Move spelling test results from Spelling panel into Gradebook
Adds a GET /api/spelling-tests endpoint that returns all standalone test results grouped by student. The Gradebook panel now shows a "Spelling Test History" section below the course gradebook table. Removed the "Test results" section from the Spelling panel left column. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
774979f2e4
commit
183b43b452
3 files changed
+46
-25
No files matched your search
+2
-2
@@ -283,6 +283,8 @@
|
||||
<button id="gradebook-csv-btn" class="secondary">⬇ Export CSV</button>
|
||||
</div>
|
||||
<div id="gradebook-table"></div>
|
||||
<h2>Spelling Test History</h2>
|
||||
<div id="spelling-tests-table"></div>
|
||||
<div id="history-modal" class="modal" hidden>
|
||||
<div class="modal-box">
|
||||
<h3 id="history-modal-title">Attempt History</h3>
|
||||
@@ -305,8 +307,6 @@
|
||||
<button type="button" id="list-show-hidden" class="secondary small" hidden>Show hidden</button>
|
||||
</div>
|
||||
<div id="list-rows"></div>
|
||||
<h2>Test results</h2>
|
||||
<div id="results-area"></div>
|
||||
</div>
|
||||
<div class="panel-col">
|
||||
<div class="toggle-btns">
|
||||
|
||||
+31
-23
@@ -1211,6 +1211,37 @@ async function loadGradebookPanel() {
|
||||
const courses = await api('/api/admin/courses');
|
||||
$('#gradebook-course').innerHTML = courses.map((c) => `<option value="${c.id}">${esc(c.name)}</option>`).join('');
|
||||
if (courses.length) renderGradebook(courses[0].id);
|
||||
loadSpellingTests();
|
||||
}
|
||||
|
||||
async function loadSpellingTests() {
|
||||
const { students } = await api('/api/spelling-tests');
|
||||
const container = $('#spelling-tests-table');
|
||||
const active = students.filter((s) => s.tests.length > 0);
|
||||
if (!active.length) {
|
||||
container.innerHTML = `<p class="hint">No spelling tests recorded yet.</p>`;
|
||||
return;
|
||||
}
|
||||
container.innerHTML = active
|
||||
.map((s) => {
|
||||
const rows = s.tests
|
||||
.map((t) => {
|
||||
const pct = Math.round((t.score / t.total) * 100);
|
||||
return `<tr>
|
||||
<td>${new Date(t.at + 'Z').toLocaleDateString()}</td>
|
||||
<td>${esc(t.list)}</td>
|
||||
<td class="${pct >= 80 ? 'score-good' : 'score-bad'}">${t.score}/${t.total} (${pct}%)</td>
|
||||
<td><button data-print="${t.id}">🖨 Print</button></td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
return `<div class="results-student"><h3>${esc(s.emoji)} ${esc(s.name)}</h3>
|
||||
<table class="results"><tr><th>Date</th><th>List</th><th>Score</th><th></th></tr>${rows}</table></div>`;
|
||||
})
|
||||
.join('');
|
||||
container.querySelectorAll('[data-print]').forEach((btn) =>
|
||||
btn.addEventListener('click', () => printSpellingReport(btn.dataset.print))
|
||||
);
|
||||
}
|
||||
$('#gradebook-course').addEventListener('change', () => renderGradebook($('#gradebook-course').value));
|
||||
$('#gradebook-csv-btn').addEventListener('click', () => {
|
||||
@@ -1281,7 +1312,6 @@ async function loadSpelling() {
|
||||
cachedStudents = overview.students;
|
||||
renderAssignRows(overview.students);
|
||||
renderLists(lists);
|
||||
renderResults(overview.students);
|
||||
}
|
||||
|
||||
function renderAssignRows(students) {
|
||||
@@ -1546,28 +1576,6 @@ $('#list-bulk-clear').addEventListener('click', () => {
|
||||
$('#list-bulk-status').textContent = '';
|
||||
});
|
||||
|
||||
function renderResults(students) {
|
||||
$('#results-area').innerHTML = students
|
||||
.map((s) => {
|
||||
if (s.tests.length === 0) return `<div class="results-student"><h3>${esc(s.emoji)} ${esc(s.name)}</h3><p class="hint">No tests yet.</p></div>`;
|
||||
const rows = s.tests
|
||||
.map((t) => {
|
||||
const pct = Math.round((t.score / t.total) * 100);
|
||||
return `<tr>
|
||||
<td>${new Date(t.at + 'Z').toLocaleDateString()}</td>
|
||||
<td>${esc(t.list)}</td>
|
||||
<td class="${pct >= 80 ? 'score-good' : 'score-bad'}">${t.score}/${t.total} (${pct}%)</td>
|
||||
<td><button data-print="${t.id}">🖨 Print</button></td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
return `<div class="results-student"><h3>${esc(s.emoji)} ${esc(s.name)}</h3>
|
||||
<table class="results"><tr><th>Date</th><th>List</th><th>Score</th><th></th></tr>${rows}</table></div>`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
document.querySelectorAll('[data-print]').forEach((btn) => btn.addEventListener('click', () => printSpellingReport(btn.dataset.print)));
|
||||
}
|
||||
|
||||
function printSpellingWorksheet(name, words) {
|
||||
const rows = words
|
||||
|
||||
Reference in new issue
Block a user