diff --git a/actix_mvc_app/src/views/governance/proposal_detail.html b/actix_mvc_app/src/views/governance/proposal_detail.html index e6f8323..d899a1c 100644 --- a/actix_mvc_app/src/views/governance/proposal_detail.html +++ b/actix_mvc_app/src/views/governance/proposal_detail.html @@ -275,7 +275,7 @@ Date - + {% if votes | length == 0 %} @@ -329,6 +329,43 @@ + + + {% if votes | length > 10 %} +
+
+ + +
+
+ +
+
+ Showing 1-10 of {{ votes | length }} +
+
+ {% endif %} @@ -362,41 +399,237 @@ // Filter votes by type filterButtons.forEach(button => { - button.addEventListener('click', function () { + button.addEventListener('click', function() { // Update active button filterButtons.forEach(btn => btn.classList.remove('active')); this.classList.add('active'); - - const filterType = this.getAttribute('data-filter'); - - voteRows.forEach(row => { - if (filterType === 'all') { - row.style.display = ''; - } else { - const voteType = row.getAttribute('data-vote-type'); - row.style.display = (voteType === filterType) ? '' : 'none'; - } - }); + + // Reset to first page and update pagination + currentPage = 1; + updatePagination(); }); }); // Search functionality if (searchInput) { - searchInput.addEventListener('input', function () { + searchInput.addEventListener('input', function() { const searchTerm = this.value.toLowerCase(); - + voteRows.forEach(row => { const voterName = row.querySelector('td:first-child').textContent.toLowerCase(); const comment = row.querySelector('td:nth-child(3)').textContent.toLowerCase(); - + if (voterName.includes(searchTerm) || comment.includes(searchTerm)) { row.style.display = ''; } else { row.style.display = 'none'; } }); + + // Reset pagination after search + currentPage = 1; + updatePagination(); }); } + + // Pagination functionality + const rowsPerPageSelect = document.getElementById('rowsPerPage'); + const paginationControls = document.getElementById('paginationControls'); + const votesTableBody = document.getElementById('votesTableBody'); + const startRowElement = document.getElementById('startRow'); + const endRowElement = document.getElementById('endRow'); + const totalRowsElement = document.getElementById('totalRows'); + const prevPageBtn = document.getElementById('prevPage'); + const nextPageBtn = document.getElementById('nextPage'); + + let currentPage = 1; + let rowsPerPage = rowsPerPageSelect ? parseInt(rowsPerPageSelect.value) : 10; + + // Function to update pagination display + function updatePagination() { + if (!paginationControls) return; + + // Get all rows that match the current filter + const currentFilter = document.querySelector('[data-filter].active'); + const filterType = currentFilter ? currentFilter.getAttribute('data-filter') : 'all'; + + // Get rows that match the current filter and search term + let filteredRows = Array.from(voteRows); + if (filterType !== 'all') { + filteredRows = filteredRows.filter(row => row.getAttribute('data-vote-type') === filterType); + } + + // Apply search filter if there's a search term + const searchTerm = searchInput ? searchInput.value.toLowerCase() : ''; + if (searchTerm) { + filteredRows = filteredRows.filter(row => { + const voterName = row.querySelector('td:first-child').textContent.toLowerCase(); + const comment = row.querySelector('td:nth-child(3)').textContent.toLowerCase(); + return voterName.includes(searchTerm) || comment.includes(searchTerm); + }); + } + + const totalRows = filteredRows.length; + + // Calculate total pages + const totalPages = Math.max(1, Math.ceil(totalRows / rowsPerPage)); + + // Ensure current page is valid + if (currentPage > totalPages) { + currentPage = totalPages; + } + + // Update pagination controls + if (paginationControls) { + // Clear existing page links (except prev/next) + const pageLinks = paginationControls.querySelectorAll('li:not(#prevPage):not(#nextPage)'); + pageLinks.forEach(link => link.remove()); + + // Add new page links + const maxVisiblePages = 5; + let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2)); + let endPage = Math.min(totalPages, startPage + maxVisiblePages - 1); + + // Adjust if we're near the end + if (endPage - startPage + 1 < maxVisiblePages && startPage > 1) { + startPage = Math.max(1, endPage - maxVisiblePages + 1); + } + + // Insert page links before the next button + const nextPageElement = document.getElementById('nextPage'); + for (let i = startPage; i <= endPage; i++) { + const li = document.createElement('li'); + li.className = `page-item ${i === currentPage ? 'active' : ''}`; + + const a = document.createElement('a'); + a.className = 'page-link'; + a.href = '#'; + a.textContent = i; + a.addEventListener('click', function(e) { + e.preventDefault(); + currentPage = i; + updatePagination(); + }); + + li.appendChild(a); + paginationControls.insertBefore(li, nextPageElement); + } + + // Update prev/next buttons + prevPageBtn.className = `page-item ${currentPage === 1 ? 'disabled' : ''}`; + nextPageBtn.className = `page-item ${currentPage === totalPages ? 'disabled' : ''}`; + } + + // Show current page + showCurrentPage(); + } + + // Function to show current page + function showCurrentPage() { + if (!votesTableBody) return; + + // Get all rows that match the current filter + const currentFilter = document.querySelector('[data-filter].active'); + const filterType = currentFilter ? currentFilter.getAttribute('data-filter') : 'all'; + + // Get rows that match the current filter and search term + let filteredRows = Array.from(voteRows); + if (filterType !== 'all') { + filteredRows = filteredRows.filter(row => row.getAttribute('data-vote-type') === filterType); + } + + // Apply search filter if there's a search term + const searchTerm = searchInput ? searchInput.value.toLowerCase() : ''; + if (searchTerm) { + filteredRows = filteredRows.filter(row => { + const voterName = row.querySelector('td:first-child').textContent.toLowerCase(); + const comment = row.querySelector('td:nth-child(3)').textContent.toLowerCase(); + return voterName.includes(searchTerm) || comment.includes(searchTerm); + }); + } + + // Hide all rows first + voteRows.forEach(row => row.style.display = 'none'); + + // Calculate pagination + const totalRows = filteredRows.length; + const totalPages = Math.max(1, Math.ceil(totalRows / rowsPerPage)); + + // Ensure current page is valid + if (currentPage > totalPages) { + currentPage = totalPages; + } + + // Show only rows for current page + const start = (currentPage - 1) * rowsPerPage; + const end = start + rowsPerPage; + + filteredRows.slice(start, end).forEach(row => row.style.display = ''); + + // Update pagination info + if (startRowElement && endRowElement && totalRowsElement) { + startRowElement.textContent = totalRows > 0 ? start + 1 : 0; + endRowElement.textContent = Math.min(end, totalRows); + totalRowsElement.textContent = totalRows; + } + } + + // Event listeners for pagination + if (prevPageBtn) { + prevPageBtn.addEventListener('click', function(e) { + e.preventDefault(); + if (currentPage > 1) { + currentPage--; + updatePagination(); + } + }); + } + + if (nextPageBtn) { + nextPageBtn.addEventListener('click', function(e) { + e.preventDefault(); + // Get all rows that match the current filter + const currentFilter = document.querySelector('[data-filter].active'); + const filterType = currentFilter ? currentFilter.getAttribute('data-filter') : 'all'; + + // Get rows that match the current filter and search term + let filteredRows = Array.from(voteRows); + if (filterType !== 'all') { + filteredRows = filteredRows.filter(row => row.getAttribute('data-vote-type') === filterType); + } + + // Apply search filter if there's a search term + const searchTerm = searchInput ? searchInput.value.toLowerCase() : ''; + if (searchTerm) { + filteredRows = filteredRows.filter(row => { + const voterName = row.querySelector('td:first-child').textContent.toLowerCase(); + const comment = row.querySelector('td:nth-child(3)').textContent.toLowerCase(); + return voterName.includes(searchTerm) || comment.includes(searchTerm); + }); + } + + const totalRows = filteredRows.length; + const totalPages = Math.max(1, Math.ceil(totalRows / rowsPerPage)); + + if (currentPage < totalPages) { + currentPage++; + updatePagination(); + } + }); + } + + if (rowsPerPageSelect) { + rowsPerPageSelect.addEventListener('change', function() { + rowsPerPage = parseInt(this.value); + currentPage = 1; // Reset to first page + updatePagination(); + }); + } + + // Initialize pagination + if (paginationControls) { + updatePagination(); + } // Initialize tooltips for all elements with title attributes const tooltipElements = document.querySelectorAll('[title]');