Commit graph

407 commits

Author SHA1 Message Date
Daniel
0fa8d0a689 feat: shareable quiz links, moderated comments and AI authoring
Quiz share links replace the PIN copy with a public /share/{token} landing page; owners can enable/revoke without showing the full link. Moderated article/question comments with approval flow, bounds and rate limits. Educator AI article drafts/refine and private card generation with Celery job polling. Migrations f2a1c9d4e801 and g4b7e2f5a903. 50 backend and 85 frontend tests pass.
2026-09-07 17:10:08 +02:00
Daniel
6c85f8b4a9 fix: resolve article review findings
Escape raw HTML in article markdown, honor section deep links, filter card link listings by bank visibility and publication status, validate source sections. 44 backend and 77 frontend tests pass.
2026-09-07 16:44:07 +02:00
Daniel
d5269d7772 feat: rename Flashcards to Cards and add card-question linking UI
Orthobullets-style Cards naming, per-card link panel to attach/unlink bank questions, article linked-content counts. New FlashcardsPage test suite; 75 frontend tests pass with build.
2026-09-07 16:32:21 +02:00
Daniel
02be9a6899 build: pin litellm 1.28.13 after 1.27.8 was yanked from PyPI 2026-09-07 16:18:35 +02:00
Daniel
325f7f400f feat: linked topic articles and card associations
Draft/published article library with stable section IDs, breadcrumbs, link remediation, question and card associations, manual card creation and side-by-side/mobile-drawer reading. Migration e8d4f1a27c93. Verified 42 deployed-image backend tests, 72 frontend tests/build and PostgreSQL migration round-trip.
2026-09-07 15:16:48 +02:00
Daniel
1ce3eec7cb feat: authorize tutor context and protect uploaded media
Tutor questions require owned selected attempts; similarity context filters eligibility before ranking. Uploads move to a permission-aware boundary with reference ACLs, canonical legacy aliases, pre-mutation attachment checks and card-aware moderator rules. Nginx stops caching media and supplies native byte ranges. Verified 37 deployed-image backend tests, 69 frontend tests/build, real pgvector/Nginx/browser checks, and two independent reviews.
2026-09-07 15:04:00 +02:00
Daniel
c605178cbc docs: record accepted quiz runner review 2026-09-07 04:22:03 +02:00
Daniel
c630b0270d fix: preserve saved quiz progress across resume failures
Block Start after failed resume, retry saved state, re-read reused-attempt progress, surface cache failures and prevent leaving on failed save. Handle nullable review settings and register lab model with Alembic. Verified 25 deployed-image backend tests, 53 frontend tests/build and PostgreSQL schema round-trip.
2026-09-07 03:34:55 +02:00
Daniel
a3a6ef7995 feat: redesign quiz runner and add study tools
Add Orthobullets-inspired numbered-answer UI, explicit study response confirmation, response statistics, review navigation, safe calculator, keyboard controls and sourced educator lab references. Persist attempt mode to prevent query-flag exam disclosure. Combined deployed-image backend suite (22), frontend suite (48), build and synthetic desktop/mobile browser checks pass. PostgreSQL round-trip and independent review remain release gates; no production deployment.
2026-09-07 03:10:23 +02:00
Daniel
38f3fb8250 fix: remove Turnstile from quiz password login
Remove the challenge from standalone and landing login plus backend verification; retain registration/contact protection and existing password, email verification, SSO and login rate-limit checks. Verified 18 backend tests in deployed image and 17 frontend tests plus build.
2026-09-07 02:54:12 +02:00
Daniel
f696b99569 fix: close custom-test review gaps and verify grading
Handle ownerless question revocation, legacy hide sharing, private deletion, selected-set grading including skips, UI validation/reparent/delete safeguards and offline-safe hierarchy migration. Verified 14 backend tests in deployed image, 13 frontend tests/build and real disposable PostgreSQL migration round-trip. Related tutor/image privacy work remains before deployment.
2026-09-07 02:07:58 +02:00
Daniel
affd7177b5 feat: add category-based custom tests and permission-safe sharing 2026-09-07 01:17:42 +02:00
Daniel
2cdfe71707 docs: record revamp execution authorization and defaults 2026-09-07 01:00:50 +02:00
Daniel
bdc2066e72 docs: track Orthobullets-inspired quiz revamp scope 2026-09-07 00:51:43 +02:00
Daniel
3cf21d4438 chore: preserve pre-revamp local changes
Recovery snapshot of the existing worktree before the Orthobullets-inspired revamp. Includes explanation images, classification snapshots, quiz visibility/resume fixes, quiz codes, TTS options and bot formatting. Secret heuristic and Python syntax checks passed; not a release or full behavioral validation.
2026-09-07 00:50:35 +02:00
Daniel
e7f91e5e5b fix: scope quiz logging and bot status 2026-06-06 00:01:44 +02:00
Daniel
95de56d81b Improve quiz note and navigation layout
All checks were successful
Mobile Android Release / android-release (push) Successful in 1m33s
2026-05-14 17:30:08 +02:00
Daniel
55713902ed Make MyNote draggable
All checks were successful
Mobile Android Release / android-release (push) Successful in 1m32s
2026-05-12 18:39:50 +02:00
Daniel
9f97218f39 Add persistent MyNote for quizzes
All checks were successful
Mobile Android Release / android-release (push) Successful in 1m32s
2026-05-12 17:51:23 +02:00
Daniel
4b75edef4c Remove highlight toast notifications 2026-05-12 17:02:41 +02:00
Daniel
e2c070b70b Refine quiz image zoom increments 2026-05-12 16:44:11 +02:00
Daniel
dd959371d1 Add dashboard in-progress quizzes 2026-05-12 16:41:44 +02:00
Daniel
d4ef94a117 Remove dashboard document management link 2026-05-12 16:38:33 +02:00
Daniel
17b0f06037 Add quiz image zoom controls 2026-05-12 16:36:53 +02:00
Daniel
4f347a18a3 Ignore local Firecrawl cache 2026-05-12 16:20:10 +02:00
Daniel
ffeb35922a Improve quiz UX and add Telegram bot 2026-05-12 15:57:27 +02:00
Daniel
dcab250223 Use explicit Android build actions 2026-05-12 01:25:40 +02:00
Daniel
a80effe9c6 Allow manual Android release tag 2026-05-12 01:07:24 +02:00
Daniel
9b691eb2fd Use local Forgejo runner for Android build 2026-05-12 01:05:37 +02:00
Daniel
fdebda993c Improve quiz TTS and Android release build
Some checks failed
Mobile Android Release / android-release (push) Failing after 1s
2026-05-12 01:01:01 +02:00
Daniel
d59c8bed6f Remove coach modes and improve quiz audio 2026-05-10 01:24:06 +02:00
Daniel
67a90f73f5 Landing page: add Bedside calculators bullet + tile to AI Scribe section
Adds a 6th feature bullet (with NEW badge) and a 7th icon tile for the
pediatric calculators + bedside emergency reference that ships with the
Pediatric AI Scribe app. Mentions weight-based dosing, sepsis, status
epilepticus, RSI, burns, anaphylaxis pathways.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 02:59:34 +02:00
Daniel
422fb1c14f Fix uncategorize quiz — omit category_id param when null
Previously sent ?category_id= (empty string) which FastAPI rejects
with 422 validation error when parsing as int.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 21:34:50 +02:00
Daniel
a31388ed17 Revert Settings redesign, keep only abridged documents list
- Restore original single-column 600px layout
- Keep documents abridged to 5 most recent with 'Show all' button

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 20:27:29 +02:00
Daniel
0489bb49a1 Redesign Settings page — responsive grid, abridged docs, less scroll
- Page max-width 1100px (from 600px) for desktop side-by-side layout
- CSS grid auto-fits cards at minmax(320px, 1fr) — 1 col mobile, 2-3 cols desktop
- Cards align to top (alignItems: start) so short ones don't stretch
- Password change hidden behind a <details> summary to reduce scroll
- Notifications + Appearance + Admin compacted (smaller padding, tighter layout)
- Documents section: shows 5 most recent, 'Show all N' button expands inline,
  'Show less' collapses — no separate page needed
