157 lines
5.3 KiB
JavaScript
157 lines
5.3 KiB
JavaScript
import { confirmDialog } from '../core/app-confirm-dialog.js';
|
|
import { warnOnce } from '../core/app-dom.js';
|
|
import { postForm } from '../core/app-http.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 postForm(url, 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);
|
|
try {
|
|
const data = await postAction(url, { uuids: ids.join(',') });
|
|
if (!data || data.ok !== true) {
|
|
throw new Error('Bulk action failed');
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
} catch {
|
|
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();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|