Basic pagination
This commit is contained in:
parent
25daed7e3c
commit
a155313cbd
|
@ -1,42 +1,114 @@
|
||||||
var reasonFlags = {};
|
var reasonFlags = {};
|
||||||
|
let currentPage = 1;
|
||||||
|
let itemsPerPage = 5;
|
||||||
|
let data;
|
||||||
|
|
||||||
|
function renderTable(data, reasonFlags) {
|
||||||
|
const tableBody = document.querySelector('#bansTableBody');
|
||||||
|
tableBody.innerHTML = '';
|
||||||
|
const start = (currentPage - 1) * itemsPerPage;
|
||||||
|
const end = start + itemsPerPage;
|
||||||
|
const pageData = data.slice(start, end);
|
||||||
|
|
||||||
|
pageData.forEach(ban => {
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
const banTimestamp = new Date(ban.banTimestamp).toLocaleString();
|
||||||
|
const expiresTimestamp = ban.expiresTimestamp ? new Date(ban.expiresTimestamp).toLocaleString() : 'Never';
|
||||||
|
const reasonsFlagNames = getSetFlags(ban.reasonsFlag, reasonFlags).join(', ');
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${ban.id}</td>
|
||||||
|
<td>${ban.robloxId || 'N/A'}</td>
|
||||||
|
<td>${ban.discordId || 'N/A'}</td>
|
||||||
|
<td>${ban.robloxUsername || 'N/A'}</td>
|
||||||
|
<td>${ban.discordUsername || 'N/A'}</td>
|
||||||
|
<td>${ban.reasonShort || 'N/A'}</td>
|
||||||
|
<td>${ban.reasonLong || 'N/A'}</td>
|
||||||
|
<td>${reasonsFlagNames}</td>
|
||||||
|
<td>${ban.moderator || 'N/A'}</td>
|
||||||
|
<td>${banTimestamp}</td>
|
||||||
|
<td style="color: ${ban.expiresTimestamp && new Date(ban.expiresTimestamp) < new Date() ? 'green' : ''};">
|
||||||
|
${expiresTimestamp}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="/admin/edit/${ban.id}" class="btn btn-primary btn-sm">Edit</a>
|
||||||
|
</td>
|
||||||
|
`;
|
||||||
|
tableBody.appendChild(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const itemsToShowDropdown = document.querySelector('#itemsToShowDropdown');
|
||||||
|
const itemsOptions = [5, 10, 20, 30, 40, 50, 100, 200, 500, 1000];
|
||||||
|
|
||||||
|
itemsOptions.forEach(option => {
|
||||||
|
const optionElement = document.createElement('option');
|
||||||
|
optionElement.value = option;
|
||||||
|
optionElement.textContent = option;
|
||||||
|
itemsToShowDropdown.appendChild(optionElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
itemsToShowDropdown.addEventListener('change', (e) => {
|
||||||
|
const selectedValue = e.target.value;
|
||||||
|
itemsPerPage = parseInt(selectedValue, 10) || 5;
|
||||||
|
currentPage = 1;
|
||||||
|
renderTable(data, reasonFlags);
|
||||||
|
setupPagination(data);
|
||||||
|
console.log('Items per page:', itemsPerPage);
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupPagination(data) {
|
||||||
|
const pagination = document.querySelector('#pagination');
|
||||||
|
pagination.innerHTML = '';
|
||||||
|
const totalPages = Math.ceil(data.length / itemsPerPage);
|
||||||
|
|
||||||
|
const ul = document.createElement('ul');
|
||||||
|
ul.classList.add('pagination');
|
||||||
|
|
||||||
|
const createPageItem = (page, text = page) => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.classList.add('page-item');
|
||||||
|
if (page === currentPage) {
|
||||||
|
li.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.classList.add('page-link');
|
||||||
|
a.textContent = text;
|
||||||
|
a.href = '#';
|
||||||
|
a.addEventListener('click', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
currentPage = page;
|
||||||
|
renderTable(data, reasonFlags);
|
||||||
|
setupPagination(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
li.appendChild(a);
|
||||||
|
return li;
|
||||||
|
};
|
||||||
|
|
||||||
|
ul.appendChild(createPageItem(1, 'First'));
|
||||||
|
ul.appendChild(createPageItem(Math.max(1, currentPage - 1), 'Prev'));
|
||||||
|
|
||||||
|
for (let i = Math.max(1, currentPage - 2); i <= Math.min(totalPages, currentPage + 2); i++) {
|
||||||
|
ul.appendChild(createPageItem(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.appendChild(createPageItem(Math.min(totalPages, currentPage + 1), 'Next'));
|
||||||
|
ul.appendChild(createPageItem(totalPages, 'Last'));
|
||||||
|
|
||||||
|
pagination.appendChild(ul);
|
||||||
|
}
|
||||||
|
|
||||||
fetch('/api/v1/info')
|
fetch('/api/v1/info')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
reasonFlags = data.reasonFlags;
|
reasonFlags = data.reasonFlags;
|
||||||
console.log('Reason Flags:', reasonFlags);
|
console.log('Reason Flags:', reasonFlags);
|
||||||
fetch('/admin/api/bans')
|
fetch('/admin/api/bans')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const tableBody = document.querySelector('#bansTableBody');
|
renderTable(data, reasonFlags);
|
||||||
data.forEach(ban => {
|
setupPagination(data);
|
||||||
const row = document.createElement('tr');
|
})
|
||||||
const banTimestamp = new Date(ban.banTimestamp).toLocaleString();
|
.catch(error => console.error('Error fetching ban data:', error));
|
||||||
const expiresTimestamp = ban.expiresTimestamp ? new Date(ban.expiresTimestamp).toLocaleString() : 'Never';
|
|
||||||
const reasonsFlagNames = getSetFlags(ban.reasonsFlag, reasonFlags).join(', ');
|
|
||||||
console.log(ban.reasonsFlag)
|
|
||||||
console.log(reasonFlags)
|
|
||||||
console.log(getSetFlags(ban.reasonsFlag, reasonFlags))
|
|
||||||
row.innerHTML = `
|
|
||||||
<td>${ban.id}</td>
|
|
||||||
<td>${ban.robloxId || 'N/A'}</td>
|
|
||||||
<td>${ban.discordId || 'N/A'}</td>
|
|
||||||
<td>${ban.robloxUsername || 'N/A'}</td>
|
|
||||||
<td>${ban.discordUsername || 'N/A'}</td>
|
|
||||||
<td>${ban.reasonShort || 'N/A'}</td>
|
|
||||||
<td>${ban.reasonLong || 'N/A'}</td>
|
|
||||||
<td>${reasonsFlagNames}</td>
|
|
||||||
<td>${ban.moderator || 'N/A'}</td>
|
|
||||||
<td>${banTimestamp}</td>
|
|
||||||
<td style="color: ${ban.expiresTimestamp && new Date(ban.expiresTimestamp) < new Date() ? 'green' : ''};">
|
|
||||||
${expiresTimestamp}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="/admin/edit/${ban.id}" class="btn btn-primary btn-sm">Edit</a>
|
|
||||||
</td>
|
|
||||||
`;
|
|
||||||
tableBody.appendChild(row);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Error fetching ban data:', error));
|
|
||||||
})
|
})
|
||||||
.catch(error => console.error('Error fetching reason flags:', error));
|
.catch(error => console.error('Error fetching reason flags:', error));
|
|
@ -177,8 +177,8 @@ router.post('/import', authenticate, upload.single('fileInput'), async (req, res
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
// This is a text file, split by "x/"", get [0], then split by / and get the last element, that will be an ID. All other values are static.
|
// This is a text file, split by "x/"", get [0], then split by / and get the last element, that will be an ID. All other values are static.
|
||||||
const robloxId = line.split('x/')[0].split('/').pop();
|
const robloxId = line.split('x/')[0].split('/').pop();
|
||||||
let reasonLong = line.split('/profile ')[1];
|
let reasonLong = line.split('/profile ')[1] || "Undefined";
|
||||||
if (reasonLong.length > 255) {
|
if (reasonLong?.length > 255) {
|
||||||
reasonLong = reasonLong.substring(0, 2048);
|
reasonLong = reasonLong.substring(0, 2048);
|
||||||
}
|
}
|
||||||
const reasonShort = "Listed by MFD";
|
const reasonShort = "Listed by MFD";
|
||||||
|
|
|
@ -39,6 +39,13 @@
|
||||||
</nav>
|
</nav>
|
||||||
<div class="container mt-5">
|
<div class="container mt-5">
|
||||||
<h2 class="mb-4 d-inline">Bans</h2>
|
<h2 class="mb-4 d-inline">Bans</h2>
|
||||||
|
<div id="pagination" class="mb-4"></div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="itemsToShowDropdown" class="form-label">Items to show:</label>
|
||||||
|
<select id="itemsToShowDropdown" class="form-select" style="width: auto; display: inline-block;">
|
||||||
|
<!-- Options will be populated by the script -->
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-dark table-striped">
|
<table class="table table-dark table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
Loading…
Reference in a new issue