- Long filenames truncate with ellipsis
- Removed redundant descriptive text, shortened labels

Mobile: single column stack, preserves all functionality.
Desktop: 2-3 columns depending on viewport width.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 20:24:41 +02:00
Daniel
2a0dd56f95 Add ai_answer extraction + broader ai_decide sampling + flashcard title edit
ai_decide now samples 4 points across the section (start, 1/3, 2/3, end)
instead of just the first 30 + last 20 pages. This gives accurate strategy
detection on large documents where the answer format might be deeper in.

New ai_answer extraction mode:
- Extracts questions from Q&A-format PDFs that have no answer key
- AI picks the correct option from each question's choices
- Generates explanation using document context + medical knowledge
- Useful for PDFs like practice tests where answers were never included
- Available manually and as an ai_decide strategy

Flashcard decks can now be renamed:
- PATCH /flashcards/{deck_id} updates title
- Inline edit on FlashcardsPage with responsive layout (input full-width,
  buttons wrap under it so Cancel never overflows the card)
- Title truncates with ellipsis when not editing

Note: generate mode (textbook -> MCQs) is unchanged per user request.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 20:17:49 +02:00
Daniel
5398342e3d Suspend pauses timer; hide timer-expired attempts from history
Suspend now pauses the timer instead of letting it run out:
- 'Suspend & Leave' sends suspended=true with time_left to backend
- On resume, backend re-anchors started_at to now with held time_left
- Closing tab without suspending continues to run the timer (unchanged)

