Commit Graph

276 Commits

Author SHA1 Message Date
a2nr 8630ba6b03 chore: bump version to v35 2026-10-05 16:20:36 +07:00
a2nr df3b89593a Merge branch 'dev' 2026-10-05 16:19:33 +07:00
a2nr 8cf85c1e4c Improve teacher content editor mobile workspace 2026-10-05 15:18:39 +07:00
a2nr 733cfa575e chore: bump version to v34 2026-10-04 07:42:18 +07:00
a2nr 75438e2ea0 Merge branch 'dev' into master — fix upload asset proxy & diagnostik bundle 2026-10-04 05:47:28 +07:00
a2nr 3c2546c818 fix(content-editor): diagnostik upload asset + kelengkapan bundle
- upload_asset: deteksi format dari magic bytes saat PIL menolak, log exception asli

- contentEditor.ts: import bundle stop di failure pertama (informasi utuh tetap
  tersedia); guard frontend
- verify_import_export.py: probe PNG 1x1 valid (PNG palsu ditolak PIL)
- test_content_editor_routes.py: coverage pesan error + AVIF
- bundle: elemes_content_fixed.zip (electron_flow_sparkfun.png 404 nginx dibuang)
2026-10-03 21:47:05 +07:00
a2nr bb8ca50650 fix(upload): review — CSP SVG, boundary 5 MiB, regression guard 502/413
Hasil review pasca-fix upload asset:

