/** * Page User List */ 'use strict'; // Datatable (js) document.addEventListener('DOMContentLoaded', function (e) { let borderColor, bodyBg, headingColor; borderColor = config.colors.borderColor; bodyBg = config.colors.bodyBg; headingColor = config.colors.headingColor; // Variable declaration for table const dt_user_table = document.querySelector('.datatables-users'), userView = 'app-user-view-account.html', statusObj = { 1: { title: 'Pending', class: 'bg-label-warning' }, 2: { title: 'Active', class: 'bg-label-success' }, 3: { title: 'Inactive', class: 'bg-label-secondary' } }; var select2 = $('.select2'); if (select2.length) { var $this = select2; $this.wrap('
').select2({ placeholder: 'Select Country', dropdownParent: $this.parent() }); } // Users datatable if (dt_user_table) { const dt_user = new DataTable(dt_user_table, { ajax: assetsPath + 'json/user-list.json', // JSON file to add data columns: [ // columns according to JSON { data: 'id' }, { data: 'id', orderable: false, render: DataTable.render.select() }, { data: 'full_name' }, { data: 'role' }, { data: 'current_plan' }, { data: 'billing' }, { data: 'status' }, { data: 'action' } ], columnDefs: [ { // For Responsive className: 'control', searchable: false, orderable: false, responsivePriority: 2, targets: 0, render: function (data, type, full, meta) { return ''; } }, { // For Checkboxes targets: 1, orderable: false, searchable: false, responsivePriority: 4, checkboxes: true, render: function () { return ''; }, checkboxes: { selectAllRender: '' } }, { targets: 2, responsivePriority: 3, render: function (data, type, full, meta) { var name = full['full_name']; var email = full['email']; var image = full['avatar']; var output; if (image) { // For Avatar image output = 'Avatar'; } else { // For Avatar badge var stateNum = Math.floor(Math.random() * 6); var states = ['success', 'danger', 'warning', 'info', 'dark', 'primary', 'secondary']; var state = states[stateNum]; var initials = (name.match(/\b\w/g) || []).map(char => char.toUpperCase()); initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase(); output = '' + initials + ''; } // Creates full output for row var row_output = '
' + '
' + '
' + output + '
' + '
' + '
' + '' + name + '' + '' + email + '' + '
' + '
'; return row_output; } }, { targets: 3, render: function (data, type, full, meta) { var role = full['role']; var roleBadgeObj = { Subscriber: '', Author: '', Maintainer: '', Editor: '', Admin: '' }; return ( "" + (roleBadgeObj[role] || '') + // Ensures badge exists for the role role + '' ); } }, { // Plans targets: 4, render: function (data, type, full, meta) { const plan = full['current_plan']; return '' + plan + ''; } }, { // User Status targets: 6, render: function (data, type, full, meta) { const status = full['status']; return ( '' + statusObj[status].title + '' ); } }, { targets: -1, title: 'Actions', searchable: false, orderable: false, render: (data, type, full, meta) => { return `
`; } } ], select: { style: 'multi', selector: 'td:nth-child(2)' }, order: [[2, 'desc']], layout: { topStart: { rowClass: 'row m-3 my-0 justify-content-between', features: [ { pageLength: { menu: [10, 25, 50, 100], text: '_MENU_' } } ] }, topEnd: { features: [ { search: { placeholder: 'Search User', text: '_INPUT_' } }, { buttons: [ { extend: 'collection', className: 'btn btn-label-secondary dropdown-toggle', text: ' Export', buttons: [ { extend: 'print', text: `Print`, className: 'dropdown-item', exportOptions: { columns: [3, 4, 5, 6, 7], format: { body: function (inner, coldex, rowdex) { if (inner.length <= 0) return inner; // Check if inner is HTML content if (inner.indexOf('<') > -1) { const parser = new DOMParser(); const doc = parser.parseFromString(inner, 'text/html'); // Get all text content let text = ''; // Handle specific elements const userNameElements = doc.querySelectorAll('.user-name'); if (userNameElements.length > 0) { userNameElements.forEach(el => { // Get text from nested structure const nameText = el.querySelector('.fw-medium')?.textContent || el.querySelector('.d-block')?.textContent || el.textContent; text += nameText.trim() + ' '; }); } else { // Get regular text content text = doc.body.textContent || doc.body.innerText; } return text.trim(); } return inner; } } }, customize: function (win) { win.document.body.style.color = config.colors.headingColor; win.document.body.style.borderColor = config.colors.borderColor; win.document.body.style.backgroundColor = config.colors.bodyBg; const table = win.document.body.querySelector('table'); table.classList.add('compact'); table.style.color = 'inherit'; table.style.borderColor = 'inherit'; table.style.backgroundColor = 'inherit'; } }, { extend: 'csv', text: `Csv`, className: 'dropdown-item', exportOptions: { columns: [3, 4, 5, 6, 7], format: { body: function (inner, coldex, rowdex) { if (inner.length <= 0) return inner; // Parse HTML content const parser = new DOMParser(); const doc = parser.parseFromString(inner, 'text/html'); let text = ''; // Handle user-name elements specifically const userNameElements = doc.querySelectorAll('.user-name'); if (userNameElements.length > 0) { userNameElements.forEach(el => { // Get text from nested structure - try different selectors const nameText = el.querySelector('.fw-medium')?.textContent || el.querySelector('.d-block')?.textContent || el.textContent; text += nameText.trim() + ' '; }); } else { // Handle other elements (status, role, etc) text = doc.body.textContent || doc.body.innerText; } return text.trim(); } } } }, { extend: 'excel', text: `Excel`, className: 'dropdown-item', exportOptions: { columns: [3, 4, 5, 6, 7], format: { body: function (inner, coldex, rowdex) { if (inner.length <= 0) return inner; // Parse HTML content const parser = new DOMParser(); const doc = parser.parseFromString(inner, 'text/html'); let text = ''; // Handle user-name elements specifically const userNameElements = doc.querySelectorAll('.user-name'); if (userNameElements.length > 0) { userNameElements.forEach(el => { // Get text from nested structure - try different selectors const nameText = el.querySelector('.fw-medium')?.textContent || el.querySelector('.d-block')?.textContent || el.textContent; text += nameText.trim() + ' '; }); } else { // Handle other elements (status, role, etc) text = doc.body.textContent || doc.body.innerText; } return text.trim(); } } } }, { extend: 'pdf', text: `Pdf`, className: 'dropdown-item', exportOptions: { columns: [3, 4, 5, 6, 7], format: { body: function (inner, coldex, rowdex) { if (inner.length <= 0) return inner; // Parse HTML content const parser = new DOMParser(); const doc = parser.parseFromString(inner, 'text/html'); let text = ''; // Handle user-name elements specifically const userNameElements = doc.querySelectorAll('.user-name'); if (userNameElements.length > 0) { userNameElements.forEach(el => { // Get text from nested structure - try different selectors const nameText = el.querySelector('.fw-medium')?.textContent || el.querySelector('.d-block')?.textContent || el.textContent; text += nameText.trim() + ' '; }); } else { // Handle other elements (status, role, etc) text = doc.body.textContent || doc.body.innerText; } return text.trim(); } } } }, { extend: 'copy', text: `Copy`, className: 'dropdown-item', exportOptions: { columns: [3, 4, 5, 6, 7], format: { body: function (inner, coldex, rowdex) { if (inner.length <= 0) return inner; // Parse HTML content const parser = new DOMParser(); const doc = parser.parseFromString(inner, 'text/html'); let text = ''; // Handle user-name elements specifically const userNameElements = doc.querySelectorAll('.user-name'); if (userNameElements.length > 0) { userNameElements.forEach(el => { // Get text from nested structure - try different selectors const nameText = el.querySelector('.fw-medium')?.textContent || el.querySelector('.d-block')?.textContent || el.textContent; text += nameText.trim() + ' '; }); } else { // Handle other elements (status, role, etc) text = doc.body.textContent || doc.body.innerText; } return text.trim(); } } } } ] }, { text: ' Add New Record', className: 'add-new btn btn-primary', attr: { 'data-bs-toggle': 'offcanvas', 'data-bs-target': '#offcanvasAddUser' } } ] } ] }, bottomStart: { rowClass: 'row mx-3 justify-content-between', features: ['info'] }, bottomEnd: 'paging' }, language: { sLengthMenu: '_MENU_', search: '', searchPlaceholder: 'Search User', paginate: { next: '', previous: '', first: '', last: '' } }, // For responsive popup responsive: { details: { display: DataTable.Responsive.display.modal({ header: function (row) { const data = row.data(); return 'Details of ' + data['full_name']; } }), type: 'column', renderer: function (api, rowIdx, columns) { const data = columns .map(function (col) { return col.title !== '' // Do not show row in modal popup if title is blank (for check box) ? ` ${col.title}: ${col.data} ` : ''; }) .join(''); if (data) { const div = document.createElement('div'); div.classList.add('table-responsive'); const table = document.createElement('table'); div.appendChild(table); table.classList.add('table'); const tbody = document.createElement('tbody'); tbody.innerHTML = data; table.appendChild(tbody); return div; } return false; } } }, initComplete: function () { const api = this.api(); // Helper function to create a select dropdown and append options const createFilter = (columnIndex, containerClass, selectId, defaultOptionText) => { const column = api.column(columnIndex); const select = document.createElement('select'); select.id = selectId; select.className = 'form-select text-capitalize'; select.innerHTML = ``; document.querySelector(containerClass).appendChild(select); // Add event listener for filtering select.addEventListener('change', () => { const val = select.value ? `^${select.value}$` : ''; column.search(val, true, false).draw(); }); // Populate options based on unique column data const uniqueData = Array.from(new Set(column.data().toArray())).sort(); uniqueData.forEach(d => { const option = document.createElement('option'); option.value = d; option.textContent = d; select.appendChild(option); }); }; // Role filter createFilter(3, '.user_role', 'UserRole', 'Select Role'); // Plan filter createFilter(4, '.user_plan', 'UserPlan', 'Select Plan'); // Status filter const statusFilter = document.createElement('select'); statusFilter.id = 'FilterTransaction'; statusFilter.className = 'form-select text-capitalize'; statusFilter.innerHTML = ''; document.querySelector('.user_status').appendChild(statusFilter); statusFilter.addEventListener('change', () => { const val = statusFilter.value ? `^${statusFilter.value}$` : ''; api.column(6).search(val, true, false).draw(); }); const statusColumn = api.column(6); const uniqueStatusData = Array.from(new Set(statusColumn.data().toArray())).sort(); uniqueStatusData.forEach(d => { const option = document.createElement('option'); option.value = statusObj[d]?.title || d; option.textContent = statusObj[d]?.title || d; option.className = 'text-capitalize'; statusFilter.appendChild(option); }); } }); //? The 'delete-record' class is necessary for the functionality of the following code. function deleteRecord(event) { let row = document.querySelector('.dtr-expanded'); if (event) { row = event.target.parentElement.closest('tr'); } if (row) { dt_user.row(row).remove().draw(); } } function bindDeleteEvent() { const userListTable = document.querySelector('.datatables-users'); const modal = document.querySelector('.dtr-bs-modal'); if (userListTable && userListTable.classList.contains('collapsed')) { if (modal) { modal.addEventListener('click', function (event) { if (event.target.parentElement.classList.contains('delete-record')) { deleteRecord(); const closeButton = modal.querySelector('.btn-close'); if (closeButton) closeButton.click(); // Simulates a click on the close button } }); } } else { const tableBody = userListTable?.querySelector('tbody'); if (tableBody) { tableBody.addEventListener('click', function (event) { if (event.target.parentElement.classList.contains('delete-record')) { deleteRecord(event); } }); } } } // Initial event binding bindDeleteEvent(); // Re-bind events when modal is shown or hidden document.addEventListener('show.bs.modal', function (event) { if (event.target.classList.contains('dtr-bs-modal')) { bindDeleteEvent(); } }); document.addEventListener('hide.bs.modal', function (event) { if (event.target.classList.contains('dtr-bs-modal')) { bindDeleteEvent(); } }); } // Filter form control to default size // ? setTimeout used for user-list table initialization setTimeout(() => { const elementsToModify = [ { selector: '.dt-buttons .btn', classToRemove: 'btn-secondary' }, { selector: '.dt-search .form-control', classToRemove: 'form-control-sm' }, { selector: '.dt-length .form-select', classToRemove: 'form-select-sm', classToAdd: 'ms-0' }, { selector: '.dt-length', classToAdd: 'mb-md-6 mb-0' }, { selector: '.dt-layout-end', classToRemove: 'justify-content-between', classToAdd: 'd-flex gap-md-4 justify-content-md-between justify-content-center gap-2 flex-wrap' }, { selector: '.dt-buttons', classToAdd: 'd-flex gap-4 mb-md-0 mb-4' }, { selector: '.dt-layout-table', classToRemove: 'row mt-2' }, { selector: '.dt-layout-full', classToRemove: 'col-md col-12', classToAdd: 'table-responsive' } ]; // Delete record elementsToModify.forEach(({ selector, classToRemove, classToAdd }) => { document.querySelectorAll(selector).forEach(element => { if (classToRemove) { classToRemove.split(' ').forEach(className => element.classList.remove(className)); } if (classToAdd) { classToAdd.split(' ').forEach(className => element.classList.add(className)); } }); }); }, 100); // Validation & Phone mask const phoneMaskList = document.querySelectorAll('.phone-mask'), addNewUserForm = document.getElementById('addNewUserForm'); // Phone Number if (phoneMaskList) { phoneMaskList.forEach(function (phoneMask) { phoneMask.addEventListener('input', event => { const cleanValue = event.target.value.replace(/\D/g, ''); phoneMask.value = formatGeneral(cleanValue, { blocks: [3, 3, 4], delimiters: [' ', ' '] }); }); registerCursorTracker({ input: phoneMask, delimiter: ' ' }); }); } // Add New User Form Validation const fv = FormValidation.formValidation(addNewUserForm, { fields: { userFullname: { validators: { notEmpty: { message: 'Please enter fullname ' } } }, userEmail: { validators: { notEmpty: { message: 'Please enter your email' }, emailAddress: { message: 'The value is not a valid email address' } } } }, plugins: { trigger: new FormValidation.plugins.Trigger(), bootstrap5: new FormValidation.plugins.Bootstrap5({ // Use this for enabling/changing valid/invalid class eleValidClass: '', rowSelector: function (field, ele) { // field is the field name & ele is the field element return '.form-control-validation'; } }), submitButton: new FormValidation.plugins.SubmitButton(), // Submit the form when all fields are valid // defaultSubmit: new FormValidation.plugins.DefaultSubmit(), autoFocus: new FormValidation.plugins.AutoFocus() } }); });