Timer-expired auto-submits are marked with expired=1 and excluded from:
- Attempt history (GET /attempts/history)
- Dashboard stats (quiz count, total attempts, average score)
- Attempt list (GET /attempts)
- DDL: ALTER TABLE quiz_attempts ADD COLUMN expired INTEGER DEFAULT 0

Course-quiz decoupling is preserved — these changes only touch
non-course quizzes (Quiz.course_id IS NULL).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 19:27:46 +02:00
Daniel
c44014c787 Improve upload progress UX — indeterminate bar and elapsed time
Local uploads appeared stuck at 0% because onUploadProgress
doesn't fire granularly on fast local networks or when network
buffering makes the browser report instant completion.

Changes:
- Animated indeterminate progress bar when percent unavailable
- Elapsed seconds counter so user sees activity
- Separate "Uploading" vs "Processing on server" stages
- Hint message about large PDFs taking time

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 19:17:33 +02:00
Daniel
56fdc57389 fix: gateway-agnostic URL handling for TTS and embeddings, docs cleanup
- Fix double /v1 in TTS audio/speech URL when LITELLM_API_BASE includes /v1
- Fix double /v1 in embedding service and vector service URLs
- Clean up docs: remove second-person language in deployment, frontend, migrations

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-19 02:17:35 +02:00
Daniel
04e1855452 Document Alembic workflow and advisory-lock startup fix 2026-04-14 05:44:48 +02:00
Daniel
0f3a267fb6 Wire Alembic to live Postgres and fix startup DDL race
- alembic.ini: remove hardcoded sqlite URL
- alembic/env.py: inject DATABASE_URL from container env
- main.py: serialize Base.metadata.create_all() + setup_pgvector() behind
  a Postgres advisory lock (_run_startup_ddl). Previously all 4 uvicorn
  workers ran the DDL in parallel and occasionally deadlocked each other
  on ALTER TABLE ordering, killing one worker at startup.
- CLAUDE.md: add Database migrations (Alembic) section

