diff --git a/client/db/set-list/index.html b/client/db/set-list/index.html
index b7009f877..228568889 100644
--- a/client/db/set-list/index.html
+++ b/client/db/set-list/index.html
@@ -18,12 +18,12 @@
- | Set Name |
- Difficulty |
- Standard |
- # of Packets |
- # of Tossups |
- # of Bonuses |
+ Set Name |
+ Difficulty |
+ Standard |
+ # of Packets |
+ # of Tossups |
+ # of Bonuses |
diff --git a/client/db/set-list/index.js b/client/db/set-list/index.js
index 1adb67261..f33cd1e5c 100644
--- a/client/db/set-list/index.js
+++ b/client/db/set-list/index.js
@@ -1,21 +1,67 @@
+let sets = [];
+let sortKey = null;
+let sortAscending = true;
+
+function renderTable () {
+ const table = document.getElementById('set-metadata-list');
+ table.textContent = '';
+ sets.forEach(({ _id, setName, difficulty, standard, packetsCount, tossupsCount, bonusesCount }) => {
+ const row = table.insertRow(-1);
+ const a = document.createElement('a');
+ a.href = `../set/?_id=${_id}`;
+ a.textContent = setName;
+ row.insertCell(-1).appendChild(a);
+ row.insertCell(-1).textContent = difficulty;
+ row.insertCell(-1).textContent = standard;
+ row.insertCell(-1).textContent = packetsCount ?? '-';
+ row.insertCell(-1).textContent = tossupsCount ?? '-';
+ row.insertCell(-1).textContent = bonusesCount ?? '-';
+ });
+}
+
+function updateSortIcons () {
+ document.querySelectorAll('th[data-sort-key]').forEach(th => {
+ const icon = th.querySelector('i.bi');
+ if (th.dataset.sortKey !== sortKey) {
+ icon.className = 'bi bi-arrow-down-up text-muted';
+ } else {
+ icon.className = sortAscending ? 'bi bi-caret-up-fill' : 'bi bi-caret-down-fill';
+ }
+ });
+}
+
+function compareRows (a, b, key) {
+ const valueA = a[key];
+ const valueB = b[key];
+ if (valueA == null && valueB == null) return 0;
+ if (valueA == null) return -1;
+ if (valueB == null) return 1;
+ if (typeof valueA === 'string') return valueA.localeCompare(valueB);
+ if (valueA < valueB) return -1;
+ if (valueA > valueB) return 1;
+ return 0;
+}
+
+function sortByKey (key) {
+ sortAscending = sortKey === key ? !sortAscending : true;
+ sortKey = key;
+ sets.sort((a, b) => compareRows(a, b, key) * (sortAscending ? 1 : -1));
+ renderTable();
+ updateSortIcons();
+}
+
+document.querySelectorAll('th[data-sort-key]').forEach(th => {
+ th.addEventListener('click', () => sortByKey(th.dataset.sortKey));
+});
+updateSortIcons();
+
await fetch('/api/db-explorer/set-metadata?' + new URLSearchParams({ includeCounts: false }))
.then(res => res.json())
.then(data => data.data)
.then(data => {
document.getElementById('spinner').classList.add('d-none');
- const table = document.getElementById('set-metadata-list');
- data.forEach(({ _id, setName, difficulty, standard }) => {
- const row = table.insertRow(-1);
- const a = document.createElement('a');
- a.href = `../set/?_id=${_id}`;
- a.textContent = setName;
- row.insertCell(-1).appendChild(a);
- row.insertCell(-1).textContent = difficulty;
- row.insertCell(-1).textContent = standard;
- row.insertCell(-1).textContent = '-';
- row.insertCell(-1).textContent = '-';
- row.insertCell(-1).textContent = '-';
- });
+ sets = data;
+ renderTable();
});
fetch('/api/db-explorer/set-metadata?' + new URLSearchParams({ includeCounts: true }))
@@ -23,11 +69,16 @@ fetch('/api/db-explorer/set-metadata?' + new URLSearchParams({ includeCounts: tr
.then(data => data.data)
.then(data => {
document.getElementById('spinner').classList.add('d-none');
- const table = document.getElementById('set-metadata-list');
- const rows = table.rows;
- for (let i = 0; i < data.length; i++) {
- rows[i].cells[3].textContent = data[i].packetsCount;
- rows[i].cells[4].textContent = data[i].tossupsCount;
- rows[i].cells[5].textContent = data[i].bonusesCount;
+ const countsById = new Map(data.map(set => [set._id, set]));
+ sets.forEach(set => {
+ const counts = countsById.get(set._id);
+ if (!counts) return;
+ set.packetsCount = counts.packetsCount;
+ set.tossupsCount = counts.tossupsCount;
+ set.bonusesCount = counts.bonusesCount;
+ });
+ if (['packetsCount', 'tossupsCount', 'bonusesCount'].includes(sortKey)) {
+ sets.sort((a, b) => compareRows(a, b, sortKey) * (sortAscending ? 1 : -1));
}
+ renderTable();
});