// Import common js
import { loadModals, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch } from './common.js';
-import { reloadDNS, reloadDHCP } from './services.js';
-import { apiMap, fetchData } from './api.js';
+// Import services
+import { serviceReloadDNS, serviceReloadDHCP, serviceGetAliases, serviceGetAlias, serviceCreateAlias, serviceUpdateAlias, serviceDeleteAlias } from './services.js';
// -----------------------------
// State variables
const sortState = { sortDirection: {}, lastSort: null };
// -----------------------------
-// Fetch hosts from API
+// Fetch aliases from API
// -----------------------------
async function fetchAliases () {
const loader = document.getElementById("loader");
loader.style.display = "block";
// Fetch aliases
- allAliases = await fetchData(apiMap.aliases);
+ allAliases = await serviceGetAliases();
viewAliases = [...allAliases];
} catch (err) {
// Clear form first
clearAddAliasForm();
- // Fetch alias
- const res = await fetch(`/api/aliases/${id}`, {
- headers: { Accept: 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Fetch failed for alias ${id}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
try {
- data = await res.json();
- } catch {
- throw new Error(`Fetch failed for alias ${id}: Invalid JSON payload`);
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Fetch failed for alias ${id}`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
-
- // Store the ID of the alias being edited
- editingAliasId = id;
-
- // Pre-fill the form fields
- document.getElementById("aliasName").value = data.name ?? "";
- document.getElementById("aliasTarget").value = data.target ?? "";
- document.getElementById("aliasDescription").value = data.description ?? "";
- document.getElementById("aliasSSL").checked = !!data.ssl_enabled;
- if (data.visibility == 2) {
- document.getElementById("aliasVisibilityAlias").checked = true;
- } else if (data.visibility == 1){
- document.getElementById("aliasVisibilityGlobal").checked = true;
- } else {
- document.getElementById("aliasVisibilityLocal").checked = true;
+ const data = await serviceGetAlias(id);
+
+ // Store the ID of the alias being edited
+ editingAliasId = id;
+
+ // Pre-fill the form fields
+ document.getElementById("aliasName").value = data.name ?? "";
+ document.getElementById("aliasTarget").value = data.target ?? "";
+ document.getElementById("aliasDescription").value = data.description ?? "";
+ document.getElementById("aliasSSL").checked = !!data.ssl_enabled;
+ if (data.visibility == 2) {
+ document.getElementById("aliasVisibilityAlias").checked = true;
+ } else if (data.visibility == 1){
+ document.getElementById("aliasVisibilityGlobal").checked = true;
+ } else {
+ document.getElementById("aliasVisibilityLocal").checked = true;
+ }
+ } catch (err) {
+ console.error(err?.message || "Error loading alias");
+ showToast(err?.message || "Error loading alias", false);
}
}
return false;
}
- if (editingAliasId !== null) {
- // Update existing alias
- const res = await fetch(`/api/aliases/${editingAliasId}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(aliasData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Alias updated successfully', true);
- return true;
- }
+ try {
+ let result;
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
+ if (editingAliasId !== null) {
+ // Update
+ result = await serviceUpdateAlias(editingAliasId, aliasData);
+ } else {
+ // Create
+ result = await serviceCreateAlias(aliasData);
}
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : editingAliasId !== null
+ ? 'Alias updated successfully'
+ : 'Alias created successfully';
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error updating alias`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ showToast(msg, true);
- // Success
- showToast(data?.message || 'Alias updated successfully', true);
return true;
- } else {
- // Create new alias
- const res = await fetch(`/api/aliases`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(aliasData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Alias created successfully', true);
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ } catch (err) {
+ console.error(err?.message || "Error saving alias");
+ showToast(err?.message || "Error saving alias", false);
+ }
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error adding alias`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ return false;
- // Success
- showToast(data?.message || 'Alias created successfully', true);
- return true
- }
}
// -----------------------------
if (ok !== false) {
// close modal and reload aliases
closeAddAliasModal();
- await loadAliases();
+ await fetchAliases();
updateTable();
return true
}
// Get alias ID
const id = Number(el.dataset.aliasId);
if (!Number.isFinite(id)) {
- console.warn('Delete: alias id not valid for delete:', id);
showToast('Alias id not valid for delete', false);
return;
}
- // Execute delete
try {
- // Fetch data
- const res = await fetch(`/api/aliases/${id}`, {
- method: 'DELETE',
- headers: { 'Accept': 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
+ const result = await serviceDeleteAlias(id);
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error deleting alias`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : 'Alias deleted successfully';
- // Success
- showToast(data?.message || 'Alias deleted successfully', true);
+ showToast(msg, true);
// Reload aliases
await fetchAliases();
updateTable();
+
return true;
} catch (err) {
// Reload DNS
reloadDns: async () => {
try {
- const result = await reloadDNS();
+ const result = await serviceReloadDNS();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DNS reload successfully';
// Reload DHCP
reloadDhcp: async () => {
try {
- const result = await reloadDHCP();
+ const result = await serviceReloadDHCP();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DHCP reload successfully';
modalEl.addEventListener('show.bs.modal', async (ev) => {
lastTriggerEl = ev.relatedTarget; // trigger (Add o Edit)
- // check Add or Edit mode based on presence of data-host-id in the trigger element
+ // check Add or Edit mode based on presence of data-alias-id in the trigger element
const id = Number(lastTriggerEl?.dataset?.aliasId);
if (Number.isFinite(id)) {
-// -----------------------------
-// API Endpoints
-// -----------------------------
-export const apiMap = {
- hosts: {
- url: "/api/hosts",
- name: "Hosts"
- },
- aliases: {
- url: "/api/aliases",
- name: "Aliases"
- },
- leases: {
- url: "/api/dhcp/leases",
- name: "Leases"
- },
- devices: {
- url: "/api/devices",
- name: "Devices"
- }
-};
-
-// -----------------------------
-// Fetch Data functions
-// -----------------------------
-export async function fetchData(api) {
+// -------------------------------------------------------
+// API CORE - Generic request wrapper
+// -------------------------------------------------------
+export async function apiRequest(
+ url,
+ {
+ method = 'GET',
+ headers = {},
+ body = null,
+ } = {},
+ errorPrefix = 'Request error'
+) {
+ let res;
- let items = [];
+ try {
+ res = await fetch(url, {
+ method,
+ headers: {
+ 'Accept': 'application/json',
+ ...headers
+ },
+ body
+ });
+ } catch (err) {
+ throw new Error(
+ `${errorPrefix}: network error${err?.message ? `: ${err.message}` : ''}`,
+ { cause: err }
+ );
+ }
- // Fetch data
- const res = await fetch(api.url, {
- headers: { Accept: 'application/json' },
- });
+ // 204 No Content
+ if (res.status === 204) {
+ return true;
+ }
- // Check content-type to avoid parsing errors
+ // Content-Type check
const contentType = res.headers.get("content-type") || "";
if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
+ const err = new Error(
+ `${errorPrefix}: ${res.status} ${res.statusText || 'Unexpected response'}`
+ );
err.status = res.status;
throw err;
}
- // Check JSON
+ // Parse JSON
let data;
try {
data = await res.json();
- items = Array.isArray(data) ? data : (Array.isArray(data?.data) ? data.data : []);
} catch {
- throw new Error('Invalid JSON payload');
+ throw new Error(`${errorPrefix}: Invalid JSON payload`);
}
- // Check JSON errors
+ // Handle HTTP error
if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error loading ${api.name}`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
+ const serverMsg =
+ data?.detail?.message?.trim()
+ || (typeof data?.detail === 'string' ? data.detail.trim() : '')
+ || data?.message?.trim()
+ || data?.error?.message?.trim()
+ || (typeof data?.error === 'string' ? data.error.trim() : '');
+
+ const err = new Error(
+ `${errorPrefix}${serverMsg ? `: ${serverMsg}` : ''}`
+ );
err.status = res.status;
throw err;
}
- return items;
+
+ return data;
+}
+
+export function apiGet(url, errorPrefix = 'Fetch error') {
+ return apiRequest(url, { method: 'GET' }, errorPrefix);
+}
+
+export function apiPost(url, payload, errorPrefix = 'Request error') {
+ return apiRequest(
+ url,
+ {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload)
+ },
+ errorPrefix
+ );
}
// Import common js
import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch } from './common.js';
-import { reloadDNS, reloadDHCP } from './services.js';
-import { apiMap, fetchData } from './api.js';
+// Import services
+import { serviceReloadDNS, serviceReloadDHCP, serviceGetDHCPLeases, serviceGetDHCPLease, serviceDeleteDHCPLease, serviceGetDevices, serviceGetHost, serviceCreateHost, serviceUpdateHost, serviceDeleteHost } from './services.js';
// -----------------------------
// State variables
loader.style.display = "block";
// Fetch devices
- allDevices = await fetchData(apiMap.devices);
+ allDevices = await serviceGetDevices();
viewDevices = [...allDevices];
} catch (err) {
} else if (id.startsWith("d-")) {
type = 2;
} else {
- console.error("loadDevices: unknown device type:", id);
- showToast("loadDevices: unknown device type:", false);
+ console.error("updateTable: unknown device type:", id);
+ showToast("updateTable: unknown device type:", false);
}
const tr = document.createElement("tr");
// -----------------------------
async function editHost(id) {
- let fetchUrl = "";
let host = false;
// Clear form first
clearAddHostForm();
+ // host or lease
if (id !== null) {
// Static or Dynamic?
if (id.startsWith("s-")) {
// static
- fetchUrl = `/api/hosts/${id.slice(2)}`;
host = true;
} else if (id.startsWith("d-")) {
// dynamic
- fetchUrl = `/api/dhcp/leases/${id.slice(2)}`;
host = false;
} else {
throw new Error("Invalid Device ID format for edit");
throw new Error("Invalid Device ID for edit");
}
- // Fetch host
- const res = await fetch(fetchUrl, {
- headers: { Accept: 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Fetch failed for host ${id}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
try {
- data = await res.json();
- } catch {
- throw new Error(`Fetch failed for host ${id}: Invalid JSON payload`);
- }
+ let data;
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Fetch failed for host ${id}`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ if(host){
+ data = await serviceGetHost(id);
- if(host) {
- // Store the ID of the host being edited
- editingHostId = id;
- }
+ // Store the ID of the host being edited
+ editingHostId = id;
+ } else {
+ data = await serviceGetDHCPLease(id);
+ }
- // Pre-fill the form fields
- document.getElementById("hostName").value = data.name ?? "";
- document.getElementById("hostIPv4").value = data.ipv4 ?? "";
- document.getElementById("hostIPv6").value = data.ipv6 ?? "";
- document.getElementById("hostMAC").value = data.mac ?? "";
- document.getElementById("hostDescription").value = data.description ?? "";
- document.getElementById("hostSSL").checked = !!data.ssl_enabled;
- if (data.visibility == 2) {
- document.getElementById("hostVisibilityAlias").checked = true;
- } else if (data.visibility == 1){
- document.getElementById("hostVisibilityGlobal").checked = true;
- } else {
- document.getElementById("hostVisibilityLocal").checked = true;
+ // Pre-fill the form fields
+ document.getElementById("hostName").value = data.name ?? "";
+ document.getElementById("hostIPv4").value = data.ipv4 ?? "";
+ document.getElementById("hostIPv6").value = data.ipv6 ?? "";
+ document.getElementById("hostMAC").value = data.mac ?? "";
+ document.getElementById("hostDescription").value = data.description ?? "";
+ document.getElementById("hostSSL").checked = !!data.ssl_enabled;
+ if (data.visibility == 2) {
+ document.getElementById("hostVisibilityAlias").checked = true;
+ } else if (data.visibility == 1){
+ document.getElementById("hostVisibilityGlobal").checked = true;
+ } else {
+ document.getElementById("hostVisibilityLocal").checked = true;
+ }
+
+ } catch (err) {
+ console.error(err?.message || "Error loading device");
+ showToast(err?.message || "Error loading device", false);
}
}
return false;
}
- if (editingHostId !== null) {
- // Update existing host
- const res = await fetch(`/api/hosts/${editingHostId}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(hostData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Host updated successfully', true);
- return true;
- }
+ try {
+ let result;
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
+ if (editingHostId !== null) {
+ // Update
+ result = await serviceUpdateHost(editingHostId, hostData);
+ } else {
+ // Create
+ result = await serviceCreateHost(hostData);
}
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : editingHostId !== null
+ ? 'Host updated successfully'
+ : 'Host created successfully';
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error updating host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ showToast(msg, true);
- // Success
- showToast(data?.message || 'Host updated successfully', true);
return true;
- } else {
- // Create new host
- const res = await fetch(`/api/hosts`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(hostData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Host created successfully', true);
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ } catch (err) {
+ console.error(err?.message || "Error saving host");
+ showToast(err?.message || "Error saving host", false);
+ }
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error adding host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ return false;
- // Success
- showToast(data?.message || 'Host created successfully', true);
- return true
- }
}
// -----------------------------
if (ok !== false) {
// close modal and reload hosts
closeAddHostModal();
- await loadDevices();
+ await fetchDevices();
updateTable();
return true
}
// Handle delete device action
// -----------------------------
async function handleDeleteDevice(e, el) {
+
+ let host = false;
+
// Prevent default action
e.preventDefault();
// Get device ID
- const id = el.dataset.deviceId;
+ let id = el.dataset.deviceId;
if (!id) {
console.warn('Delete: device id not valid for delete:', id);
return;
}
- let deleteUrl = "";
-
- // Static or Dynamic?
- if (id.startsWith("s-")) {
- // static → delete su DB
- deleteUrl = `/api/hosts/${id.slice(2)}`
- } else if (id.startsWith("d-")) {
- // dynamic → delete su DHCP server
- deleteUrl = `/api/dhcp/leases/${id.slice(2)}`
+ // host or lease
+ if (id !== null) {
+ // Static or Dynamic?
+ if (id.startsWith("s-")) {
+ // static
+ host = true;
+ } else if (id.startsWith("d-")) {
+ // dynamic
+ host = false;
+ } else {
+ throw new Error("Invalid Device ID format for edit");
+ }
+ id = Number(id.slice(2));
} else {
- console.error("Delete: unknown device type:", id);
- showToast("Delete: unknown device type:", false);
- return;
+ throw new Error("Invalid Device ID for edit");
}
- // Execute delete
try {
- // Fetch data
- const res = await fetch(deleteUrl, {
- method: 'DELETE',
- headers: { 'Accept': 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
+ if(host){
+ const result = await serviceDeleteHost(id);
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
+ } else {
+ const result = await serviceDeleteDHCPLease(id);
}
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error deleting device`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : 'Host deleted successfully';
- // Success
- showToast(data?.message || 'Device deleted successfully', true);
+ showToast(msg, true);
// Reload devices
await fetchDevices();
updateTable();
+
return true;
} catch (err) {
// Reload DNS
reloadDns: async () => {
try {
- const result = await reloadDNS();
+ const result = await serviceReloadDNS();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DNS reload successfully';
// Reload DHCP
reloadDhcp: async () => {
try {
- const result = await reloadDHCP();
+ const result = await serviceReloadDHCP();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DHCP reload successfully';
// Import common js
import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch } from './common.js';
-import { reloadDNS, reloadDHCP } from './services.js';
-import { apiMap, fetchData } from './api.js';
+// Import services
+import { serviceReloadDNS, serviceReloadDHCP, serviceGetHosts, serviceGetHost, serviceCreateHost, serviceUpdateHost, serviceDeleteHost } from './services.js';
// -----------------------------
// State variables
loader.style.display = "block";
// Fetch hosts
- allHosts = await fetchData(apiMap.hosts);
+ allHosts = await serviceGetHosts();
viewHosts = [...allHosts];
} catch (err) {
// Clear form first
clearAddHostForm();
- // Fetch host
- const res = await fetch(`/api/hosts/${id}`, {
- headers: { Accept: 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Fetch failed for host ${id}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
try {
- data = await res.json();
- } catch {
- throw new Error(`Fetch failed for host ${id}: Invalid JSON payload`);
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Fetch failed for host ${id}`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ const data = await serviceGetHost(id);
+
+ // Store the ID of the host being edited
+ editingHostId = id;
+
+ // Pre-fill the form fields
+ document.getElementById("hostName").value = data.name ?? "";
+ document.getElementById("hostIPv4").value = data.ipv4 ?? "";
+ document.getElementById("hostIPv6").value = data.ipv6 ?? "";
+ document.getElementById("hostMAC").value = data.mac ?? "";
+ document.getElementById("hostDescription").value = data.description ?? "";
+ document.getElementById("hostSSL").checked = !!data.ssl_enabled;
+ if (data.visibility == 2) {
+ document.getElementById("hostVisibilityAlias").checked = true;
+ } else if (data.visibility == 1){
+ document.getElementById("hostVisibilityGlobal").checked = true;
+ } else {
+ document.getElementById("hostVisibilityLocal").checked = true;
+ }
- // Store the ID of the host being edited
- editingHostId = id;
-
- // Pre-fill the form fields
- document.getElementById("hostName").value = data.name ?? "";
- document.getElementById("hostIPv4").value = data.ipv4 ?? "";
- document.getElementById("hostIPv6").value = data.ipv6 ?? "";
- document.getElementById("hostMAC").value = data.mac ?? "";
- document.getElementById("hostDescription").value = data.description ?? "";
- document.getElementById("hostSSL").checked = !!data.ssl_enabled;
- if (data.visibility == 2) {
- document.getElementById("hostVisibilityAlias").checked = true;
- } else if (data.visibility == 1){
- document.getElementById("hostVisibilityGlobal").checked = true;
- } else {
- document.getElementById("hostVisibilityLocal").checked = true;
+ } catch (err) {
+ console.error(err?.message || "Error loading host");
+ showToast(err?.message || "Error loading host", false);
}
}
return false;
}
- if (editingHostId !== null) {
- // Update existing host
- const res = await fetch(`/api/hosts/${editingHostId}`, {
- method: 'PUT',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(hostData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Host updated successfully', true);
- return true;
- }
+ try {
+ let result;
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
+ if (editingHostId !== null) {
+ // Update
+ result = await serviceUpdateHost(editingHostId, hostData);
+ } else {
+ // Create
+ result = await serviceCreateHost(hostData);
}
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : editingHostId !== null
+ ? 'Host updated successfully'
+ : 'Host created successfully';
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error updating host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ showToast(msg, true);
- // Success
- showToast(data?.message || 'Host updated successfully', true);
return true;
- } else {
- // Create new host
- const res = await fetch(`/api/hosts`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(hostData)
- });
-
- // Success without JSON
- if (res.status === 204) {
- showToast('Host created successfully', true);
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ } catch (err) {
+ console.error(err?.message || "Error saving host");
+ showToast(err?.message || "Error saving host", false);
+ }
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error adding host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ return false;
- // Success
- showToast(data?.message || 'Host created successfully', true);
- return true
- }
}
// -----------------------------
// Get host ID
const id = Number(el.dataset.hostId);
if (!Number.isFinite(id)) {
- console.warn('Delete: host id not valid for delete:', id);
showToast('Host id not valid for delete', false);
return;
}
- // Execute delete
try {
- // Fetch data
- const res = await fetch(`/api/hosts/${id}`, {
- method: 'DELETE',
- headers: { 'Accept': 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ const result = await serviceDeleteHost(id);
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error deleting host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : 'Host deleted successfully';
- // Success
- showToast(data?.message || 'Host deleted successfully', true);
+ showToast(msg, true);
// Reload hosts
await fetchHosts();
updateTable();
+
return true;
} catch (err) {
// Reload DNS
reloadDns: async () => {
try {
- const result = await reloadDNS();
+ const result = await serviceReloadDNS();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DNS reload successfully';
// Reload DHCP
reloadDhcp: async () => {
try {
- const result = await reloadDHCP();
+ const result = await serviceReloadDHCP();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DHCP reload successfully';
// IMPORT
// -------------------------------------------------------
import { loadModals, showToast } from './common.js';
-import { apiCheck, reloadDNS, reloadDHCP, CreateBackup, fetchBackups, RestoreBackup, deleteBackup, checkHealth } from './services.js';
+import { serviceCheckAbount, serviceCheckHealth , serviceReloadDNS, serviceReloadDHCP, serviceBackupCreate, serviceBackupList, serviceBackupRestore, deleteBackup} from './services.js';
// -------------------------------------------------------
// BACKUP MODAL OPEN/CLOSE
}
try {
- const data = await fetchBackups();
+ const data = await serviceBackupList();
renderBackupList(data);
} catch (err) {
console.error(err);
}
// -------------------------------------------------------
-// HEALTH MODAL OPEN/CLOSE + RENDER (usa checkHealth())
+// HEALTH MODAL OPEN/CLOSE + RENDER
// -------------------------------------------------------
function openHealthModal() {
const modal = document.getElementById('healthModal');
}
if (updatedAtEl) updatedAtEl.textContent = '';
- // Usa checkHealth() per ottenere il payload health
+ // Usa serviceCheckHealth() per ottenere il payload health
Promise.resolve()
- .then(() => checkHealth())
+ .then(() => serviceCheckHealth())
.then((data) => {
- // Se checkHealth ritorna true o {message}, non abbiamo i dettagli: mostra un messaggio
+ // Se serviceCheckHealth ritorna true o {message}, non abbiamo i dettagli: mostra un messaggio
const isDetailed =
data && typeof data === 'object' &&
('status' in data || 'latency_ms' in data || 'database' in data);
label.textContent = ' Exporting…';
try {
- const result = await CreateBackup();
+ const result = await serviceBackupCreate();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'Backup completed successfully';
label.textContent = ' Restoring…';
try {
- const result = await RestoreBackup(id);
+ const result = await serviceBackupRestore(id);
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'Restore completed successfully';
showToast(msg, true);
// reload list
- const data = await fetchBackups();
+ const data = await serviceBackupList();
renderBackupList(data);
} catch (err) {
// Reload DNS
reloadDns: async () => {
try {
- const result = await reloadDNS();
+ const result = await serviceReloadDNS();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DNS reload successfully';
// Reload DHCP
reloadDhcp: async () => {
try {
- const result = await reloadDHCP();
+ const result = await serviceReloadDHCP();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DHCP reload successfully';
},
// Check API status
apiCheck: async () => {
- const result = await apiCheck();
+ const result = await serviceCheckAbount();
if(result) {
showToast('API status updated succesfully', true);
} else {
// Periodic API Check
// -------------------------------------------------------
async function periodicTest() {
- await apiCheck();
+ await serviceCheckAbount();
setTimeout(periodicTest, 10000);
}
// Import common js
import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch } from './common.js';
-import { reloadDNS, reloadDHCP } from './services.js';
-import { apiMap, fetchData } from './api.js';
+// Import services
+import { serviceReloadDNS, serviceReloadDHCP, serviceGetDHCPLeases, serviceDeleteDHCPLease, serviceGetDHCPLease, serviceCreateHost} from './services.js';
// -----------------------------
// State variables
loader.style.display = "block";
// Fetch leases
- allLeases = await fetchData(apiMap.leases);
+ allLeases = await serviceGetDHCPLeases();
viewLeases = [...allLeases];
} catch (err) {
// Clear form first
clearAddHostForm();
- // Fetch lease
- const res = await fetch(`/api/dhcp/leases/${id}`, {
- headers: { Accept: 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Fetch failed for lease ${id}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data;
try {
- data = await res.json();
- } catch {
- throw new Error(`Fetch failed for lease ${id}: Invalid JSON payload`);
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Fetch failed for lease ${id}`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
+ const data = await serviceGetDHCPLease(id);
+
+ // Pre-fill the form fields
+ document.getElementById("hostName").value = data.name ?? "";
+ document.getElementById("hostIPv4").value = data.ipv4 ?? "";
+ document.getElementById("hostIPv6").value = data.ipv6 ?? "";
+ document.getElementById("hostMAC").value = data.mac ?? "";
+ document.getElementById("hostDescription").value = data.description ?? "";
+ document.getElementById("hostSSL").checked = !!data.ssl_enabled;
+ if (data.visibility == 2) {
+ document.getElementById("hostVisibilityAlias").checked = true;
+ } else if (data.visibility == 1){
+ document.getElementById("hostVisibilityGlobal").checked = true;
+ } else {
+ document.getElementById("hostVisibilityLocal").checked = true;
+ }
- // Pre-fill the form fields
- document.getElementById("hostName").value = data.name ?? "";
- document.getElementById("hostIPv4").value = data.ipv4 ?? "";
- document.getElementById("hostIPv6").value = data.ipv6 ?? "";
- document.getElementById("hostMAC").value = data.mac ?? "";
- document.getElementById("hostDescription").value = data.description ?? "";
- document.getElementById("hostSSL").checked = !!data.ssl_enabled;
- if (data.visibility == 2) {
- document.getElementById("hostVisibilityAlias").checked = true;
- } else if (data.visibility == 1){
- document.getElementById("hostVisibilityGlobal").checked = true;
- } else {
- document.getElementById("hostVisibilityLocal").checked = true;
+ } catch (err) {
+ console.error(err?.message || "Error loading lease");
+ showToast(err?.message || "Error loading lease", false);
}
}
return false;
}
- // Create new host
- const res = await fetch(`/api/hosts`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify(hostData)
- });
+ try {
+ const result = await serviceCreateHost(hostData);
- // Success without JSON
- if (res.status === 204) {
- showToast('Host created successfully', true);
- return true;
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : 'Host created successfully';
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
+ showToast(msg, true);
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ return true;
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error adding host`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
+ } catch (err) {
+ console.error(err?.message || "Error saving host");
+ showToast(err?.message || "Error saving host", false);
}
- // Success
- showToast(data?.message || 'Host created successfully', true);
- return true
+ return false;
+
}
+
// -----------------------------
// Prepare add host form
// -----------------------------
// Get lease ID
const id = Number(el.dataset.leaseId);
if (!Number.isFinite(id)) {
- console.warn('Delete: lease id not valid for delete:', id);
showToast('Lease id not valid for delete', false);
return;
}
- // Execute delete
try {
- // Fetch data
- const res = await fetch(`/api/dhcp/leases/${id}`, {
- method: 'DELETE',
- headers: { 'Accept': 'application/json' },
- });
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`${res.status}: ${res.statusText}`);
- err.status = res.status;
- throw err;
- }
+ const result = await serviceDeleteDHCPLease(id);
- // Check JSON
- let data;
- try {
- data = await res.json();
- } catch {
- throw new Error('Invalid JSON payload');
- }
+ const msg = (typeof result === 'object' && result?.message)
+ ? result.message
+ : 'Lease deleted successfully';
- // Check JSON errors
- if (!res.ok) {
- const serverMsg = data?.detail?.message?.trim();
- const base = `Error deleting lease`;
- const err = new Error(serverMsg ? `${base}: ${serverMsg}` : base);
- err.status = res.status;
- throw err;
- }
-
- // Success
- showToast(data?.message || 'Lease deleted successfully', true);
+ showToast(msg, true);
// Reload leases
await fetchLeases();
updateTable();
+
return true;
} catch (err) {
// Reload DNS
reloadDns: async () => {
try {
- const result = await reloadDNS();
+ const result = await serviceReloadDNS();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DNS reload successfully';
// Reload DHCP
reloadDhcp: async () => {
try {
- const result = await reloadDHCP();
+ const result = await serviceReloadDHCP();
const msg = (typeof result === 'object' && result?.message)
? result.message
: 'DHCP reload successfully';
try {
await addHost(id);
} catch (err) {
- showToast(err?.message || "Error loading host for edit", false);
+ showToast(err?.message || "Error loading host", false);
// Close modal
modalEl.addEventListener('shown.bs.modal', () => {
closeAddHostModal(lastTriggerEl);
+// import api
+import { apiRequest, apiGet, apiPost } from './api.js';
+
// -------------------------------------------------------
-// API Health Check
+// Check Abount
// -------------------------------------------------------
-export async function apiCheck() {
+export async function serviceCheckAbount() {
const pill = document.getElementById('api-pill');
if (!pill) return;
}
}
+// -------------------------------------------------------
+// Check Health
+// -------------------------------------------------------
+export async function serviceCheckHealth() {
+ return await apiGet("/api/health", "Error performing health check");
+}
+
// -----------------------------
// Reload DNS
// -----------------------------
-export async function reloadDNS() {
- let res;
- try {
- // Fetch data
- res = await fetch('/api/dns/reload', {
- method: 'POST',
- headers: { 'Accept': 'application/json' },
- });
- } catch (err) {
- const msg = 'Network error while reloading DNS' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
-
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
+export async function serviceReloadDNS() {
+ const data = await apiPost(
+ "/api/dns/reload",
+ null,
+ "Error reloading DNS"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error reloading DNS: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
+// -----------------------------
+// Reload DHCP action
+// -----------------------------
+export async function serviceReloadDHCP() {
+ const data = await apiPost(
+ "/api/dhcp/reload",
+ null,
+ "Error reloading DHCP"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error reloading DNS: Invalid JSON payload');
- }
+// -----------------------------
+// Get DHCP Leaseses
+// -----------------------------
+export async function serviceGetDHCPLeases() {
+ return await apiGet("/api/dhcp/leases", "Error loading DHCP leases");
+}
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error reloading DNS' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
- }
+// -----------------------------
+// Get a single DHCP Leases
+// -----------------------------
+export async function serviceGetDHCPLease(id) {
+ return await apiRequest(
+ `/api/dhcp/leases/${id}`,
+ { method: "GET" },
+ `Error loading host ${id}`
+ );
+}
- if (res.ok && (data.status === 'success' || data.code === 'DNS_RELOAD_OK')) {
- // Success
- return data?.message ? { message: data.message } : true;
- } else {
- // Failed with JSON error message
- return data?.message ? { message: data.message } : false;
- }
+// -----------------------------
+// Delete Hosts
+// -----------------------------
+export async function serviceDeleteDHCPLease(id) {
+ const data = await apiRequest(
+ `/api/dhcp/leases/${id}`,
+ { method: "DELETE" },
+ "Error deleting host"
+ );
+
+ return data?.message ? { message: data.message } : true;
}
// -----------------------------
-// Reload DHCP action
+// Get Hosts
// -----------------------------
-export async function reloadDHCP() {
- let res;
- try {
- // Fetch data
- res = await fetch(`/api/dhcp/reload`, {
- method: 'POST',
- headers: { 'Accept': 'application/json' },
- });
- } catch (err) {
- const msg = 'Network error while reloading DHCP' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
+export async function serviceGetHosts() {
+ return await apiGet("/api/hosts", "Error loading hosts");
+}
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
+// -----------------------------
+// Get a single host
+// -----------------------------
+export async function serviceGetHost(id) {
+ return await apiRequest(
+ `/api/hosts/${id}`,
+ { method: "GET" },
+ `Error loading host ${id}`
+ );
+}
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error reloading DHCP: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
+// -----------------------------
+// Create a new host
+// -----------------------------
+export async function serviceCreateHost(hostData) {
+ const data = await apiRequest(
+ "/api/hosts",
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(hostData)
+ },
+ "Error creating host"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error reloading DHCP: Invalid JSON payload');
- }
+// -----------------------------
+// Update an host
+// -----------------------------
+export async function serviceUpdateHost(id, hostData) {
+ const data = await apiRequest(
+ `/api/hosts/${id}`,
+ {
+ method: "PUT",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(hostData)
+ },
+ "Error updating host"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error reloading DHCP' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
- }
+// -----------------------------
+// Delete Hosts
+// -----------------------------
+export async function serviceDeleteHost(id) {
+ const data = await apiRequest(
+ `/api/hosts/${id}`,
+ { method: "DELETE" },
+ "Error deleting host"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- if (res.ok && (data.status === 'success' || data.code === 'DHCP_RELOAD_OK')) {
- // Success
- return data?.message ? { message: data.message } : true;
- } else {
- // Failed with JSON error message
- return data?.message ? { message: data.message } : false;
- }
+// -----------------------------
+// Get Aliases
+// -----------------------------
+export async function serviceGetAliases() {
+ return await apiGet("/api/aliases", "Error loading aliases");
}
-// -------------------------------------------------------
-// Create a Backup
-// -------------------------------------------------------
-export async function CreateBackup() {
- let res;
+// -----------------------------
+// Get a single alias
+// -----------------------------
+export async function serviceGetAlias(id) {
+ return await apiRequest(
+ `/api/aliases/${id}`,
+ { method: "GET" },
+ `Error loading alias ${id}`
+ );
+}
- try {
- // Fetch data
- res = await fetch(`/api/backup/create`, {
- method: 'POST',
- headers: { 'Accept': 'application/json' },
- });
-
- } catch (err) {
- const msg = 'Network error while performing backup' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
+// -----------------------------
+// Create a new alias
+// -----------------------------
+export async function serviceCreateAlias(aliasData) {
+ const data = await apiRequest(
+ "/api/aliases",
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(aliasData)
+ },
+ "Error creating alias"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
+// -----------------------------
+// Update an alias
+// -----------------------------
+export async function serviceUpdateAlias(id, aliasData) {
+ const data = await apiRequest(
+ `/api/aliases/${id}`,
+ {
+ method: "PUT",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(aliasData)
+ },
+ "Error updating alias"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error performing backup: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
+// -----------------------------
+// Delete Alias
+// -----------------------------
+export async function serviceDeleteAlias(id) {
+ const data = await apiRequest(
+ `/api/aliases/${id}`,
+ { method: "DELETE" },
+ "Error deleting alias"
+ );
+
+ return data?.message ? { message: data.message } : true;
+}
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error performing backup: Invalid JSON payload');
- }
+// -----------------------------
+// Get Devices
+// -----------------------------
+export async function serviceGetDevices() {
+ return await apiGet("/api/devices", "Error loading Devices");
+}
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error performing backup' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
+// -------------------------------------------------------
+// Create a Backup
+// -------------------------------------------------------
+export async function serviceBackupCreate() {
+ const data = await apiPost(
+ "/api/backup/create",
+ null,
+ "Error performing backup"
+ );
+
+ if (data.status === 'success') {
+ return data?.message ? { message: data.message } : true;
}
- if (res.ok && (data.status === 'success' || data.code === 'BACKUP_CREATE_OK')) {
- // Success
- return data?.message ? { message: data.message } : true;
- } else if (res.ok && (data.status === 'partial' || data.code === 'BACKUP_PARTIAL')) {
- // Partial success
+ if (data.status === 'partial') {
return data?.message
? { message: data.message, partial: true }
: { partial: true };
- } else {
- // Failed with JSON error message
- return data?.message ? { message: data.message } : false;
}
+
+ return false;
}
// -------------------------------------------------------
// Fetch Backups list
// -------------------------------------------------------
-export async function fetchBackups() {
- let res;
-
- try {
- // Fetch data
- res = await fetch(`/api/backup/list`, {
- method: 'GET',
- headers: { 'Accept': 'application/json' },
- });
-
- } catch (err) {
- const msg = 'Network error while fetching backups' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
-
- // Success without JSON
- if (res.status === 204) {
- return [];
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error fetching backups: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error fetching backups: Invalid JSON payload');
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error fetching backups' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
- }
-
- return (data ?? []);
+export async function serviceBackupList() {
+ return await apiGet("/api/backup/list", "Error fetching backups");
}
// -------------------------------------------------------
// Restore a Backup
// -------------------------------------------------------
-export async function RestoreBackup(id) {
- let res;
-
- try {
- // Fetch data
- res = await fetch(`/api/backup/restore`, {
- method: 'POST',
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ backup_id: id })
- });
-
- } catch (err) {
- const msg = 'Network error while performing restore' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
-
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error performing restore: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error performing restore: Invalid JSON payload');
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error performing restore' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
+export async function serviceBackupRestore(id) {
+ const data = await apiPost(
+ "/api/backup/restore",
+ { backup_id: id },
+ "Error performing restore"
+ );
+
+ if (data.status === 'success') {
+ return data?.message ? { message: data.message } : true;
}
- if (res.ok && (data.status === 'success' || data.code === 'BACKUP_RESTORE_OK')) {
- // Success
- return data?.message ? { message: data.message } : true;
- } else if (res.ok && (data.status === 'partial' || data.code === 'BACKUP_RESTORE_PARTIAL')) {
- // Partial success
+ if (data.status === 'partial') {
return data?.message
? { message: data.message, partial: true }
: { partial: true };
- } else {
- // Failed with JSON error message
- return data?.message ? { message: data.message } : false;
}
+
+ return false;
}
// -------------------------------------------------------
// Delete a Backup
// -------------------------------------------------------
export async function deleteBackup(id) {
- let res;
-
- try {
- // Fetch data
- res = await fetch(`/api/backup/delete`, {
- method: 'POST',
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ backup_id: id })
- });
-
- } catch (err) {
- const msg = 'Network error while performing delete' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
-
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error performing delete: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error performing delete: Invalid JSON payload');
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error performing delete' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
- }
-
- if (res.ok && (data.status === 'success' || data.code === 'BACKUP_DELETEE_OK')) {
- // Success
- return data?.message ? { message: data.message } : true;
- } else {
- // Failed with JSON error message
- return data?.message ? { message: data.message } : false;
- }
-}
-
-// -------------------------------------------------------
-// Check Health
-// -------------------------------------------------------
-export async function checkHealth() {
- let res;
-
- try {
- // Fetch data
- res = await fetch(`/api/health`, {
- method: 'GET',
- headers: { 'Accept': 'application/json' }
- });
-
- } catch (err) {
- const msg = 'Network error while performing health check' + (err?.message ? `: ${err.message}` : '');
- throw new Error(msg, { cause: err });
- }
-
- // Success without JSON
- if (res.status === 204) {
- return true;
- }
-
- // Check content-type to avoid parsing errors
- const contentType = res.headers.get("content-type") || "";
- if (!contentType.includes("application/json")) {
- const err = new Error(`Error performing health check: ${res.status}: ${res.statusText || 'Unexpected response'}`);
- err.status = res.status;
- throw err;
- }
-
- // Check JSON
- let data = {};
- try {
- data = await res.json();
- } catch {
- throw new Error('Error performing health check: Invalid JSON payload');
- }
-
- // Check JSON errors
- if (!res.ok) {
- const serverMsg =
- data?.detail?.message?.trim()
- || (typeof data?.detail === 'string' ? data.detail.trim() : '')
- || data?.message?.trim()
- || data?.error?.message?.trim()
- || (typeof data?.error === 'string' ? data.error.trim() : '');
- const err = new Error('Error performing health check' + (serverMsg ? `: ${serverMsg}` : ''));
- err.status = res.status;
- throw err;
- }
+ const data = await apiPost(
+ "/api/backup/delete",
+ { backup_id: id },
+ "Error performing delete"
+ );
- return (data ?? []);
+ return data?.message ? { message: data.message } : true;
}
<div class="modal-footer modal-buttons">
<button type="button" class="btn btn-outline-primary" data-action="closeHealthModal">
- <span class="label">Close</span>
+ <i class="bi bi-x-circle me-1"></i><span class="label">Close</span>
</button>
</div>
</div>