Keamanan:
- Mitigasi stored-XSS via SVG (route /assets/* publik, same-origin):
  CSP 'default-src none; sandbox' saat serve SVG — di backend
  (send_assets) DAN di proxy SvelteKit (proxy hanya meneruskan
  content-type/set-cookie, jadi CSP backend tak sampai ke browser).
- Deteksi 413 proxy kini ber-test status code + pesan.

Testing:
- Regression guard: error jaringan biasa tetap 502, bukan 413.
- 413 via status code saja (tanpa regex pesan) tetap 413.
- Boundary 5 MiB: file TEPAT 5 MiB lolos; 5 MiB+1 ditolak (cabang
  len(raw) — SVG dipakai karena dikecualikan validasi PIL).
- CSP: SVG dapat header, raster tidak.
- E2E script (verify_asset_upload.py) memakai file asli
  mr-edu/assets/ilustrasi_beban.jpeg + test 413 terintegrasi.

Reuseability:
- Komentar silang-referensi _MAX_ASSET_BYTES (sumber) dengan pesan 413
  proxy dan BODY_SIZE_LIMIT compose.
2026-10-03 08:06:29 +07:00
a2nr 8fd39d6e1a fix(frontend): upload asset lolos proxy — BODY_SIZE_LIMIT 8M + proxy 413 jelas
Body upload (JSON base64, ~7 MiB untuk file 5 MiB) ditolak default
adapter-node 512K sebelum sampai backend Flask, lalu error itu
terlapor sebagai 502 'Backend tidak tersedia'.

- podman-compose: BODY_SIZE_LIMIT=8M untuk elemes-frontend
- hooks.server: SvelteKitError body-size (413) dipisah dari kegagalan
  koneksi — balas 413 'Ukuran file terlalu besar' bukan 502
- test: proxy balas 413 untuk body melebihi limit
2026-10-03 05:16:41 +07:00
a2nr d51c7da972 chore: bump version to v33 2026-10-01 13:29:12 +07:00
a2nr 2780e5f4a9 Merge branch 'dev' into master — import/export content & assets 2026-10-01 13:28:52 +07:00
a2nr c127309dd8 test: script E2E verify import/export bundle di content editor 2026-10-01 12:45:54 +07:00
a2nr ed7e7d1b26 feat: tombol export/import bundle di content editor 2026-10-01 12:11:58 +07:00
a2nr 961d2a0ac2 feat: extractBundle — unzip client-side via fflate dengan validasi entry 2026-10-01 12:09:12 +07:00
a2nr 796fd47800 feat: exportBundle + importBundle per-file via endpoint existing 2026-10-01 12:08:07 +07:00
a2nr f1f0b57189 chore: tambah fflate untuk unzip client-side 2026-10-01 12:06:24 +07:00
a2nr 67f1501b4e feat: GET /content/export — download zip content+assets 2026-10-01 11:49:27 +07:00
a2nr f5ee52080c Merge branch 'dev' into master 2026-09-16 22:20:20 +07:00
a2nr ba1e7240f3 feat(offline-db): implement offline progress persistence and sync manager for lessons
- Add getProgress and getAllProgress to local IndexedDB SyncManager
- Support opportunistic background sync for lesson progress and quizzes
- Connect LessonManager to IndexedDB progress cache for offline lesson completion status
- Disable SSR for /lesson and /bab routes to ensure consistent client-side local storage
2026-09-16 22:19:53 +07:00
a2nr 53b704c7de fix(teacher): align student and teacher counters on progress tree view
- Count only distinct students for sub-chapter folder completion badge
- Separate teacher attempts from student counter on lesson header with a dedicated '+Y guru' badge
- Differentiate teacher rows with teacher icon and dashed styling
2026-09-16 20:15:20 +07:00
a2nr f95365a6e3 feat(teacher): refactor progress into tree view and separate classroom management
- Redesign /teacher/progress into a folder-like tree view (sub-bab -> lesson -> completed students)
- Create /teacher/classroom for student management (import/export CSV, add, bulk delete)
- Enrich /progress-report.json API response with sub_bab, sub_bab_title, and sub_bab_list
- Add Classroom navigation item to teacher navbar menu
2026-09-15 04:51:35 +07:00
a2nr 8d1fe00bf2 Merge branch 'dev' into master 2026-09-14 04:29:24 +07:00
a2nr c765399715 feat(playground): implement synchronous interactive input for client-side C and Python
- Unbuffer C stdout via setbuf(stdout, NULL) so prompts flush before blocking on input
- Break Emscripten FS.read loop with justFinishedLine and upgrade float/%f to double/%lf for PicoC compatibility
- Provide reactive waitingForInput state with auto-focus, dynamic placeholder, and highlighted send button in ConsolePanel
- Enable full multi-step interactive stdin flow in browser execution mode via SharedArrayBuffer and Atomics
2026-09-14 04:13:08 +07:00
a2nr 0decd6ce86 fix(playground): resolve mobile layout overlap and missing console input
- Lock viewport and relative navbar in +layout.svelte on both mobile and desktop
- Remove static min-height and overflow-y overrides on mobile in +page.svelte
- Auto-collapse file tree and compact code toolbar on mobile
- Add safe-area padding and 200px mobile height in ConsolePanel.svelte
- Bump APP_VERSION to 32
2026-09-13 15:53:02 +07:00
a2nr c1cb60be1e feat(code-runner): implement client-side C and Python execution with offline mirror and COEP iframe embedding
- Add client-side code runner via Web Workers (PicoC for C, MicroPython WASM for Python)
- Support interactive stdin with SharedArrayBuffer and Atomics
- Implement offline database mirror using Dexie.js with opportunistic auto-sync
- Add execution mode toggle in Playground (Browser vs Server)
- Configure COOP, COEP, and CORP security headers in SvelteKit server hook
- Fix Velxio and Flowchart Nginx headers and add credentialless attribute to iframes
- Mount Nginx configs in podman-compose.yml for velxio and flowchart services
- Add unit and E2E Playwright integration tests (100% passed)
2026-09-13 10:14:51 +07:00
a2nr d0e4645c36 fix(playground): resolve desktop layout overlap and show velxio toolbar 2026-09-11 12:55:35 +07:00
a2nr 1f4217be76 fix(quiz): enforce 75% passing threshold, sync server progress, and persist attempt review
- Only show celebration overlay and top bar completed checkmark if quiz score meets 75% threshold (>= 0.75) and exercises are done
- Return is_done, state, and composite_percent in POST /lesson-progress for exercise and quiz submissions
- Synchronize frontend LessonManager state with authoritative server is_done response
- Add has_quiz_attempt check in routes/lessons.py and token_service to recognize existing attempts even when composite state is in_progress
- Update QuizTab to display persistent attempt review, score status, and explanation instead of retake prompt on page load/refresh
- Make QuizQuestionView finish handler async, await finishQuiz(), and disable submission buttons to prevent navigation race conditions
- Update local ordered_lessons completion state dynamically upon passing
- Add unit and integration tests covering response payload attributes and has_quiz_attempt API field
- Bump APP_VERSION to 30
2026-09-09 07:33:52 +07:00
a2nr 9bfecfbcab feat(student-management): sync imported progress with composite model and add inline expected format to CSV headers
- Sync imported progress (completed, scored, done, reset) to composite progress model and recompute composite_percent
- Prevent caching of /progress-report.json with Cache-Control: no-store and frontend cache-busting timestamp
- Provide inline expected format guides in exported CSV lesson headers (e.g. [completed], [<earned>/<total>], [done:<1|0>:<earned>/N])
- Support robust slug extraction from formatted headers in CSV roundtrip import with full backward compatibility
- Add example composite lesson (exercise + quiz) in examples/content/dasar/composite_test.md
- Add comprehensive unit and integration tests covering progress synchronization, header formatting, and roundtrip workflows
2026-09-08 19:01:33 +07:00
a2nr fe1fd8ce8a Merge branch 'dev' into master
- Unified lesson progress tracking with composite scoring
- Client-side SvelteKit markdown rendering and preview
- Velxio simulator integration with bidirectional circuit/code sync
- Modular Python CLI and interactive TUI replacing bash scripts
- Postgres storage optimizations (N+1 query bulk fetch, backfill sync)
- Proxy binary payload safety and origin-restricted postMessage
2026-09-06 18:11:47 +07:00
a2nr 17713303bb fix(review): address code review findings for dev to master merge
- Optimize N+1 queries in get_all_students_progress via bulk fetch
- Backfill legacy progress in migration 0005 and startup sync
- Use arrayBuffer in hooks.server proxy for binary payload safety
- Restrict postMessage targetOrigin from wildcard to window.location.origin
- Harden iframe polling in TeacherVelxioEditor and reduce frequency
- Improve markdown section extractor line-boundary detection
- Clean up child subprocesses on exception in CLI runner
- Add console.error in contentEditor catch blocks and parameterize repro script
- Configure sequential vitest execution to optimize test runs
2026-09-06 18:08:58 +07:00
a2nr 74423eee49 fix(test): update make test-cli path and configure pytest cache_dir for container compatibility
- Point make test-cli to isolated cli/tests/test_cli_tui.py
- Add cache_dir = /tmp/.pytest_cache in pytest.ini to avoid permission denied warnings under non-root container users
2026-09-06 16:17:41 +07:00
a2nr 7d590e0f95 fix(content-editor): sync and auto-save velxio arduino draft on publish
- Auto-save dirty draft before publishing in ContentEditorManager so in-memory
  Velxio circuit/code changes are never lost when clicking Publish directly
- Add resolveRestoredContent and baseline tracking to velxio-manager so lesson
  view immediately reflects updated server code instead of stale localStorage
- Invalidate in-memory lesson and markdown caches on draft publish and file operations
- Update teacher content page publish button disabled condition to check saving state
2026-09-06 16:17:35 +07:00
a2nr 76e0210a9d feat(cli): refactor elemes.sh to modular Python CLI, interactive TUI, and multi-OS support
- Modularize orchestrator into Python modules under cli/ (config, runner, commands, tui)
- Introduce interactive Rich-based TUI with live container status, focused description panel, and arrow navigation
- Add multi-OS launcher wrappers: elemes.sh (Unix), elemes.bat (Windows CMD), elemes.ps1 (PowerShell), elemes.py
- Default isolated virtualenv to parent folder (../venv) to keep repository clean
- Add stopclean command for compose down with container & image pruning
- Fix submenu navigation when pressing ENTER on Kembali and Keluar
- Prevent keystroke bleeding across subprocess executions with DEVNULL stdin and tcflush
- Add unit test suite (make test-cli) covering 27 isolated CLI/TUI tests
- Maintain 100% backward compatibility with existing elemes.sh commands and shell regression tests
2026-09-06 12:28:07 +07:00
a2nr e4ab058078 feat(velxio): improve teacher arduino toolbar, add expected_wiring template, and harden deployer board detection
- Add EXPECTED_WIRING block to set-arduino template and standalone expected-wiring feature in teacher content editor
- Reposition reload button to the far left inline with status dot, and shorten status text to 'Siap' / 'Menghubungkan...'
- Decouple transfer from save: replace 'Simpan ke Dokumen' with 'Pindahkan Hasil' and centralize document saving to top header save button
- Dynamically detect board FQBN from circuit in DeployTab with arduino:avr:uno fallback
2026-09-06 05:10:13 +07:00
a2nr 5429dc17f9 feat(test): add velxio-test command to elemes.sh and Arduino content editor integration tests 2026-09-05 20:44:58 +07:00
a2nr 812ede0acc test(velxio): add comprehensive unit test suites for velxio-manager, hooks redirect, and backend markdown parsing 2026-09-05 18:06:19 +07:00
a2nr ea167b45a7 fix(tailscale): use __VELXIO_PROXY_TARGET__ for all velxio routes and add editor routes in template 2026-09-05 18:02:20 +07:00
a2nr 032e7f29ae fix(teacher): fix CSS height collapse and flex layout in content editor arduino tab 2026-09-05 17:32:21 +07:00
a2nr 21ffb65e05 fix(frontend): handle /editor gracefully and enable desktopLayout for teacher arduino tab 2026-09-05 17:03:15 +07:00
a2nr c3fc8dc8f1 feat(teacher): integrate full Velxio editor with bi-directional circuit and code sync 2026-09-05 16:50:31 +07:00
a2nr 2a152c8559 fix(tailscale,velxio): add wasm and boards proxy routes and update velxio submodule 2026-09-05 10:27:01 +07:00
a2nr e6507542ea fix(proxy): remove velxio compile route conflict in tailscale serve config 2026-09-05 10:07:16 +07:00
a2nr f12014a331 fix(velxio): update submodule with lockComponents fix and add fallback proxies in tail config 2026-09-05 09:41:18 +07:00
a2nr fb68c56e51 chore(velxio): update submodule to elemes-v3.0.4 with embed and build fixes 2026-09-05 07:53:51 +07:00
a2nr f34bdc8b94 fix(submodule): update velxio to elemes-legacy-stable with nginx redirect fix 2026-09-05 06:55:46 +07:00
a2nr 4ed5fd8dc4 fix(docker): optimize backend build with explicit COPY and updated .dockerignore 2026-09-05 06:55:43 +07:00
a2nr 17b645325c chore: tambah script debug scan/parse quiz & repro opsi via Playwright
_scan_quiz_issues.py: cari soal MCQ dengan <2 opsi (ter-split).
repro_quiz_options.py: navigasi quiz di browser, assert jumlah opsi DOM
vs server quiz_data.
2026-08-30 10:55:29 +07:00
a2nr a157a31b78 fix(lesson): no-store cache header pada response lesson JSON
Mencegah browser/SW/proxy menyajikan lesson (termasuk quiz_data) dari
cache stale, terutama saat file lesson diubah.
2026-08-30 10:55:22 +07:00
a2nr da6d7e25d3 fix(quiz): pakai state eksplisit + keyed each agar opsi render konsisten
currentQuizQuestion dijadikan $state (bukan getter) yang di-sync lewat
_syncCurrentQuestion() tiap ganti soal, dan {#each} opsi memakai :key
option.id. Mencegah opsi 'hilang' 1 frame saat navigasi mcq<->flashcard.
Tambah test integritas shuffle (opsi tetap lengkap & id konsisten).
2026-08-30 10:55:14 +07:00
a2nr 5cc4ca472b fix(quiz): jangan belah soal saat '#' muncul di dalam code fence
_split_flashcard_parts() pakai state-machine per-baris agar komentar '#'
di dalam blok kode (python/shell/bash/yaml) tidak dianggap heading baru.
Sebelumnya re.split('^#{1,3}\s+') membelah soal menjadi dua, sehingga
opsi meleset ke 'soal hantu' dan pilihan di layar tidak sesuai markdown.
2026-08-30 10:55:06 +07:00
a2nr ac3fdb8dff refactor(routes): remove /api/lesson-progress aliases and standardize tests to /lesson-progress 2026-08-30 04:45:37 +07:00