- Task 1: pindahkan .quiz-navigator & .quiz-controls dari QuizTab ke
QuizQuestionView; refactor props jadi mgr: LessonManager; CSS ke lesson.css.
Navigator+kontrol kuis selalu terlihat di mobile walau workspace hidden.
- Task 2: get_all_students_progress tidak filter role guru; field role per row;
badge 'Guru', bulk-action & empty-state & ringkasan hanya hitung siswa.
- Task 3: endpoint POST /students/add (reuse StudentRoundTripRow +
find_student_import_conflicts + run_student_import); validate_single_student_input;
AddStudentDialog + addStudent(); import/export/bulk-delete CSV lama tetap ada.
- Fix (Opsi A): breakdown eval/diag hanya hitung MCQ (flashcard netral) —
selaraskan dengan skor resmi FE; perbaiki tampilan eval:4/6 yg membingungkan.
Tambah field type ke QuizAnswerPayload.
Test: backend 239 passed (termasuk test baru teacher-in-report, add-student,
breakdown-excludes-flashcards); svelte-check 0 error; build sukses.
version.ts 27->28.
- QUIZ-01: beforeunload hanya kirim beacon (tanpa finalisasi state) sehingga
Cancel dialog membatalkan reload dan quiz lanjut; beforeNavigate tidak lagi
memfinalisasi untuk tipe 'leave' (full-page unload/reload); review
disembunyikan untuk page_unload (display policy anti-eksploitasi)
- QUIZ-02: opsi MCQ tampil 2-kolom grid (single-col untuk <=2 pilihan,
fallback 1 kolom di mobile sempit)
- QUIZ-03: hapus info "soal X dari Y / X dijawab" + progress bar dari
workspace dan question view
- QUIZ-04: opsi tinggi workspace mobile hide/30%/50%/70%/full dengan
stepUp/stepDown untuk swipe & tombol resize
- QUIZ-05: workspace flashcard hanya 2 tombol "Sudah Mengerti"/"Tidak
Mengerti" (tracking understood), indikator di summary review
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
lesson_specs() hanya memindai home.md root sehingga lesson di
bab/<folder>/sub-home.md tidak pernah masuk tabel lessons. Akibatnya kolom
materi sub-bab hilang saat guru import/export siswa CSV.
- services/lesson_service.py: tambah find_all_sub_home_folders() (enumerate
level-1 folder di CONTENT_DIR berisi sub-home.md)
- services/lesson_registry.py: lesson_specs() gabungkan union root + sub-bab,
dedupe slug (root priority) — satu lesson entitas
- services/tests/test_lesson_registry.py: test unit + DB integration
Verifikasi: 3 passed, 2 skipped (unit); test_sync_includes_sub_bab_lessons
passed (DB); 58 passed total termasuk test_repositories + student_management
tanpa regresi.
The /bab/<folder> endpoint returned raw get_sub_home_data() output, so
lessons had no completed/locked fields and green checkmarks never
appeared. api_bab now reads the student token, injects progress via
get_ordered_lessons_with_learning_objectives (scoped to the folder's
sub-home.md), and computes lock status from prerequisites — matching
/lessons. The bab page load also forwards the student token, and tests
cover progress injection and prerequisite locking.
Lengkapi rencana sub-home (fitur bab sudah ada sejak 2f689af) dengan
perilaku sidebar/navigasi yang akurat per sub-folder:
- get_lessons()/get_ordered_lessons_with_learning_objectives() menerima
source_path opsional sehingga daftar materi dapat diambil dari
sub-home.md alih-alih home.md root
- api_lesson: ordered_lessons + prev/next di-scope ke sub-home.md bila
folder memilikinya, fallback ke daftar global home.md
- get_sub_home_data kini mtime-cached (bukan lru_cache) sehingga edit
sub-home.md langsung terlihat tanpa restart; edit juga meng-invalidate
find_lesson_file agar materi baru terdeteksi
Testing & docs:
- test_sub_home.py (unit): _read_md_cached mtime, find_sub_home_for_lesson,
get_sub_home_data refresh, ordered_lessons via source_path
- test_sub_home_api.py (integration): GET /bab/<folder> + scoped
ordered_lessons di /lesson/<slug>.json
- docs/13-content-sub-home.md (baru), README + docs/02-backend-flask.md
diperbarui dengan catatan fallback
- elemes.sh: perintah `test` + verifikasi tes sub-home di runclearbuild
Append &hideMenu=true to the circuitjs.html iframe src used by
renderCircuitEmbeds so lesson content embeds render clean without
the toolbar and menu bar. The embed path in CircuitEditor.svelte
is untouched, so the editor keeps its full toolbar.
Verified:
- Bundle contains embed URL (with hideMenu=true) and editor URL
(without) as separate variants
- svelte-check: 0 errors
- /lesson/rangkaian_dasar returns 200 on the running stack
- add @types/node for hooks.server process/env types
- fix katex auto-render import path (contrib/auto-render)
- declare global Web Bluetooth API types in ble-deployer
- guard simApi null in CircuitEditor autosave interval
- default-type imports for CodeEditor/CircuitEditor
- make lesson slug getter non-nullable
- add expected_flowchart to LessonContent type
- key lesson workspace by slug; drop phantom onReset prop
- guard CodeTab render when lesson data is null
- Export siswa terpilih/seluruh + progress ke CSV round-trip (token tidak
pernah diekspor; teacher tidak ikut; urutan deterministik)
- Import preview all-or-nothing: siswa existing di-restore (nama+progress,
token lama dipertahankan), siswa baru dibuat dari student_id kosong +
token; conflict tidak menyebut raw token/digest
- Bulk delete multi-seleksi dengan validasi ketat (teacher terlindungi,
zero-delete bila ada ID bermasalah)
- fix(import): deteksi delimiter berbasis schema — menerima titik koma
(;) maupun koma (,), ekspor tetap ';' + BOM; header tab/campuran ditolak
dengan pesan jelas (regresi: file Excel/Sheets kini bisa diimpor)
- refactor: progress_status.py — kontrak status legacy tunggal dipakai
storage PG, export, dan import; report siswa hanya role student
- UI /progress: dialog import/export + bulk delete, selection store,
respon import tanpa raw token; APP_VERSION 22 -> 26
- ops: ORIGIN env var di podman-compose.yml
- docs: README section 9 (workflow round-trip + delimiter) dan
docs/11-database-migration (kelola siswa via round-trip CSV)
- test: parser round-trip (45), repositories, route management (24,
PostgreSQL), frontend 91, fixtures CSV valid/invalid
- FileTree menerima prop language ('c' | 'python', default 'c')
- hanya merender file dengan ekstensi yang cocok (.c atau .py)
- tombol + buat file dengan ekstensi bahasa aktif
- header menampilkan nama bahasa (C/Python), bukan generik 'File'
- runActiveFile() memanggil consumeStdin() (antrean + draft, digabung, dikosongkan)
- pesan info jika stdin kosong: program yang membaca input akan mendapat EOF
- hapus pembacaan consoleInput langsung yang menyebabkan baris hilang
- playground route: velxio/flowchart/circuit/code tabs with auto-save
- FileTree + ConsolePanel for C/Python code tab
- compileCode() forwards stdin through routes/compile.py to compiler_worker
- compiler_worker run_c_code/run_python_code accept stdin, pass via subprocess.run(input=)
- known issue: Console UI does not queue stdin properly → fix in next cycle
Update velxio submodule pointer to the new integration branch that contains:
- EmbedBridge.ts PostMessage bridge for iframe integration
- DeployProgress UI for compile/transfer/flash status
- BASE_URL customization for /velxio/ path
- Backend auth, project, and database endpoints for Elemes LMS
- SerialMonitor BLE/Hardware toggle support
Restructure quiz flow into QuizSession primitive + atomic quiz state in
LessonManager, and extract QuizQuestionView for split-view display.
Tab-safety fix: add lesson-tabs.ts with pickDefaultTab(), getAvailableTabs()
mirroring the exact {#if} conditions in +page.svelte, and ensureActiveTab()
safety-net that falls back to pickDefaultTab() when the desired tab is not
rendered. A reactive $effect in lesson/[slug]/+page.svelte validates
activeTab against lesson data on every change, preventing the "tab quiz
kosong" (empty workspace) regression for quiz-only lessons and phantom-tab
state after data changes.
Files:
- lib/services/lesson-tabs.ts (+test): pure helpers, 18 tests pass
- lesson/[slug]/+page.svelte: ensureActiveTab reactive guard + QuizQuestionView
- lesson/[slug]/lesson.svelte.ts: atomic startQuiz, getExitStatus, idempotent
submit on navigate/exit
- lib/services/quiz-session.ts (+test), lib/types/quiz.ts, QuizTab.svelte
(mgr-driven), QuizQuestionView.svelte, lesson.css
- services/lesson_service.py, services/tests/test_lesson_service_quiz.py
(test_lesson_service_quiz.py), requirements.txt (+pytest)
- docs/07-quiz-authoring.md
- version.ts APP_VERSION 21 -> 22 (forces SW update for the fix)
- examples/content/dasar/quiz_test.md synced to live content root
- Generalize _read_md_cached() for generic file caching
- Add find_sub_home_for_lesson() and get_sub_home_data() helpers
- Add /api/bab/<folder> endpoint
- Detect sub-home in api_lesson for nav context
- Skip sub-home.md in find_lesson_file() and _parse_lesson_links()
- Add title to bab frontend page data
- Update generate_tokens.py & content_parser.py to skip sub-home.md