[feat](trx-frontend-http): paginate bookmarks tab
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -393,6 +393,14 @@
|
|||||||
<tbody id="bm-tbody"></tbody>
|
<tbody id="bm-tbody"></tbody>
|
||||||
</table>
|
</table>
|
||||||
<div id="bm-empty" class="bm-empty" style="display:none;">No bookmarks yet. Click <strong>+ Add Bookmark</strong> to save a frequency.</div>
|
<div id="bm-empty" class="bm-empty" style="display:none;">No bookmarks yet. Click <strong>+ Add Bookmark</strong> to save a frequency.</div>
|
||||||
|
<div id="bm-paginator" class="bm-paginator" style="display:none;">
|
||||||
|
<div id="bm-page-summary" class="bm-page-summary">Showing 0-0 of 0</div>
|
||||||
|
<div class="bm-page-controls">
|
||||||
|
<button id="bm-page-prev" type="button">Previous</button>
|
||||||
|
<span id="bm-page-indicator" class="bm-page-indicator">Page 1 of 1</span>
|
||||||
|
<button id="bm-page-next" type="button">Next</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tab-decoders" class="tab-panel" style="display:none;">
|
<div id="tab-decoders" class="tab-panel" style="display:none;">
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
// --- Bookmarks Tab ---
|
// --- Bookmarks Tab ---
|
||||||
|
|
||||||
var bmList = [];
|
var bmList = [];
|
||||||
|
let bmFilteredList = [];
|
||||||
let bmEditId = null;
|
let bmEditId = null;
|
||||||
|
let bmCurrentPage = 1;
|
||||||
|
const BM_PAGE_SIZE = 25;
|
||||||
|
|
||||||
function bmFmtFreq(hz) {
|
function bmFmtFreq(hz) {
|
||||||
if (!Number.isFinite(hz) || hz <= 0) return "--";
|
if (!Number.isFinite(hz) || hz <= 0) return "--";
|
||||||
@@ -66,6 +69,8 @@ function bmApplyFilters() {
|
|||||||
(bm.comment || "").toLowerCase().includes(text)
|
(bm.comment || "").toLowerCase().includes(text)
|
||||||
)
|
)
|
||||||
: filtered;
|
: filtered;
|
||||||
|
bmFilteredList = filtered;
|
||||||
|
bmCurrentPage = 1;
|
||||||
bmRender(filtered);
|
bmRender(filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,18 +111,30 @@ async function bmRefreshCategoryFilter(keepValue) {
|
|||||||
function bmRender(list) {
|
function bmRender(list) {
|
||||||
const tbody = document.getElementById("bm-tbody");
|
const tbody = document.getElementById("bm-tbody");
|
||||||
const emptyEl = document.getElementById("bm-empty");
|
const emptyEl = document.getElementById("bm-empty");
|
||||||
|
const paginatorEl = document.getElementById("bm-paginator");
|
||||||
|
const pageSummaryEl = document.getElementById("bm-page-summary");
|
||||||
|
const pageIndicatorEl = document.getElementById("bm-page-indicator");
|
||||||
|
const prevBtn = document.getElementById("bm-page-prev");
|
||||||
|
const nextBtn = document.getElementById("bm-page-next");
|
||||||
if (!tbody) return;
|
if (!tbody) return;
|
||||||
tbody.innerHTML = "";
|
tbody.innerHTML = "";
|
||||||
|
|
||||||
if (list.length === 0) {
|
if (list.length === 0) {
|
||||||
if (emptyEl) emptyEl.style.display = "";
|
if (emptyEl) emptyEl.style.display = "";
|
||||||
|
if (paginatorEl) paginatorEl.style.display = "none";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (emptyEl) emptyEl.style.display = "none";
|
if (emptyEl) emptyEl.style.display = "none";
|
||||||
|
|
||||||
const canControl = bmCanControl();
|
const canControl = bmCanControl();
|
||||||
|
const totalPages = Math.max(1, Math.ceil(list.length / BM_PAGE_SIZE));
|
||||||
|
const page = Math.min(Math.max(bmCurrentPage, 1), totalPages);
|
||||||
|
bmCurrentPage = page;
|
||||||
|
const startIndex = (page - 1) * BM_PAGE_SIZE;
|
||||||
|
const endIndex = Math.min(startIndex + BM_PAGE_SIZE, list.length);
|
||||||
|
const pageItems = list.slice(startIndex, endIndex);
|
||||||
|
|
||||||
list.forEach((bm) => {
|
pageItems.forEach((bm) => {
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
tr.dataset.bmId = bm.id;
|
tr.dataset.bmId = bm.id;
|
||||||
const bwCell = bm.bandwidth_hz ? bmFmtFreq(bm.bandwidth_hz) : "--";
|
const bwCell = bm.bandwidth_hz ? bmFmtFreq(bm.bandwidth_hz) : "--";
|
||||||
@@ -143,6 +160,20 @@ function bmRender(list) {
|
|||||||
`</td>`;
|
`</td>`;
|
||||||
tbody.appendChild(tr);
|
tbody.appendChild(tr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (paginatorEl) paginatorEl.style.display = totalPages > 1 ? "flex" : "";
|
||||||
|
if (pageSummaryEl) pageSummaryEl.textContent = `Showing ${startIndex + 1}-${endIndex} of ${list.length}`;
|
||||||
|
if (pageIndicatorEl) pageIndicatorEl.textContent = `Page ${page} of ${totalPages}`;
|
||||||
|
if (prevBtn) prevBtn.disabled = page <= 1;
|
||||||
|
if (nextBtn) nextBtn.disabled = page >= totalPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bmChangePage(delta) {
|
||||||
|
const totalPages = Math.max(1, Math.ceil(bmFilteredList.length / BM_PAGE_SIZE));
|
||||||
|
const nextPage = Math.min(Math.max(bmCurrentPage + delta, 1), totalPages);
|
||||||
|
if (nextPage === bmCurrentPage) return;
|
||||||
|
bmCurrentPage = nextPage;
|
||||||
|
bmRender(bmFilteredList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read decoder checkboxes and return an array of selected decoder names.
|
// Read decoder checkboxes and return an array of selected decoder names.
|
||||||
@@ -370,6 +401,14 @@ async function bmApply(bm) {
|
|||||||
bmApplyFilters();
|
bmApplyFilters();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("bm-page-prev").addEventListener("click", () => {
|
||||||
|
bmChangePage(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("bm-page-next").addEventListener("click", () => {
|
||||||
|
bmChangePage(1);
|
||||||
|
});
|
||||||
|
|
||||||
// Form submit
|
// Form submit
|
||||||
document.getElementById("bm-form").addEventListener("submit", bmSave);
|
document.getElementById("bm-form").addEventListener("submit", bmSave);
|
||||||
|
|
||||||
|
|||||||
@@ -3135,6 +3135,30 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
|
.bm-paginator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.8rem;
|
||||||
|
padding: 0.9rem 0.2rem 0;
|
||||||
|
}
|
||||||
|
.bm-page-summary,
|
||||||
|
.bm-page-indicator {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.88rem;
|
||||||
|
}
|
||||||
|
.bm-page-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.55rem;
|
||||||
|
}
|
||||||
|
.bm-page-controls button {
|
||||||
|
min-width: 6.4rem;
|
||||||
|
}
|
||||||
|
.bm-page-controls button:disabled {
|
||||||
|
opacity: 0.45;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Donald style ─────────────────────────────────────────────────────── */
|
/* ── Donald style ─────────────────────────────────────────────────────── */
|
||||||
[data-style="golden-rain"] {
|
[data-style="golden-rain"] {
|
||||||
@@ -3574,6 +3598,21 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
.sch-label {
|
.sch-label {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
}
|
}
|
||||||
|
.bm-paginator {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.bm-page-controls {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bm-page-controls button {
|
||||||
|
flex: 1 1 0;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.bm-page-indicator,
|
||||||
|
.bm-page-summary {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.bgd-add-row,
|
.bgd-add-row,
|
||||||
.bgd-status-row {
|
.bgd-status-row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
Reference in New Issue
Block a user