DB was stamped at 9bac7bf02e38; no schema changes in this commit.
2026-04-14 04:49:23 +02:00
Daniel
b39e09f393 Persist reminders_disabled in Postgres and harden reminder scheduler
- Add reminders_disabled boolean column to users (DB source of truth).
- Scheduler reads the DB column directly; Redis no longer used for
  opt-out checks.
- Scheduler now deactivates reminders when a user has no completed
  attempts left for a quiz (e.g., after deleting their attempts).
- Settings API: GET returns DB value for reminders_disabled; PUT
  persists that key to DB and keeps the rest of the blob in Redis.

Rollback point for Alembic wiring.
2026-04-14 04:31:03 +02:00
Daniel
dc240c31d2 Add Capacitor mobile app wrapper for PedsHub Quiz
- Configurable server URL (default: pedshub.com)
- Android + iOS platforms initialized
- Dark theme matching quiz app (#0f172a)
- Status bar and navigation bar color matched
- Auto-redirect on subsequent launches
- App ID: com.pedshub.quiz, App Name: PedsHub

Build: cd mobile && npx cap sync && npx cap open android

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 05:12:25 +02:00
Daniel
d0518d0737 Add comprehensive structured logging with Loki + Grafana
Backend logging:
- Centralized JSON logging config with LOG_LEVEL env var
- Request logging middleware: user, method, path, status, duration, request_id
- Fixed all 9 silent except:pass blocks to log warnings with tracebacks
- Celery workers use same structured JSON format

Infrastructure:
- Loki 3.3.2 for log storage (30-day retention)
- Promtail 3.3.2 for Docker container log shipping
- Grafana 10.3.1 with auto-provisioned Loki datasource
- Grafana on port 3002 (admin/pedshub_grafana)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:53:54 +02:00
Daniel
b32fc65236 Fix mark-complete 403 for course creators previewing lessons
Creators preview courses without enrolling, so markComplete and SCORM
onComplete were hitting the progress endpoint and getting 403. Now
guarded by enrollment check — buttons hidden and callbacks skipped
for non-enrolled users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:25:21 +02:00
Daniel
2db5cb74d7 Fix SCORM content blocked by CSP and X-Frame-Options
- Add 'self' to frame-src in CSP to allow same-origin iframes
- Add 'unsafe-eval' to script-src (SCORM packages often use eval)
- Add /uploads/scorm/ location that strips frame-blocking headers
- SCORM content served without X-Frame-Options or CSP restrictions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 02:08:51 +02:00
Daniel
d44ad883e9 Add SCORM data persistence across sessions
SCORM runtime data (bookmarks, scores, lesson position) now saved to
Redis via GET/PUT /courses/{id}/lessons/{id}/scorm/data endpoints.
Data loads before iframe renders and saves on Commit/Finish/Terminate.
90-day TTL on stored data.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:53:53 +02:00
Daniel
84c899a814 Add SCORM API shim for proper content communication
SCORM content expects window.API (1.2) or window.API_1484_11 (2004)
on the parent frame. Without it, content fails to initialize.

Implements all 8 required methods for both SCORM versions:
- Initialize/LMSInitialize, Terminate/LMSFinish
- GetValue/LMSGetValue, SetValue/LMSSetValue
- Commit/LMSCommit, error methods
- Auto-marks lesson complete when content reports completion
- Removed iframe sandbox to allow parent frame API access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:36:44 +02:00
Daniel
db98c6ae69 Add certificate generation, SCORM support, QTI export/import
- Certificate: PDF generated on course completion, download from course page
- SCORM: upload ZIP packages as lesson type, served in iframe, manifest parsed
- QTI 2.1: export selected/all questions as XML, import QTI files into bank
- Uses fpdf2 for certificate PDF generation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 01:30:09 +02:00
Daniel
029d985149 Add SSO setup guides for Google, Microsoft, Keycloak, Auth0, Authentik
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 04:13:16 +02:00