Files
breadcrumb-the-shire/web/js/pages/app-users-list.js
2026-03-06 00:44:52 +01:00

162 lines
5.5 KiB
JavaScript

import { confirmDialog } from '../core/app-confirm-dialog.js';
import { warnOnce } from '../core/app-dom.js';
export function initUsersListPage(options = {}) {
const {
gridConfig,
appBase,
csrf,
labels = {},
selectors = {},
bulkDownloadForms = {},
exportPath = 'admin/users/export',
listPath = 'admin/users',
resetOptions = {},
buildBulkUrl,
showFlash,
withLoading
} = options;
if (!gridConfig) {return;}
const exportSelector = selectors.exportButton || '[data-users-export]';
const resetSelector = selectors.resetButton || '[data-users-reset]';
const bulkSelector = selectors.bulkButtons || '[data-users-bulk]';
const resolveBulkUrl = buildBulkUrl
? buildBulkUrl
: (action) => new URL(`admin/users/bulk/${action}`, appBase).toString();
const postAction = async (url, data = {}) => {
const body = new URLSearchParams({ ...data, [csrf.key]: csrf.token });
return fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'X-Requested-With': 'fetch'
},
body
});
};
const exportButton = document.querySelector(exportSelector);
if (exportButton) {
exportButton.addEventListener('click', () => {
const exportUrl = new URL(exportPath, appBase);
const dataUrl = new URL(gridConfig.baseUrl());
dataUrl.searchParams.forEach((value, key) => exportUrl.searchParams.set(key, value));
const sortParams = gridConfig.getSortParams ? gridConfig.getSortParams() : null;
if (sortParams && sortParams.order) {
exportUrl.searchParams.set('order', sortParams.order);
exportUrl.searchParams.set('dir', sortParams.dir || 'asc');
}
window.location.href = exportUrl.toString();
});
}
const resetButton = document.querySelector(resetSelector);
if (resetButton) {
resetButton.addEventListener('click', () => {
if (typeof gridConfig.resetFilters === 'function') {
gridConfig.resetFilters(resetOptions);
} else {
gridConfig.updateGrid(resetOptions);
}
document.dispatchEvent(new CustomEvent('app:filters-updated'));
});
}
const bulkButtons = Array.from(document.querySelectorAll(bulkSelector));
if (bulkButtons.length) {
bulkButtons.forEach((button) => {
button.addEventListener('click', async () => {
const action = button.getAttribute('data-users-bulk') || '';
const ids = gridConfig.selection?.getSelectedIds?.() || [];
const validActions = ['activate', 'deactivate', 'delete', 'send-access', 'access-pdf'];
if (!ids.length || !validActions.includes(action)) {
if (action && !validActions.includes(action)) {
warnOnce('UI_ACTION_UNSUPPORTED', `Unsupported users bulk action: ${action}`, {
module: 'users-list',
component: 'bulk-action',
});
}
return;
}
const confirmTexts = {
'activate': labels.bulkActivateConfirm,
'deactivate': labels.bulkDeactivateConfirm,
'delete': labels.bulkDeleteConfirm,
'send-access': labels.bulkSendAccessConfirm,
'access-pdf': labels.bulkAccessPdfConfirm
};
const confirmText = confirmTexts[action];
if (confirmText) {
const approved = await confirmDialog.confirm({
message: confirmText,
actionKind: action,
});
if (!approved) {
return;
}
}
const downloadFormSelector = bulkDownloadForms?.[action];
if (downloadFormSelector) {
const downloadForm = document.querySelector(downloadFormSelector);
if (!downloadForm) {
window.location.href = new URL(listPath, appBase).toString();
return;
}
const uuidsInput = downloadForm.querySelector('input[name="uuids"]');
if (uuidsInput) {
uuidsInput.value = ids.join(',');
}
downloadForm.submit();
return;
}
const executeBulk = async () => {
const url = resolveBulkUrl(action);
const response = await postAction(url, { uuids: ids.join(',') });
const data = await response.json().catch(() => null);
if (response.ok && data && data.ok) {
gridConfig.selection?.clear?.();
gridConfig.grid?.forceRender();
if (showFlash && labels.bulkMessages) {
const msg = labels.bulkMessages[action];
if (msg) {
const count = data.count ?? 0;
const failed = data.failed ?? 0;
let text = msg.success.replace('%d', count);
if (failed > 0 && msg.partial) {
text = msg.partial.replace('%d', count).replace('%f', failed);
}
showFlash('success', text);
}
}
} else {
if (showFlash && labels.bulkMessages) {
const msg = labels.bulkMessages[action];
if (msg?.error) {
showFlash('error', msg.error);
} else {
window.location.href = new URL(listPath, appBase).toString();
}
} else {
window.location.href = new URL(listPath, appBase).toString();
}
}
};
if (withLoading) {
await withLoading(executeBulk);
} else {
await executeBulk();
}
});
});
}
}