Files
kane-diagnostics/hubzilla/addon/assoc_profile/view/js/assoc_profile.js
2026-06-06 09:18:00 -04:00

157 lines
6.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* assoc_profile — v0.2.0
Client-side search, filter, pagination, and bulk select for the manage index.
No dependencies beyond Bootstrap 5 (already loaded by Hubzilla). */
(function () {
'use strict';
// ----------------------------------------------------------------
// MANAGE INDEX — search, filter, paginate, bulk select
// ----------------------------------------------------------------
var PAGE_SIZE = 25;
function initManageIndex() {
var table = document.getElementById('assoc-manage-table');
if (!table) return;
var rows = Array.from(table.querySelectorAll('tbody tr[data-slug]'));
var searchInput = document.getElementById('assoc-search');
var filterCounty = document.getElementById('assoc-filter-county');
var filterType = document.getElementById('assoc-filter-type');
var filterStatus = document.getElementById('assoc-filter-status');
var pageInfo = document.getElementById('assoc-page-info');
var prevBtn = document.getElementById('assoc-page-prev');
var nextBtn = document.getElementById('assoc-page-next');
var selectAll = document.getElementById('assoc-select-all');
var bulkBar = document.getElementById('assoc-bulk-bar');
var bulkCount = document.getElementById('assoc-bulk-count');
var exportBtn = document.getElementById('assoc-export-selected');
var currentPage = 1;
var filtered = rows.slice();
function getRowText(row) {
return (row.dataset.slug + ' ' +
row.dataset.name + ' ' +
(row.dataset.county || '')).toLowerCase();
}
function applyFilters() {
var q = searchInput ? searchInput.value.toLowerCase().trim() : '';
var county = filterCounty ? filterCounty.value : '';
var type = filterType ? filterType.value : '';
var status = filterStatus ? filterStatus.value : '';
filtered = rows.filter(function (row) {
if (q && getRowText(row).indexOf(q) === -1) return false;
if (county && row.dataset.county !== county) return false;
if (type && row.dataset.type !== type) return false;
if (status && row.dataset.status !== status) return false;
return true;
});
currentPage = 1;
render();
}
function render() {
var total = filtered.length;
var pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
currentPage = Math.min(currentPage, pages);
var start = (currentPage - 1) * PAGE_SIZE;
var end = Math.min(start + PAGE_SIZE, total);
rows.forEach(function (row) { row.style.display = 'none'; });
filtered.slice(start, end).forEach(function (row) { row.style.display = ''; });
if (pageInfo) {
pageInfo.textContent = total === 0
? 'No associations found'
: 'Showing ' + (start + 1) + '' + end + ' of ' + total;
}
if (prevBtn) prevBtn.disabled = currentPage <= 1;
if (nextBtn) nextBtn.disabled = currentPage >= pages;
}
function updateBulkBar() {
if (!bulkBar) return;
var checked = table.querySelectorAll('tbody input[name="assoc_select[]"]:checked');
var n = checked.length;
bulkBar.style.display = n > 0 ? 'flex' : 'none';
if (bulkCount) bulkCount.textContent = n + ' selected';
}
// Event wiring
if (searchInput) searchInput.addEventListener('input', applyFilters);
if (filterCounty) filterCounty.addEventListener('change', applyFilters);
if (filterType) filterType.addEventListener('change', applyFilters);
if (filterStatus) filterStatus.addEventListener('change', applyFilters);
if (prevBtn) prevBtn.addEventListener('click', function () {
if (currentPage > 1) { currentPage--; render(); }
});
if (nextBtn) nextBtn.addEventListener('click', function () {
var pages = Math.max(1, Math.ceil(filtered.length / PAGE_SIZE));
if (currentPage < pages) { currentPage++; render(); }
});
if (selectAll) {
selectAll.addEventListener('change', function () {
var visible = table.querySelectorAll('tbody tr[data-slug]:not([style*="none"]) input[name="assoc_select[]"]');
visible.forEach(function (cb) { cb.checked = selectAll.checked; });
updateBulkBar();
});
}
table.addEventListener('change', function (e) {
if (e.target.name === 'assoc_select[]') updateBulkBar();
});
if (exportBtn) {
exportBtn.addEventListener('click', function () {
var checked = Array.from(table.querySelectorAll('tbody input[name="assoc_select[]"]:checked'));
var slugs = checked.map(function (cb) { return cb.value; });
if (!slugs.length) return;
var form = document.getElementById('assoc-export-form');
if (!form) return;
document.getElementById('assoc-export-slugs').value = slugs.join(',');
form.submit();
});
}
render();
}
// ----------------------------------------------------------------
// DIFF VIEW — confirm/skip per entry
// ----------------------------------------------------------------
function initDiffView() {
var container = document.getElementById('assoc-diff-container');
if (!container) return;
container.addEventListener('change', function (e) {
if (e.target.name === 'diff_action[]') {
var entry = e.target.closest('.assoc-diff-entry');
if (!entry) return;
if (e.target.value === 'skip') {
entry.style.opacity = '0.45';
} else {
entry.style.opacity = '1';
}
}
});
}
// ----------------------------------------------------------------
// INIT
// ----------------------------------------------------------------
document.addEventListener('DOMContentLoaded', function () {
initManageIndex();
initDiffView();
});
})();