- Export any course as a .json bundle (GET /api/admin/courses/:id/export)
- Import a .json bundle as a new course (POST /api/admin/import-course)
- Import one or more unit .docx files directly in the browser — server
parses each file with mammoth, extracts Week N: headings as lesson
items and the Unit Quiz section as a graded quiz with answer key
(POST /api/admin/import-course-docx, multer memory storage)
- Admin UI: Export button on course detail; Import card with JSON and
Word docs tabs; multi-file picker for docx uploads
- scripts/import-kitchen-course.js: one-time converter that produced
the Kitchen, Tools & Electrical Skills course JSON bundle (already
imported as course id 3: 8 units, 44 items)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Admin enters Across/Down words and clues; server auto-generates the grid
using a backtracking placement algorithm (longest-first, intersection-based).
Students fill in the interactive grid with click-to-select, direction toggle,
arrow-key navigation, and Tab-to-next-word. Auto-graded per word on submit,
with correct/wrong color highlighting on the results view. Includes a print
worksheet option for blank paper practice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of embedding an iframe, mammoth HTML is inserted straight into
the contenteditable body so the admin can edit it like any other content.
A download link to the original .docx sits above the content.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch to Georgia to better match Word's serif rendering
- Explicit font-weight:normal on body/p so mammoth's <strong> wrapping
doesn't bleed into paragraph text
- Tighter heading/paragraph spacing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Removed narrow max-width/margin from generated HTML page
- iframe now spans full card width (100%)
- onload JS auto-sizes iframe height to content so nothing is cut off
- Falls back to 500px if cross-origin restriction ever applies
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the <iframe> with an inline <div> containing the mammoth HTML.
Content now flows full-width with the page instead of being cramped in
a fixed-height scrolling box. Download link still available below.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On upload, mammoth converts the doc to a styled HTML page saved alongside
the .docx. The item body gets an <iframe> pointing to the HTML so students
see the document inline. A download link below gives access to the original.
Falls back to a plain download link if HTML conversion fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Instead of parsing .docx content via mammoth and inserting raw text/HTML,
the import flow now saves the file to data/attachments/ (UUID filename) and
inserts an <a> link into the item body so students can open/download the doc.
- Added GET /api/attachments/:filename (no PIN — students access directly)
- Added POST /api/admin/upload-attachment (PIN required)
- Removed mammoth dependency from server
- Updated admin.js import handler to POST to new endpoint and set link HTML
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove all AI processing from the import-docx endpoint. Instead:
- Convert the .docx to HTML with mammoth.convertToHtml (preserves
bold, headings, lists, etc.) — the result goes straight into the
item body and renders in the lesson viewer
- Extract raw text in parallel to pick the document title from the
first non-empty line
- No external services, no AI, works on the deployed server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The import-docx endpoint was hardcoded to local Ollama, which fails
on the deployed server where Ollama isn't running. Now mirrors the
image scan logic: tries local first, falls back to Ollama Cloud if
configured, using the same scan_primary setting.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The old import scanned a hardcoded Seafile CloudStorage path that only
worked on one specific machine. Replaced with a standard <input type=file>
browser picker that reads the .docx as base64 and uploads it directly, so
the feature works everywhere. Server endpoint now accepts either a base64
payload or the legacy path. Also fixed a crash where resetImportSection()
still referenced the removed select element, which was breaking the item
editor for all item types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gradebook now groups items by unit with collapsible cards (same card
style as course detail) and a Course overall summary table at the bottom
- server.js: add unit_id/unit_name to gradebook API so items can be grouped
- Course detail: preserve which units are open and scroll position across
any in-place re-render (add unit, delete unit, save meta, return from
item editor) — no more jumping to the top with everything reset
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gradebook: period dropdown (all time / 30 / 90 days) and CSV export for
Spelling Test History section
- Student portal spelling tab: shows last 10 tests as a Recent Tests list
- Planner: completed standalone spelling tests appear as read-only ⭐ badges
on the day they were taken (week and month views)
- Removed dead s.tests query from /api/overview (now served by dedicated endpoints)
- New endpoints: GET /api/spelling-tests/csv, GET /api/students/:id/tests,
GET /api/admin/students/:id/tests-range
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- Assign → button on each list row opens a popup to pick a kid directly
without scrolling up to the assignment dropdowns
- Hide/Unhide button on built-in lists (stored in localStorage) keeps
UNGROUPED clean; Show hidden toggle reveals them dimmed when needed
- Mastery progress bar on each kid showing X/Y words mastered for their
current assigned list (server now returns listProgress in /api/overview)
- Filter-lists / filter-decks search input for fast lookup by name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- group_name column added to lists and decks tables
- GET/POST/PUT endpoints for both include group_name
- Admin Spelling and Flashcards panels render items grouped under
labeled section headers (e.g. Bible 6, Bible 8) with ungrouped
items shown last
- Group input in each form has datalist autocomplete from existing groups
- Edit/copy populates the group field; Clear resets it
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- POST /api/courses/:id/duplicate deep-copies a course with all units,
items, and quiz questions; opens the copy immediately for renaming
- Roster changed from broken vertical stack to horizontal chip-pills
(fixes admin-card label override that was collapsing inline-flex)
- item-row padding reduced for tighter lists throughout admin
- Courses and Kids admin panels now use a 2-column auto-fill grid
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Week print: tasks grouped by day, each showing course name, type,
and full assignment body text. Month print: course name in calendar
cells + an Assignment Detail section below the calendar with body text.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Course detail API now returns item body text and quiz questions.
Print course renders body paragraphs and numbered quiz questions
with lettered choices (correct answers marked with ✓).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Month view toggle in planner (Mon-Fri calendar grid, 4-5 weeks)
- Prev/Next navigate by month when in month mode
- Print month report (landscape calendar layout)
- Print course button on course detail (all units + items)
- New GET /api/schedule-range endpoint for arbitrary date spans
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Streak tracker: server-side streak counting per kid, celebration overlay
when all today's tasks are done for the first time that day
- Kid themes: 5 colour palettes (blue/green/purple/orange/pink), picked via
colour dots on the kid home screen; parents can set it from the Kids panel
- Grading badge: Grading nav pill turns red and shows a pending count
- Print worksheets: 🖨 Worksheet button per word list in admin Spelling panel;
kids also get "Print my words" on the Spelling tab
- Parent feedback: gold 💬 badge on Today rows with unread comments; more
prominent callout styling inside the assignment view
- Planner drag-and-drop: tasks can be dragged between days; PATCH
/api/schedule/:id moves the task, drop zones highlight on hover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Practice: fire streak badge, first-letter hint on wrong answers, missed-words drill session after practice completes.
Test: audio-only mode with listening state before input appears, larger re-read button.
Words: definition field (DB migration + admin editor + TTS playback).
TTS: replace speechSynthesis with local Piper via /api/tts, WAV cached in data/tts-cache, falls back to browser voice when Piper is not installed.
Dockerfile: switched to node:26-slim, installs Piper binary + en_US-lessac-medium voice.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New "Auto-schedule a course" section in the Weekly Planner lets you pick
a course, start date, and items-per-day, then fills the planner in order
skipping weekends. POST /api/schedule/auto handles the logic server-side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Evidence on assignments: photo upload + notes + student self-note (needs help / not sure)
- Evidence required/optional/none flag per item; grading queue shows evidence with lightbox thumbnail
- Parent comment field when grading; shown to student on graded items
- Offline tasks: 3-state status (not started → in progress → done) with inline evidence form
- Retake policy per item: latest / highest / average — gradebook computes effective score accordingly
- Grading queue expanded to include lessons and practices (not just assignments) when evidence present
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- allow_retakes flag on items: quizzes, spelling tests, and assignments can all be retaken
- Quiz templates: save any quiz as a reusable template and load it into new items
- Score history: every quiz/test attempt logged to submission_history; click a gradebook score to see all attempts
- Due dates: optional due date per item, shown in course view and gradebook (overdue flagged with ⚠️)
- Gradebook CSV export: one-click download of any course gradebook
- Prerequisites: lock an item until a prior one is completed; locked items show 🔒 in course view
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>