import { initMultiSelect } from '../../../../js/components/app-multiselect-init.js'; import { initMultiSelectCascade } from '../../../../js/components/app-multiselect-cascade.js'; import { initStandardListPage } from '../../../../js/core/app-grid-factory.js'; import { readPageConfig } from '../../../../js/core/app-page-config.js'; import { warnOnce } from '../../../../js/core/app-dom.js'; import { getAppBase, escapeHtml, buildBadgeList, gridFilterMultiCsv, gridFilterText, withCurrentListReturn } from '../../../../js/pages/app-list-utils.js'; const config = readPageConfig('address-book-index'); if (config) { const appBase = getAppBase(); const gridSearch = config.gridSearch ?? null; const filterSchema = config.filterSchema ?? []; const filterChipMeta = config.filterChipMeta ?? []; const labels = config.labels ?? {}; const toolbar = document.querySelector('#address-book-drawer-toolbar'); const customFilterInputs = Array.from(document.querySelectorAll('[data-address-book-custom-filter]')); const tenantDepartmentMap = toolbar?.dataset?.tenantDeptMap ? JSON.parse(toolbar.dataset.tenantDeptMap) : {}; const uuidIndex = 0; const initialsForName = (name) => { const parts = String(name || '') .trim() .split(/\s+/) .filter(Boolean); const chars = parts.slice(0, 2).map((value) => value[0] || '').join('').toUpperCase(); return chars || '?'; }; const customFilters = customFilterInputs.map((input) => { const param = String(input?.dataset?.addressBookCustomFilterParam || '').trim(); if (!param) {return null;} if (input.dataset.addressBookCustomFilterType === 'multiselect') { const targetSelector = input.dataset.addressBookCustomFilterInput || ''; return gridFilterMultiCsv(targetSelector, param, { default: [] }); } return gridFilterText(input, param, { default: '' }); }).filter(Boolean); const gridOptions = { gridjs: window.gridjs, container: '#address-book-grid', dataUrl: 'address-book/data', appBase, columns: [ { name: 'UUID', hidden: true }, { name: labels.name || 'Name', sort: true, formatter: (cell, row) => { const nameValue = typeof cell === 'object' && cell !== null ? (cell.name ?? '') : cell; const avatarUuid = typeof cell === 'object' && cell !== null ? (cell.avatar_uuid ?? '') : ''; const name = escapeHtml(nameValue || '-'); const uuid = row?.cells?.[uuidIndex]?.data; const editUrl = uuid ? withCurrentListReturn(new URL(`address-book/view/${uuid}`, appBase).toString()) : ''; const nameHtml = editUrl ? `${name}` : `${name}`; if (!avatarUuid) { const initials = escapeHtml(initialsForName(nameValue)); return gridjs.html(`${initials}${nameHtml}`); } const src = new URL(`admin/users/avatar-file?uuid=${avatarUuid}&size=64`, appBase).toString(); const full = new URL(`admin/users/avatar-file?uuid=${avatarUuid}&size=256`, appBase).toString(); return gridjs.html(`${nameHtml}`); }, }, { name: labels.email || 'Email', sort: true }, { name: labels.phone || 'Phone', sort: false }, { name: labels.mobile || 'Mobile', sort: false }, { name: labels.shortDial || 'Short dial', sort: false }, { name: labels.tenants || 'Tenants', sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) }, { name: labels.departments || 'Departments', sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) }, { name: labels.roles || 'Roles', sort: false, formatter: (cell) => gridjs.html(buildBadgeList(cell)) }, ], sortColumns: [null, 'display_name', 'email', null, null, null, null, null, null], paginationLimit: 10, language: config.gridLang ?? {}, mapData: (data) => data.data.map((row) => [ row.uuid, { name: row.display_name, avatar_uuid: row.has_avatar ? row.uuid : '', }, row.email, row.phone, row.mobile, row.short_dial, row.tenants, row.departments, row.roles, ]), search: gridSearch, filterSchema, extraFilters: customFilters, urlSync: true, rowDataset: (row) => ({ uuid: row?.cells?.[uuidIndex]?.data, }), rowInteraction: { linkColumn: false }, rowDblClick: { getUrl: (rowData) => { const uuid = rowData?.cells?.[uuidIndex]?.data; return uuid ? new URL(`address-book/view/${uuid}`, appBase).toString() : ''; }, }, }; const { gridConfig } = initStandardListPage({ grid: gridOptions, filters: { mode: 'drawer', chipMeta: filterChipMeta, watchInputs: ['#address-book-search'], }, }); if (!gridConfig || !gridConfig.grid) { warnOnce('UI_INIT_FAIL', 'Address book grid init failed', { module: 'address-book-index', component: 'grid' }); } initMultiSelect().then(() => { initMultiSelectCascade({ parent: '#address-book-tenant-filter', child: '#address-book-department-filter', map: tenantDepartmentMap, mode: 'disable', clearInvalid: true, }); }); }