193 lines
5.8 KiB
JavaScript
193 lines
5.8 KiB
JavaScript
class DataTableManager {
|
|
constructor(tableElement, apiUrl) {
|
|
this.tableElement = tableElement;
|
|
this.apiUrl = apiUrl;
|
|
this.dataTableOptions = this.createDataTableOptions();
|
|
this.dataTable = new KTDataTable(tableElement, this.dataTableOptions);
|
|
this.filterMap = this.createFilterMap();
|
|
}
|
|
|
|
static isLocalhost() {
|
|
return /^(localhost|127.0.0.1)$/.test(window.location.hostname);
|
|
}
|
|
|
|
/**
|
|
* Creates the options for the DataTable.
|
|
*
|
|
* @return {Object} The options for the DataTable.
|
|
*/
|
|
createDataTableOptions() {
|
|
return {
|
|
apiEndpoint: this.apiUrl,
|
|
pageSize: 10,
|
|
columns: {
|
|
select: {
|
|
render: (item, data, context) => {
|
|
const checkbox = document.createElement('input');
|
|
checkbox.className = 'checkbox checkbox-sm';
|
|
checkbox.type = 'checkbox';
|
|
checkbox.value = data.id.toString();
|
|
checkbox.setAttribute('data-datatable-row-check', 'true');
|
|
return checkbox.outerHTML.trim();
|
|
},
|
|
},
|
|
user: {
|
|
title: 'Person',
|
|
render: (item) => {
|
|
const prefix = DataTableManager.isLocalhost() ? 'metronic-tailwind-html' : 'metronic/tailwind';
|
|
return `
|
|
<div class="flex items-center gap-2.5">
|
|
<div class="shrink-0">
|
|
<img class="h-9 rounded-full" src="/static/${prefix}/dist/assets/media/avatars/${item.avatar}">
|
|
</div>
|
|
<a class="leading-none font-semibold text-gray-900 hover:text-primary" href="#">
|
|
${item.name}
|
|
</a>
|
|
</div>
|
|
`;
|
|
},
|
|
},
|
|
browser: {
|
|
title: 'Browser',
|
|
render: (item) => {
|
|
return `
|
|
<div class="flex items-center gap-2">
|
|
<i class="ki-outline ki-chrome text-gray-700 text-lg"></i>
|
|
<span class="text-gray-700">${item.name}</span>
|
|
</div>
|
|
`;
|
|
},
|
|
},
|
|
ipAddress: {
|
|
title: 'IP Address',
|
|
},
|
|
location: {
|
|
title: 'Location',
|
|
render: (item) => {
|
|
const prefix = DataTableManager.isLocalhost() ? 'metronic-tailwind-html' : 'metronic/tailwind';
|
|
return `
|
|
<div class="flex items-center gap-1.5">
|
|
<img alt="flag" class="h-4 rounded-full" src="/static/${prefix}/dist/assets/media/flags/${item.flag}">
|
|
<span class="leading-none text-gray-700">${item.name}</span>
|
|
</div>
|
|
`;
|
|
},
|
|
},
|
|
action: {
|
|
title: '',
|
|
render: (item) => {
|
|
return `
|
|
<button class="btn btn-icon btn-light btn-clear btn-sm">
|
|
<i class="ki-outline ki-dots-vertical"></i>
|
|
</button>
|
|
`;
|
|
},
|
|
createdCell: (cell, cellData, rowData) => {
|
|
cell.querySelector('.btn').addEventListener('click', () => {
|
|
alert(`Clicked on action button for row ${rowData.user.name}`);
|
|
});
|
|
},
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Creates a map of filter elements based on the data-datatable-filter-column attribute.
|
|
*
|
|
* @return {Map<string, HTMLSelectElement>} A map of filter elements, where the key is the value of the data-datatable-filter-column attribute and the value is the corresponding HTMLSelectElement.
|
|
*/
|
|
createFilterMap() {
|
|
const filterElements = document.querySelectorAll(
|
|
'select[data-datatable-filter-column]'
|
|
);
|
|
return new Map(
|
|
Array.from(filterElements).map((el) => [
|
|
el.getAttribute('data-datatable-filter-column'),
|
|
el,
|
|
])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Initialize the filters based on the state and map the filter elements to their corresponding datatable columns.
|
|
*/
|
|
initializeFilters() {
|
|
this.dataTable.getState().filters.forEach(({ column, value }) => {
|
|
if (this.filterMap.has(column)) {
|
|
const filterEl = this.filterMap.get(column);
|
|
if (filterEl !== null) {
|
|
filterEl.value = value || '';
|
|
}
|
|
}
|
|
});
|
|
|
|
this.filterMap.forEach((el, column) => {
|
|
el.addEventListener('change', () => {
|
|
this.dataTable
|
|
.setFilter({
|
|
column,
|
|
type: 'text',
|
|
value: el.value || '',
|
|
})
|
|
.redraw();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* A debounced function that delays invoking the input function until after wait milliseconds have elapsed since the last time the debounced function is invoked.
|
|
*
|
|
* @param {Function} func - The function to debounce.
|
|
* @param {number} wait - The number of milliseconds to delay.
|
|
* @return {Function} The debounced function.
|
|
*/
|
|
debounce(func, wait) {
|
|
let timeout;
|
|
return function (...args) {
|
|
const context = this;
|
|
clearTimeout(timeout);
|
|
timeout = setTimeout(() => func.apply(context, args), wait);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initializes the search functionality for the current table.
|
|
* It sets up a debounced search event listener on the search element
|
|
* to perform a search on the datatable whenever the user types in the search input.
|
|
*
|
|
* @return {void}
|
|
*/
|
|
initSearch() {
|
|
const searchElement = document.querySelector('[data-datatable-search="true"]');
|
|
if (this.dataTable && searchElement) {
|
|
const debouncedSearch = this.debounce(() => {
|
|
this.dataTable.search(searchElement.value);
|
|
}, 300);
|
|
searchElement.addEventListener('keyup', debouncedSearch);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new instance of DataTableManager with the specified tableElement and apiUrl.
|
|
* Initializes filters and search functionality for the instance.
|
|
*
|
|
* @param {void}
|
|
* @return {void}
|
|
*/
|
|
static createInstance() {
|
|
const apiUrl = DataTableManager.isLocalhost()
|
|
? 'http://127.0.0.1:8001/metronic-tailwind-html/demo1/account/security/current-sessions/_data.html'
|
|
: 'https://keenthemes.com/metronic/tailwind/demo1/account/security/current-sessions/_data.html';
|
|
const tableElement = document.querySelector('#current_sessions_table');
|
|
|
|
const dataTableManager = new DataTableManager(tableElement, apiUrl);
|
|
dataTableManager.initializeFilters();
|
|
dataTableManager.initSearch();
|
|
}
|
|
}
|
|
|
|
KTDom.ready(() => {
|
|
DataTableManager.createInstance();
|
|
});
|