feat: web admin UI for lesson management (#7) #14

Merged
sscoble merged 2 commits from issue-7-admin-ui into main 2026-05-16 04:50:30 +00:00
Owner

What

Adds admin-ui/ directory with a Node.js Express web admin for managing Jellyfin Lessons.

Files

  • admin-ui/server.js — Express server on port 3099 with REST API
  • admin-ui/public/index.html — Single-page admin UI
  • admin-ui/package.json — Dependencies and start script

Features

  • REST API: CRUD for lessons with media items, Typst compile endpoint
  • Shared DB: Uses same SQLite path as the Jellyfin plugin (~/.local/share/jellyfin-lessons/lessons.db)
  • Admin UI: Sidebar grouped by grade/subject, lesson editor form
  • Typst Preview: Live compilation via typst compile subprocess
  • Media Items: Add/remove Jellyfin item UUIDs with sort order
  • CORS enabled for local development

How to run

cd admin-ui && npm install && npm start
# Open http://localhost:3099

Closes #7

## What Adds `admin-ui/` directory with a Node.js Express web admin for managing Jellyfin Lessons. ### Files - `admin-ui/server.js` — Express server on port 3099 with REST API - `admin-ui/public/index.html` — Single-page admin UI - `admin-ui/package.json` — Dependencies and start script ### Features - **REST API:** CRUD for lessons with media items, Typst compile endpoint - **Shared DB:** Uses same SQLite path as the Jellyfin plugin (`~/.local/share/jellyfin-lessons/lessons.db`) - **Admin UI:** Sidebar grouped by grade/subject, lesson editor form - **Typst Preview:** Live compilation via `typst compile` subprocess - **Media Items:** Add/remove Jellyfin item UUIDs with sort order - **CORS enabled** for local development ### How to run ```bash cd admin-ui && npm install && npm start # Open http://localhost:3099 ``` Closes #7
sscoble added 1 commit 2026-05-16 04:43:46 +00:00
- REST API server on port 3099 with better-sqlite3
- CRUD endpoints for lessons, Typst compile endpoint
- Shared DB path with plugin (~/.local/share/jellyfin-lessons/lessons.db)
- Single-page admin UI with sidebar (grouped by grade/subject)
- Lesson editor with Typst source editing, live preview via compile
- Media items management (Jellyfin item UUIDs with sort order)
- CORS enabled for local dev
First-time contributor

Reviewed — solid implementation. Two fixes needed:

✅ Good

  • Clean Express API with proper error handling
  • Typst compile via temp files with cleanup
  • Shared DB path with plugin
  • Transaction-wrapped upsert

❌ Fixes required

  1. Schema mismatch with plugin (#4) — The plugin's LessonStore uses id TEXT PRIMARY KEY (UUIDs) and lesson_media as the join table name. The admin UI's schema uses id INTEGER PRIMARY KEY AUTOINCREMENT and media_items. These need to match. Sync to the plugin's schema exactly:

    • id TEXT PRIMARY KEY (generate UUIDs)
    • Table: lesson_media not media_items
    • Columns: lesson_id, jellyfin_item_id, sort_order (exactly as plugin uses)
  2. npm packages not in Nix — The server depends on express and better-sqlite3 installed via npm. To integrate with the flake, add a shell.nix or update the flake to include these as runtime deps. Minimum: document in README that nix develop provides node but npm install is needed separately. Better: wrap in a flake package that does the npm install at build time.

Fix the schema first (blocker — data corruption risk), then we can handle the Nix integration in issue #8.

Reviewed — solid implementation. Two fixes needed: ### ✅ Good - Clean Express API with proper error handling - Typst compile via temp files with cleanup - Shared DB path with plugin - Transaction-wrapped upsert ### ❌ Fixes required 1. **Schema mismatch with plugin (#4)** — The plugin's LessonStore uses `id TEXT PRIMARY KEY` (UUIDs) and `lesson_media` as the join table name. The admin UI's schema uses `id INTEGER PRIMARY KEY AUTOINCREMENT` and `media_items`. These need to match. Sync to the plugin's schema exactly: - `id TEXT PRIMARY KEY` (generate UUIDs) - Table: `lesson_media` not `media_items` - Columns: `lesson_id`, `jellyfin_item_id`, `sort_order` (exactly as plugin uses) 2. **npm packages not in Nix** — The server depends on `express` and `better-sqlite3` installed via npm. To integrate with the flake, add a shell.nix or update the flake to include these as runtime deps. Minimum: document in README that `nix develop` provides node but `npm install` is needed separately. Better: wrap in a flake package that does the npm install at build time. Fix the schema first (blocker — data corruption risk), then we can handle the Nix integration in issue #8.
sscoble added 1 commit 2026-05-16 04:50:23 +00:00
Schema now matches plugin Data/LessonStore.cs exactly:
- id TEXT PRIMARY KEY (UUIDs)
- lesson_media table (not media_items)
- Full column set with NOT NULL constraints matching plugin

Addresses PR #14 review feedback.
First-time contributor

Schema mismatch fixed. Now matches plugin exactly:

  • id TEXT PRIMARY KEY (UUIDs via generateId())
  • lesson_media table name
  • All column constraints match Data/LessonStore.cs

Re-approving.

Schema mismatch fixed. Now matches plugin exactly: - `id TEXT PRIMARY KEY` (UUIDs via `generateId()`) - `lesson_media` table name - All column constraints match `Data/LessonStore.cs` Re-approving.
sscoble merged commit 68c6861e70 into main 2026-05-16 04:50:30 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: sscoble/jellyfin-lessons#14
No description provided.