<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
<!-- Spacer -->
<div class="col d-none d-md-block"></div>
- <!-- Search -->
- <div class="col-12 col-md-auto">
+ <!-- Search Desktop -->
+ <div class="col-12 col-md-auto d-none d-md-block">
<div class="search-wrapper">
<input
type="text"
id="searchInput"
placeholder="Search..."
class="form-control form-control-sm placeholder-italic"
- aria-label="Search alias"
- >
+ aria-label="Search alias">
</div>
</div>
<!-- Bottoni -->
<div class="col-12 col-md-auto d-flex align-items-center gap-2 flex-wrap">
+ <!-- Search Mobile -->
+ <div class="col-auto d-md-none">
+ <button
+ class="btn btn-primary d-flex align-items-center gap-2 px-3"
+ data-bs-toggle="collapse" data-bs-target="#mobileSearch"
+ aria-expanded="false" aria-controls="mobileSearch">
+ <i class="bi bi-search"></i>
+ </button>
+ </div>
+
+ <!-- Separator -->
+ <div class="vr mx-2"></div>
+
<!-- Add alias -->
<button
class="btn btn-primary d-flex align-items-center gap-2 px-3"
</button>
</div>
</div>
+
+ <!-- Search collapsabile -->
+ <div class="collapse mt-2 d-md-none" id="mobileSearch">
+ <input
+ type="text"
+ id="searchInputMobile"
+ placeholder="Search..."
+ class="form-control form-control-sm placeholder-italic"
+ aria-label="Search alias">
+ </div>
</div>
</section>
<table id="dataTable" class="table table-bordered table-hover align-middle">
<thead class="table-light">
<tr>
- <th data-type="string" data-sortable="true" data-sort="0">Alias <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="1">Target <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="2">Description<span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="3">Options <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false" data-sort="4">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="string" data-sortable="true" data-sort="0">
+ Alias <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="1">
+ Target <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="2">
+ Description <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="3" class="text-center text-nowrap">
+ Options <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false" class="text-center text-nowrap">
+ Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ </th>
</tr>
</thead>
<tbody></tbody>
<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
<!-- Spacer -->
<div class="col d-none d-md-block"></div>
- <!-- Search -->
- <div class="col-12 col-md-auto">
+ <!-- Search Desktop -->
+ <div class="col-12 col-md-auto d-none d-md-block">
<div class="search-wrapper">
<input
type="text"
id="searchInput"
placeholder="Search..."
class="form-control form-control-sm placeholder-italic"
- aria-label="Search hosts"
- >
+ aria-label="Search device">
</div>
</div>
<!-- Bottoni -->
<div class="col-12 col-md-auto d-flex align-items-center gap-2 flex-wrap">
+ <!-- Search Mobile -->
+ <div class="col-auto d-md-none">
+ <button
+ class="btn btn-primary d-flex align-items-center gap-2 px-3"
+ data-bs-toggle="collapse" data-bs-target="#mobileSearch"
+ aria-expanded="false" aria-controls="mobileSearch">
+ <i class="bi bi-search"></i>
+ </button>
+ </div>
+
+ <!-- Separator -->
+ <div class="vr mx-2"></div>
+
<!-- Add host -->
<button
class="btn btn-primary d-flex align-items-center gap-2 px-3"
</button>
</div>
</div>
+
+ <!-- Search collapsabile -->
+ <div class="collapse mt-2 d-md-none" id="mobileSearch">
+ <input
+ type="text"
+ id="searchInputMobile"
+ placeholder="Search..."
+ class="form-control form-control-sm placeholder-italic"
+ aria-label="Search device">
+ </div>
</div>
</section>
<table id="dataTable" class="table table-bordered table-hover align-middle">
<thead class="table-light">
<tr>
- <th data-type="ipv4" data-sortable="true" data-sort="0">IP Address <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="mac" data-sortable="true" data-sort="1">MAC Address<span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="2">Hostname <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="3">Description<span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="4">State <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="5">Active <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false" data-sort="6">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="ipv4" data-sortable="true" data-sort="0">
+ IP Address <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="mac" data-sortable="true" data-sort="1">
+ MAC Address <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="2">
+ Hostname <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="3">
+ Description <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="4" class="text-center text-nowrap">
+ State <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="5" class="text-center text-nowrap">
+ Active <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false" class="text-center text-nowrap">
+ Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ </th>
</tr>
</thead>
<tbody></tbody>
<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
<!-- Spacer -->
<div class="col d-none d-md-block"></div>
- <!-- Search -->
- <div class="col-12 col-md-auto">
+ <!-- Search Desktop -->
+ <div class="col-12 col-md-auto d-none d-md-block">
<div class="search-wrapper">
<input
type="text"
id="searchInput"
placeholder="Search..."
class="form-control form-control-sm placeholder-italic"
- aria-label="Search hosts"
- >
+ aria-label="Search hosts">
</div>
</div>
<!-- Bottoni -->
<div class="col-12 col-md-auto d-flex align-items-center gap-2 flex-wrap">
+ <!-- Search Mobile -->
+ <div class="col-auto d-md-none">
+ <button
+ class="btn btn-primary d-flex align-items-center gap-2 px-3"
+ data-bs-toggle="collapse" data-bs-target="#mobileSearch"
+ aria-expanded="false" aria-controls="mobileSearch">
+ <i class="bi bi-search"></i>
+ </button>
+ </div>
+
+ <!-- Separator -->
+ <div class="vr mx-2"></div>
+
<!-- Add host -->
<button
class="btn btn-primary d-flex align-items-center gap-2 px-3"
</button>
</div>
</div>
+
+ <!-- Search collapsabile -->
+ <div class="collapse mt-2 d-md-none" id="mobileSearch">
+ <input
+ type="text"
+ id="searchInputMobile"
+ placeholder="Search..."
+ class="form-control form-control-sm placeholder-italic"
+ aria-label="Search hosts">
+ </div>
</div>
</section>
<table id="dataTable" class="table table-bordered table-hover align-middle">
<thead class="table-light">
<tr>
- <th data-type="string" data-sortable="true" data-sort="0">Hostname <span class="sort-arrow"></span></th>
- <th data-type="ipv4" data-sortable="true" data-sort="1">IP Address <span class="sort-arrow"></span></th>
- <th data-type="mac" data-sortable="true" data-sort="2">MAC Address <span class="sort-arrow"></span></th>
- <th data-type="string" data-sortable="true" data-sort="3">Description <span class="sort-arrow"></span></th>
- <th data-type="string" data-sortable="true" data-sort="4">Options <span class="sort-arrow"></span></th>
- <th data-type="string" data-sortable="false" data-sort="5">Actions <span class="sort-arrow"></span></th>
+ <th data-type="string" data-sortable="true" data-sort="0">
+ Hostname <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="ipv4" data-sortable="true" data-sort="1">
+ IP Address <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="mac" data-sortable="true" data-sort="2">
+ MAC Address <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="3">
+ Description <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="4" class="text-center text-nowrap">
+ Options <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false" class="text-center text-nowrap">
+ Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ </th>
</tr>
</thead>
<tbody></tbody>
// Import common js
-import { loadModals, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch, handleReload } from './common.js';
+import { loadModals, showToast, sortTable, initSortableTable, resetSorting, handleSearch, filterTable, clearSearch, handleReload } from './common.js';
// Import services
import { serviceReloadDNS, serviceReloadDHCP, serviceGetAliases, serviceGetAlias, serviceCreateAlias, serviceUpdateAlias, serviceDeleteAlias } from './services.js';
tableWrapper.classList.remove("d-none");
// apply current search filter
- const searchInput = document.getElementById("searchInput");
- if (searchInput) {
- const term = searchInput.value.trim().toLowerCase();
- if (term) {
- filterTable(term);
- }
+ const term =
+ document.getElementById('searchInput')?.value ||
+ document.getElementById('searchInputMobile')?.value;
+ if (term) {
+ handleSearch(term);
}
}
// SEARCH
// -----------------------------
function initSearch() {
- // search bar
- const input = document.getElementById("searchInput");
- if (!input) return;
-
- // clean input on load
- input.value = "";
- // live filter for each keystroke
- input.addEventListener("input", (e) => {
- const term = e.target.value.trim().toLowerCase();
- filterTable(term);
+
+ ["searchInput", "searchInputMobile"].forEach(id => {
+
+ const input = document.getElementById(id);
+
+ if (!input) return;
+
+ // clean input on load
+ input.value = "";
+
+ // live filter
+ input.addEventListener("input", (e) => {
+ handleSearch(e.target.value);
+ });
});
}
const tag = (e.target.tagName || "").toLowerCase();
const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
- const isSearchInput = e.target.id === "searchInput";
+ const isSearchInput =
+ e.target.id === "searchInput" || e.target.id === "searchInputMobile";
// ESC should clear search and reset sorting only if not focused on a typing field, or if focused on the search input (to allow quick clearing of search)
if (!isTypingField || isSearchInput) {
ths.forEach(th => th.setAttribute("aria-sort", "none"));
}
+/**
+ * search handler
+ */
+export function handleSearch(value, callback) {
+ const desktopSearch = document.getElementById('searchInput');
+ const mobileSearch = document.getElementById('searchInputMobile');
+
+ // sync valori
+ desktopSearch.value = value;
+ mobileSearch.value = value;
+
+ const term = value.trim().toLowerCase();
+ callback(term);
+}
+
/**
* Live filter: mostra solo le righe che contengono il testo di ricerca (case-insensitive)
*/
* Clear search input and reset table filter
*/
export function clearSearch() {
- const input = document.getElementById("searchInput");
- if (input) {
- input.value = "";
- input.blur();
+ const desktopSearch = document.getElementById("searchInput");
+ if (desktopSearch) {
+ desktopSearch.value = "";
+ desktopSearch.blur();
+ }
+ const mobileSearch = document.getElementById("searchInputMobile");
+ if (mobileSearch) {
+ mobileSearch.value = "";
+ mobileSearch.blur();
}
}
// Import common js
-import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch, handleReload } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, handleSearch, filterTable, clearSearch, handleReload } from './common.js';
// Import services
import { serviceReloadDNS, serviceReloadDHCP, serviceGetDHCPLeases, serviceGetDHCPLease, serviceDeleteDHCPLease, serviceGetDevices, serviceGetHost, serviceCreateHost, serviceUpdateHost, serviceDeleteHost } from './services.js';
tableWrapper.classList.remove("d-none");
// apply current search filter
- const searchInput = document.getElementById("searchInput");
- if (searchInput) {
- const term = searchInput.value.trim().toLowerCase();
- if (term) {
- filterTable(term);
- }
+ const term =
+ document.getElementById('searchInput')?.value ||
+ document.getElementById('searchInputMobile')?.value;
+ if (term) {
+ handleSearch(term, filterTable);
}
}
// SEARCH
// -----------------------------
function initSearch() {
- // search bar
- const input = document.getElementById("searchInput");
- if (!input) return;
-
- // clean input on load
- input.value = "";
- // live filter for each keystroke
- input.addEventListener("input", (e) => {
- const term = e.target.value.trim().toLowerCase();
- filterTable(term);
+
+ ["searchInput", "searchInputMobile"].forEach(id => {
+
+ const input = document.getElementById(id);
+
+ if (!input) return;
+
+ // clean input on load
+ input.value = "";
+
+ // live filter
+ input.addEventListener("input", (e) => {
+ handleSearch(e.target.value, filterTable);
+ });
});
}
const tag = (e.target.tagName || "").toLowerCase();
const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
- const isSearchInput = e.target.id === "searchInput";
+ const isSearchInput =
+ e.target.id === "searchInput" || e.target.id === "searchInputMobile";
// ESC should clear search and reset sorting only if not focused on a typing field, or if focused on the search input (to allow quick clearing of search)
if (!isTypingField || isSearchInput) {
// Import common js
-import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch, handleReload } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, handleSearch, filterTable, clearSearch, handleReload } from './common.js';
// Import services
import { serviceReloadDNS, serviceReloadDHCP, serviceGetHosts, serviceGetHost, serviceCreateHost, serviceUpdateHost, serviceDeleteHost } from './services.js';
tableWrapper.classList.remove("d-none");
// apply current search filter
- const searchInput = document.getElementById("searchInput");
- if (searchInput) {
- const term = searchInput.value.trim().toLowerCase();
- if (term) {
- filterTable(term);
- }
+ const term =
+ document.getElementById('searchInput')?.value ||
+ document.getElementById('searchInputMobile')?.value;
+ if (term) {
+ handleSearch(term, filterTable);
}
}
// SEARCH
// -----------------------------
function initSearch() {
- // search bar
- const input = document.getElementById("searchInput");
- if (!input) return;
-
- // clean input on load
- input.value = "";
- // live filter for each keystroke
- input.addEventListener("input", (e) => {
- const term = e.target.value.trim().toLowerCase();
- filterTable(term);
+
+ ["searchInput", "searchInputMobile"].forEach(id => {
+
+ const input = document.getElementById(id);
+
+ if (!input) return;
+
+ // clean input on load
+ input.value = "";
+
+ // live filter
+ input.addEventListener("input", (e) => {
+ handleSearch(e.target.value, filterTable);
+ });
});
}
const tag = (e.target.tagName || "").toLowerCase();
const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
- const isSearchInput = e.target.id === "searchInput";
+ const isSearchInput =
+ e.target.id === "searchInput" || e.target.id === "searchInputMobile";
// ESC should clear search and reset sorting only if not focused on a typing field, or if focused on the search input (to allow quick clearing of search)
if (!isTypingField || isSearchInput) {
// Import common js
-import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, filterTable, clearSearch, handleReload } from './common.js';
+import { loadModals, isValidIPv4, isValidIPv6, isValidMAC, showToast, sortTable, initSortableTable, resetSorting, handleSearch, filterTable, clearSearch, handleReload } from './common.js';
// Import services
import { serviceReloadDNS, serviceReloadDHCP, serviceGetDHCPLeases, serviceDeleteDHCPLease, serviceGetDHCPLease, serviceCreateHost} from './services.js';
tableWrapper.classList.remove("d-none");
// apply current search filter
- const searchInput = document.getElementById("searchInput");
- if (searchInput) {
- const term = searchInput.value.trim().toLowerCase();
- if (term) {
- filterTable(term);
- }
+ const term =
+ document.getElementById('searchInput')?.value ||
+ document.getElementById('searchInputMobile')?.value;
+ if (term) {
+ handleSearch(term, filterTable);
}
}
// SEARCH
// -----------------------------
function initSearch() {
- // search bar
- const input = document.getElementById("searchInput");
- if (!input) return;
-
- // clean input on load
- input.value = "";
- // live filter for each keystroke
- input.addEventListener("input", (e) => {
- const term = e.target.value.trim().toLowerCase();
- filterTable(term);
+
+ ["searchInput", "searchInputMobile"].forEach(id => {
+
+ const input = document.getElementById(id);
+
+ if (!input) return;
+
+ // clean input on load
+ input.value = "";
+
+ // live filter
+ input.addEventListener("input", (e) => {
+ handleSearch(e.target.value, filterTable);
+ });
});
}
const tag = (e.target.tagName || "").toLowerCase();
const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
- const isSearchInput = e.target.id === "searchInput";
+ const isSearchInput =
+ e.target.id === "searchInput" || e.target.id === "searchInputMobile";
// ESC should clear search and reset sorting only if not focused on a typing field, or if focused on the search input (to allow quick clearing of search)
if (!isTypingField || isSearchInput) {
// Import common js
-import { loadModals, showToast, clearSearch, showConfirmModal, handleReload } from './common.js';
+import { loadModals, showToast, handleSearch, clearSearch, showConfirmModal, handleReload } from './common.js';
// Import services
import { serviceGetConfigs, serviceGetConfig, serviceUpdateConfig, serviceResetConfig, serviceRestartApp, serviceIsAlive } from './services.js';
// -----------------------------
// Update table with current configs
// -----------------------------
-function updateTable () {
+function updateTable (filter = null) {
const loader = document.getElementById("loader");
const tableWrapper = document.getElementById("tableWrapper");
- const searchInput = document.getElementById("searchInput");
- const term = searchInput?.value?.trim().toLowerCase();
- const hasSearch = !!term;
+ const hasSearch = !!filter;
const expandBtn = document.getElementById("expandAllBtn");
const collapseBtn = document.getElementById("collapseAllBtn");
let rows = grouped[group];
- if (term) {
+ if (filter) {
rows = rows.filter(c => {
return (
- (c.key ?? "").toString().toLowerCase().includes(term) ||
- (c.value ?? "").toString().toLowerCase().includes(term) ||
- (c.description ?? "").toString().toLowerCase().includes(term)
+ (c.key ?? "").toString().toLowerCase().includes(filter) ||
+ (c.value ?? "").toString().toLowerCase().includes(filter) ||
+ (c.description ?? "").toString().toLowerCase().includes(filter)
);
});
}
// skip group if no result
- if (term && rows.length === 0) return;
+ if (filter && rows.length === 0) return;
// GROUP HEADER
tdGroup.colSpan = 7;
trGroup.className = "table-group-header";
trGroup.setAttribute("data-group", groupKey);
- tdGroup.innerHTML = term
+ tdGroup.innerHTML = filter
? '<i class="bi bi-folder2-open"></i>'
: '<i class="bi bi-folder"></i>';
tdGroup.appendChild(
tr.setAttribute("data-parent-group", groupKey);
// show only filtered keys
- if (!term) {
+ if (!filter) {
tr.classList.add("d-none");
}
// SEARCH
// -----------------------------
function initSearch() {
- // search bar
- const input = document.getElementById("searchInput");
- if (!input) return;
-
- // clean input on load
- input.value = "";
- // live filter for each keystroke
- input.addEventListener("input", (e) => {
- const term = e.target.value.trim().toLowerCase();
- updateTable();
+
+ ["searchInput", "searchInputMobile"].forEach(id => {
+
+ const input = document.getElementById(id);
+
+ if (!input) return;
+
+ // clean input on load
+ input.value = "";
+
+ // live filter
+ input.addEventListener("input", (e) => {
+ handleSearch(e.target.value, updateTable);
+ });
});
}
const tag = (e.target.tagName || "").toLowerCase();
const isTypingField =
tag === "input" || tag === "textarea" || tag === "select" || e.target.isContentEditable;
- const isSearchInput = e.target.id === "searchInput";
+ const isSearchInput =
+ e.target.id === "searchInput" || e.target.id === "searchInputMobile";
// ESC should clear search only if not focused on a typing field, or if focused on the search input (to allow quick clearing of search)
if (!isTypingField || isSearchInput) {
<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
<!-- Spacer -->
<div class="col d-none d-md-block"></div>
- <!-- Search -->
- <div class="col-12 col-md-auto">
+ <!-- Search Desktop -->
+ <div class="col-12 col-md-auto d-none d-md-block">
<div class="search-wrapper">
<input
type="text"
id="searchInput"
placeholder="Search..."
class="form-control form-control-sm placeholder-italic"
- aria-label="Search hosts"
- >
+ aria-label="Search lease">
</div>
</div>
<!-- Bottoni -->
<div class="col-12 col-md-auto d-flex align-items-center gap-2 flex-wrap">
+ <!-- Search Mobile -->
+ <div class="col-auto d-md-none">
+ <button
+ class="btn btn-primary d-flex align-items-center gap-2 px-3"
+ data-bs-toggle="collapse" data-bs-target="#mobileSearch"
+ aria-expanded="false" aria-controls="mobileSearch">
+ <i class="bi bi-search"></i>
+ </button>
+ </div>
+
+ <!-- Separator -->
+ <div class="vr mx-2"></div>
+
<!-- Add host -->
<button
class="btn btn-primary d-flex align-items-center gap-2 px-3"
</button>
</div>
</div>
+
+ <!-- Search collapsabile -->
+ <div class="collapse mt-2 d-md-none" id="mobileSearch">
+ <input
+ type="text"
+ id="searchInputMobile"
+ placeholder="Search..."
+ class="form-control form-control-sm placeholder-italic"
+ aria-label="Search lease">
+ </div>
</div>
</section>
<table id="dataTable" class="table table-bordered table-hover align-middle">
<thead class="table-light">
<tr>
- <th data-type="ipv4" data-sortable="true" data-sort="0">IP Address<span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="mac" data-sortable="true" data-sort="1">MAC <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="2">Hostname <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="3">Start <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="4">End <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="true" data-sort="5">State <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false" data-sort="6">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="ipv4" data-sortable="true" data-sort="0">
+ IP Address <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="mac" data-sortable="true" data-sort="1">
+ MAC <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="2">
+ Hostname <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="3">
+ Start <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="4">
+ End <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="true" data-sort="5">
+ State <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false" class="text-center text-nowrap">
+ Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ </th>
</tr>
</thead>
<tbody></tbody>
<section class="page-frame">
<div class="container-fluid p-0">
<div class="row g-2 align-items-center">
+
<!-- Title -->
<div class="col-12 col-md-auto">
<h2 class="mb-0 d-flex align-items-center gap-2 lh-1">
<!-- Spacer -->
<div class="col d-none d-md-block"></div>
- <!-- Search -->
- <div class="col-12 col-md-auto">
+ <!-- Search Desktop -->
+ <div class="col-12 col-md-auto d-none d-md-block">
<div class="search-wrapper">
<input
type="text"
id="searchInput"
placeholder="Search..."
class="form-control form-control-sm placeholder-italic"
- aria-label="Search config"
- >
+ aria-label="Search config">
</div>
</div>
<!-- Bottoni -->
<div class="col-12 col-md-auto d-flex align-items-center gap-2 flex-wrap">
- <!-- Expand -->
+ <!-- Search Mobile -->
+ <div class="col-auto d-md-none">
+ <button
+ class="btn btn-primary d-flex align-items-center gap-2 px-3"
+ data-bs-toggle="collapse" data-bs-target="#mobileSearch"
+ aria-expanded="false" aria-controls="mobileSearch">
+ <i class="bi bi-search"></i>
+ </button>
+ </div>
+
+ <!-- Separator -->
+ <div class="vr mx-2"></div>
+
+ <!-- Expand -->
<button id="expandAllBtn"
class="btn btn-sm btn-primary d-flex align-items-center gap-2 px-3"
title="Expand all groups"
aria-label="Expand all groups">
<i class="bi bi-arrows-expand"></i>
<span class="label">Expand</span>
- </button>
+ </button>
<!-- Collapse -->
<button id="collapseAllBtn"
</button>
</div>
</div>
+
+ <!-- Search collapsabile -->
+ <div class="collapse mt-2 d-md-none" id="mobileSearch">
+ <input
+ type="text"
+ id="searchInputMobile"
+ placeholder="Search..."
+ class="form-control form-control-sm placeholder-italic"
+ aria-label="Search config">
+ </div>
</div>
</section>
<table id="dataTable" class="table table-bordered table-hover align-middle">
<thead class="table-light">
<tr>
- <th data-type="string" data-sortable="false">Parameter <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false">Value <span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false">Description<span class="sort-arrow" aria-hidden="true"></span></th>
- <th data-type="string" data-sortable="false">Actions <span class="sort-arrow" aria-hidden="true"></span></th>
+ <th data-type="string" data-sortable="false">
+ Parameter <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false">
+ Value <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false">
+ Description <span class="sort-arrow" aria-hidden="true"></span>
+ </th>
+
+ <th data-type="string" data-sortable="false" class="text-center text-nowrap">
+ Actions <span class="sort-arrow invisible" aria-hidden="true"></span>
+ </th>
</tr>
</thead>
<tbody></tbody>