Added pagination to /parts page.
This commit is contained in:
@@ -4,6 +4,12 @@ function applyFilters() {
|
||||
const colorSelect = document.getElementById('filter-color');
|
||||
const currentUrl = new URL(window.location);
|
||||
|
||||
// Reset to first page when filters change (only for pagination mode)
|
||||
const tableElement = document.querySelector('#parts');
|
||||
if (tableElement && tableElement.getAttribute('data-table') === 'false') {
|
||||
currentUrl.searchParams.set('page', '1');
|
||||
}
|
||||
|
||||
// Handle owner filter
|
||||
if (ownerSelect) {
|
||||
const selectedOwner = ownerSelect.value;
|
||||
@@ -70,68 +76,140 @@ function setupSortButtons() {
|
||||
const attribute = button.dataset.sortAttribute;
|
||||
const isDesc = button.dataset.sortDesc === 'true';
|
||||
|
||||
// Get column index based on attribute
|
||||
const columnMap = {
|
||||
'name': 1,
|
||||
'color': 2,
|
||||
'quantity': 3,
|
||||
'missing': 4,
|
||||
'damaged': 5,
|
||||
'sets': 6,
|
||||
'minifigures': 7
|
||||
};
|
||||
if (isPaginationMode()) {
|
||||
// PAGINATION MODE - Server-side sorting via URL parameters
|
||||
const currentUrl = new URL(window.location);
|
||||
|
||||
const columnIndex = columnMap[attribute];
|
||||
if (columnIndex !== undefined && window.partsTableInstance) {
|
||||
// Determine sort direction
|
||||
const isCurrentlyActive = button.classList.contains('btn-primary');
|
||||
const currentDirection = button.dataset.currentDirection || (isDesc ? 'desc' : 'asc');
|
||||
const newDirection = isCurrentlyActive ?
|
||||
(currentDirection === 'asc' ? 'desc' : 'asc') :
|
||||
(isDesc ? 'desc' : 'asc');
|
||||
const currentSort = currentUrl.searchParams.get('sort');
|
||||
const currentOrder = currentUrl.searchParams.get('order');
|
||||
const isCurrentlyActive = currentSort === attribute;
|
||||
|
||||
// Clear other active buttons
|
||||
sortButtons.forEach(btn => {
|
||||
btn.classList.remove('btn-primary');
|
||||
btn.classList.add('btn-outline-primary');
|
||||
btn.removeAttribute('data-current-direction');
|
||||
});
|
||||
let newDirection;
|
||||
if (isCurrentlyActive) {
|
||||
// Toggle direction if same attribute
|
||||
newDirection = currentOrder === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
// Use default direction for new attribute
|
||||
newDirection = isDesc ? 'desc' : 'asc';
|
||||
}
|
||||
|
||||
// Mark this button as active
|
||||
button.classList.remove('btn-outline-primary');
|
||||
button.classList.add('btn-primary');
|
||||
button.dataset.currentDirection = newDirection;
|
||||
// Set sort parameters and reset to first page
|
||||
currentUrl.searchParams.set('sort', attribute);
|
||||
currentUrl.searchParams.set('order', newDirection);
|
||||
currentUrl.searchParams.set('page', '1');
|
||||
|
||||
// Apply sort using Simple DataTables API
|
||||
window.partsTableInstance.table.columns.sort(columnIndex, newDirection);
|
||||
// Navigate to sorted results
|
||||
window.location.href = currentUrl.toString();
|
||||
|
||||
} else {
|
||||
// ORIGINAL MODE - Client-side sorting via Simple DataTables
|
||||
// Get column index based on attribute
|
||||
const columnMap = {
|
||||
'name': 1,
|
||||
'color': 2,
|
||||
'quantity': 3,
|
||||
'missing': 4,
|
||||
'damaged': 5,
|
||||
'sets': 6,
|
||||
'minifigures': 7
|
||||
};
|
||||
|
||||
const columnIndex = columnMap[attribute];
|
||||
if (columnIndex !== undefined && window.partsTableInstance) {
|
||||
// Determine sort direction
|
||||
const isCurrentlyActive = button.classList.contains('btn-primary');
|
||||
const currentDirection = button.dataset.currentDirection || (isDesc ? 'desc' : 'asc');
|
||||
const newDirection = isCurrentlyActive ?
|
||||
(currentDirection === 'asc' ? 'desc' : 'asc') :
|
||||
(isDesc ? 'desc' : 'asc');
|
||||
|
||||
// Clear other active buttons
|
||||
sortButtons.forEach(btn => {
|
||||
btn.classList.remove('btn-primary');
|
||||
btn.classList.add('btn-outline-primary');
|
||||
btn.removeAttribute('data-current-direction');
|
||||
});
|
||||
|
||||
// Mark this button as active
|
||||
button.classList.remove('btn-outline-primary');
|
||||
button.classList.add('btn-primary');
|
||||
button.dataset.currentDirection = newDirection;
|
||||
|
||||
// Apply sort using Simple DataTables API
|
||||
window.partsTableInstance.table.columns.sort(columnIndex, newDirection);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (clearButton) {
|
||||
clearButton.addEventListener('click', () => {
|
||||
// Clear all sort buttons
|
||||
sortButtons.forEach(btn => {
|
||||
btn.classList.remove('btn-primary');
|
||||
btn.classList.add('btn-outline-primary');
|
||||
btn.removeAttribute('data-current-direction');
|
||||
});
|
||||
if (isPaginationMode()) {
|
||||
// PAGINATION MODE - Clear server-side sorting via URL parameters
|
||||
const currentUrl = new URL(window.location);
|
||||
currentUrl.searchParams.delete('sort');
|
||||
currentUrl.searchParams.delete('order');
|
||||
currentUrl.searchParams.set('page', '1');
|
||||
window.location.href = currentUrl.toString();
|
||||
|
||||
// Reset table sort - remove all sorting
|
||||
if (window.partsTableInstance) {
|
||||
// Destroy and recreate to clear sorting
|
||||
const tableElement = document.querySelector('#parts');
|
||||
const currentPerPage = window.partsTableInstance.table.options.perPage;
|
||||
window.partsTableInstance.table.destroy();
|
||||
} else {
|
||||
// ORIGINAL MODE - Clear client-side sorting
|
||||
// Clear all sort buttons
|
||||
sortButtons.forEach(btn => {
|
||||
btn.classList.remove('btn-primary');
|
||||
btn.classList.add('btn-outline-primary');
|
||||
btn.removeAttribute('data-current-direction');
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
// Create new instance using the globally available BrickTable class
|
||||
const newInstance = new window.BrickTable(tableElement, currentPerPage);
|
||||
window.partsTableInstance = newInstance;
|
||||
// Reset table sort - remove all sorting
|
||||
if (window.partsTableInstance) {
|
||||
// Destroy and recreate to clear sorting
|
||||
const tableElement = document.querySelector('#parts');
|
||||
const currentPerPage = window.partsTableInstance.table.options.perPage;
|
||||
window.partsTableInstance.table.destroy();
|
||||
|
||||
// Re-enable search functionality
|
||||
newInstance.table.searchable = true;
|
||||
}, 50);
|
||||
setTimeout(() => {
|
||||
// Create new instance using the globally available BrickTable class
|
||||
const newInstance = new window.BrickTable(tableElement, currentPerPage);
|
||||
window.partsTableInstance = newInstance;
|
||||
|
||||
// Re-enable search functionality
|
||||
newInstance.table.searchable = true;
|
||||
}, 50);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Check if pagination mode is enabled
|
||||
function isPaginationMode() {
|
||||
const tableElement = document.querySelector('#parts');
|
||||
// In pagination mode, table has data-table="false"
|
||||
// In original mode, table has data-table="true"
|
||||
return tableElement && tableElement.getAttribute('data-table') === 'false';
|
||||
}
|
||||
|
||||
// Initialize sort button states for pagination mode
|
||||
function initializeSortButtonStates() {
|
||||
const currentUrl = new URL(window.location);
|
||||
const currentSort = currentUrl.searchParams.get('sort');
|
||||
const currentOrder = currentUrl.searchParams.get('order');
|
||||
|
||||
if (currentSort) {
|
||||
const sortButtons = document.querySelectorAll('[data-sort-attribute]');
|
||||
sortButtons.forEach(btn => {
|
||||
// Clear all buttons first
|
||||
btn.classList.remove('btn-primary');
|
||||
btn.classList.add('btn-outline-primary');
|
||||
btn.removeAttribute('data-current-direction');
|
||||
|
||||
// Set active state for current sort
|
||||
if (btn.dataset.sortAttribute === currentSort) {
|
||||
btn.classList.remove('btn-outline-primary');
|
||||
btn.classList.add('btn-primary');
|
||||
btn.dataset.currentDirection = currentOrder || 'asc';
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -159,32 +237,71 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
}
|
||||
|
||||
if (searchInput && searchClear) {
|
||||
// Wait for table to be initialized by setup_tables
|
||||
const setupSearch = () => {
|
||||
const tableElement = document.querySelector('table[data-table="true"]');
|
||||
if (tableElement && window.partsTableInstance) {
|
||||
// Enable custom search for parts table
|
||||
window.partsTableInstance.table.searchable = true;
|
||||
if (isPaginationMode()) {
|
||||
// PAGINATION MODE - Server-side search with Enter key
|
||||
// Search on Enter key press
|
||||
searchInput.addEventListener('keypress', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
const currentUrl = new URL(window.location);
|
||||
const searchValue = e.target.value.trim();
|
||||
|
||||
// Connect search input to table
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
window.partsTableInstance.table.search(e.target.value);
|
||||
});
|
||||
// Reset to first page when searching
|
||||
currentUrl.searchParams.set('page', '1');
|
||||
|
||||
// Clear search
|
||||
searchClear.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
window.partsTableInstance.table.search('');
|
||||
});
|
||||
if (searchValue) {
|
||||
currentUrl.searchParams.set('search', searchValue);
|
||||
} else {
|
||||
currentUrl.searchParams.delete('search');
|
||||
}
|
||||
|
||||
// Setup sort buttons
|
||||
setupSortButtons();
|
||||
} else {
|
||||
// If table instance not ready, try again
|
||||
setTimeout(setupSearch, 100);
|
||||
}
|
||||
};
|
||||
window.location.href = currentUrl.toString();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(setupSearch, 100);
|
||||
// Clear search
|
||||
searchClear.addEventListener('click', () => {
|
||||
const currentUrl = new URL(window.location);
|
||||
currentUrl.searchParams.delete('search');
|
||||
currentUrl.searchParams.set('page', '1');
|
||||
window.location.href = currentUrl.toString();
|
||||
});
|
||||
} else {
|
||||
// ORIGINAL MODE - Client-side instant search via Simple DataTables
|
||||
// Wait for table to be initialized
|
||||
const setupClientSearch = () => {
|
||||
const tableElement = document.querySelector('table[data-table="true"]');
|
||||
if (tableElement && window.partsTableInstance) {
|
||||
// Enable search functionality
|
||||
window.partsTableInstance.table.searchable = true;
|
||||
|
||||
// Instant search as user types
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const searchValue = e.target.value.trim();
|
||||
window.partsTableInstance.table.search(searchValue);
|
||||
});
|
||||
|
||||
// Clear search
|
||||
searchClear.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
window.partsTableInstance.table.search('');
|
||||
});
|
||||
} else {
|
||||
// If table instance not ready, try again
|
||||
setTimeout(setupClientSearch, 100);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(setupClientSearch, 100);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Setup sort buttons
|
||||
setupSortButtons();
|
||||
|
||||
// Initialize sort button states for pagination mode
|
||||
if (isPaginationMode()) {
|
||||
initializeSortButtonStates();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -36,10 +36,12 @@ window.BrickTable = class BrickTable {
|
||||
// Special configuration for tables with custom search/sort
|
||||
const isMinifiguresTable = table.id === 'minifigures';
|
||||
const isPartsTable = table.id === 'parts';
|
||||
const hasCustomInterface = isMinifiguresTable || isPartsTable;
|
||||
const isPartsTablePaginationMode = isPartsTable && table.getAttribute('data-table') === 'false';
|
||||
const hasCustomInterface = isMinifiguresTable || isPartsTablePaginationMode;
|
||||
|
||||
this.table = new simpleDatatables.DataTable(`#${table.id}`, {
|
||||
columns: columns,
|
||||
paging: !isPartsTablePaginationMode, // Disable built-in pagination only for parts table in pagination mode
|
||||
pagerDelta: 1,
|
||||
perPage: per_page,
|
||||
perPageSelect: [10, 25, 50, 100, 500, 1000],
|
||||
|
||||
Reference in New Issue
Block a user