Files
kodi 410f37a008 feat(oa): add training-dir workflow and save flow for OnlineAcademy runner
Introduce a simpler training-based workflow for the OnlineAcademy Playwright runner.

Changes included:
- support --training-dir and automatic loading of content.md and training.json
- support --env-file so OA credentials no longer need manual shell sourcing
- resolve asset paths relative to the training directory
- improve human-readable review and execute output with step-by-step progress
- keep the browser open after execute when no save flag is used
- add optional --save flow that clicks 'Opslaan als' and then chooses 'Concept'
- add a concrete user guide for preparing and running training imports
- update handover documentation to reflect the current repo structure and workflow
- align the repo around trainings/<name>/content.md, training.json and assets/
- remove reliance on older pilot/test material in the documented main flow
2026-05-09 11:29:35 +02:00

12 KiB

OnlineAcademy Handover

Doel

Automatiseren van het opbouwen van elearningmodules in create.onlineacademy.nl met Markdown als bron, maar bewust via de zichtbare editor-UI met Playwright in plaats van via backend write-API's.

De gebruiker wil meekijken tijdens de browserrun en de oplossing moet veilig blijven in een productieomgeving.

Onderzoeksuitkomst

Platformstructuur

Live bevestigd:

  • links: hoofdstukken/pagina's
  • midden: paginacanvas met contentblokken
  • rechts: blokbibliotheek en instellingen

Belangrijke UI-ankers die zijn aangetroffen:

  • data-testid="editor-main"
  • data-testid="page-button"
  • blokken rechts zoals:
    • drag-block-text
    • drag-block-heading
    • drag-block-quote
    • drag-block-table
    • drag-block-multiple-choice
    • drag-block-multiple-response
    • drag-block-open-question
    • drag-block-matching-pairs

Bloktypes

In UI gezien:

  • text
  • heading
  • quote
  • table
  • image
  • video
  • audio
  • downloads
  • links
  • expert
  • typeform
  • multiple-choice
  • multiple-response
  • open-question
  • matching-pairs

Backend read-only bevindingen

Er is bewust alleen read-only gekeken naar de data die de editor zelf ophaalt.

Belangrijke GET endpoints:

  • GET /authoring/v1.0/contents/course/{contentId}
  • GET /authoring/v1.0/contents/version?externalId=...

De echte cursusinhoud zit in jsonContent en heeft grofweg deze vorm:

{
  "chapters": [
    {
      "id": "...",
      "title": "...",
      "pages": [
        {
          "id": "...",
          "pageType": "number",
          "title": "...",
          "blocks": [
            {
              "id": "...",
              "type": "text",
              "data": { "...": "..." }
            }
          ]
        }
      ]
    }
  ],
  "examPage": {
    "enabled": false,
    "blocks": [],
    "examSettings": {
      "showFeedbackAfterExam": false,
      "questionPool": false,
      "numberOfQuestions": 0,
      "minimumPassingScore": 60
    }
  }
}

Deze kennis is alleen gebruikt voor begrip en mapping, niet voor writes.

Gekozen oplossingsrichting

Niet API-first.

Wel:

  • Markdown parser
  • intern trainingsmodel
  • UI-plan
  • zichtbare Playwright runner
  • review en execute via de editor-UI
  • optionele save via Opslaan als -> Concept

Reden:

  • minder risico in productie
  • platformvalidaties blijven actief
  • gebruiker kan meekijken
  • geen directe backend writes

Huidige bestanden

Input / referentie

Gebruikersinvoer volgens huidige werkwijze

De beoogde gebruikersflow is nu:

  • per training een eigen map onder /Users/nico/skillstown/trainings/
  • vaste bestandsnamen binnen die map:
    • content.md
    • training.json
    • assets/

Concreet voorbeeld dat nu is ingericht:

Belangrijk:

  • de runner ondersteunt nu direct --training-dir <map>
  • daarbij wordt automatisch content.md en training.json gebruikt
  • de URL wordt dus standaard uit training.json gelezen
  • credentials kunnen via --env-file .env worden geladen zonder source .env

Scripts

  • inspect-onlineacademy.mjs Read-only inspectie van login, editor, requests en payloads.

  • markdown-to-onlineacademy-json.mjs Parser en dry-run converter van Markdown naar platform-compatibele jsonContent.

  • onlineacademy-playwright-runner.mjs Zichtbare Playwright runner met:

    • reviewmodus
    • execute-modus
    • optionele --save flag
    • login
    • inlezen van .env via --env-file
    • inlezen van training.json via --training-dir
    • editorverificatie
    • pagina-aanmaak
    • blokinsertie/invulling
    • asset-resolutie relatief aan content.md
    • menselijk leesbare voortgangsmeldingen
    • DOM-snapshot voor detectie van nieuw ingevoegde blokken
    • drop-targeting op de onderkant van het laatste bestaande blok
    • execute zonder save laat het scherm open voor handmatige controle
    • save klikt Opslaan als en kiest daarna Concept

Config

De runner verwacht credentials via environment variables:

  • OA_EMAIL
  • OA_PASSWORD

Praktisch worden die lokaal in .env gezet en tijdens een run automatisch ingelezen met:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env

Zonder deze stap stopt de runner met:

Error: Zet OA_EMAIL en OA_PASSWORD in /Users/nico/skillstown/.env of in de omgeving.

Wat werkt al

Lokaal

  • Markdown parsing werkt
  • dry-run JSON generatie werkt
  • plan/validatie-export werkt
  • trainingsmap-structuur werkt
  • .env en training.json worden automatisch ingelezen via flags

Live in de zichtbare browser

Bewezen:

  • login werkt
  • editorherkenning werkt
  • reviewmodus zonder mutaties werkt
  • menselijk leesbare statusuitvoer werkt
  • execute zonder --save laat het scherm nu open voor handmatige controle
  • execute met --save bewaart nu via Opslaan als -> Concept
  • nieuwe pagina Intro aanmaken werkt
  • paginatitel invullen werkt
  • drag/drop insertie van blokken werkt aantoonbaar stabieler wanneer op de onderkant van het laatste bestaande blok wordt gedropt
  • execute-run in natuurlijke volgorde van boven naar beneden werkt nu voor:
    • text
    • heading
    • quote
  • multiple-choice blokinsertie werkt en de vraag wordt ingevuld
  • multiple-choice werkt nu end-to-end voor de pilot:
    • vraag invullen
    • aantal antwoorden afstemmen op Markdown
    • juiste antwoord selecteren
    • feedback invullen
  • multiple-response werkt nu end-to-end voor de pilot:
    • vraag invullen
    • aantal antwoorden afstemmen op Markdown
    • alle checkboxen resetten
    • meerdere correcte antwoorden selecteren
    • feedback invullen
  • image werkt nu voor de pilot:
    • upload via lokaal bestandspad
    • titel invullen
    • onderschrift invullen
    • alternatieve tekst invullen
  • table werkt nu end-to-end voor de pilot:
    • titel invullen
    • Top header aan/uit zetten
    • Left header aan/uit zetten
    • aantal kolommen uitbreiden op basis van Markdown
    • aantal rijen uitbreiden op basis van Markdown
    • header- en bodycellen invullen
  • open-question werkt nu end-to-end voor de pilot:
    • vraag invullen
    • toelichting invullen
  • hoofdstukaanmaak werkt nu voor de pilot:
    • de execute-flow maakt nu altijd een nieuw hoofdstuk aan via Nieuw hoofdstuk
    • automatisch aangemaakte eerste pagina in nieuwe hoofdstukken hernoemen en hergebruiken
    • extra pagina's per hoofdstuk aanmaken wanneer Markdown meer pagina's bevat
  • asset-paden in trainingsmappen werken nu correct via relatieve resolutie vanaf content.md
  • save via Opslaan als -> Concept werkt nu

Artifacts / bewijs

De repo is opgeschoond; oude pilots en artifacts zijn verwijderd.

Huidige relevante artifacts worden per run geschreven naar:

  • artifacts/<trainingsnaam>/

Daar vind je typisch:

  • plan.json
  • validation.json
  • editor-ready.png
  • review-stop.png of after-save.png
  • failure-state.png als een run mislukt

Belangrijkste observatie over drag/drop

De eerdere generieke drop in het bovenste deel van editor-main gaf instabiele invoegposities.

Verbetering die live is gevalideerd:

  • wanneer het nieuwe blok naar het onderste deel van het laatste bestaande blok wordt gedropt, wordt het in de pilot-run onder dat blok ingevoegd
  • de runner vult niet meer "eerste" of "laatste" blok blind in, maar detecteert het nieuwe blok via een DOM-snapshot vóór en na insertie

Gevolg:

  • omgekeerde insertievolgorde is niet meer nodig voor de huidige MVP-blokken
  • de gebruiker ziet nu een natuurlijke opbouw van boven naar beneden tijdens de zichtbare run

Belangrijke observatie over verwijderen

Tijdens de grotere hoofdstukpilot verscheen zichtbaar een bevestigingspopup bij het leegmaken van de bestaande eerste pagina.

Waarschijnlijk oorzaak:

  • de runner hergebruikt voor hoofdstuk 1 de al bestaande geopende pagina
  • daarvoor probeert clearCurrentPageBlocks(...) bestaande blokken via Verwijderen weg te halen
  • de huidige implementatie klikt wel op Verwijderen, maar handelt de bevestigingspopup nog niet expliciet en stap-voor-stap af

Gevolg:

  • de popup kan enkele seconden knipperen of opnieuw focus krijgen
  • dit oogt voor de gebruiker onrustig
  • het is een risicovoller stuk gedrag dan de overige blokinvullingen, omdat het om verwijderacties gaat

Pragmatische koerswijziging:

  • de execute-flow verwijdert nu geen bestaande hoofdstukken, pagina's of blokken meer
  • de runner hergebruikt hoofdstuk 1 niet meer
  • voor elk Markdown-hoofdstuk wordt nu altijd een nieuw hoofdstuk aangemaakt
  • daarmee verdwijnt de delete-confirmation popup uit het normale execute-pad

Huidige tekortkomingen

Nog niet robuust:

  • de execute-flow is nu gevalideerd voor de gebruikte bloksets in hoofdstuk-04-basisqueries
  • scoped targeting per bloktype blijft verder hardening nodig hebben voor bredere bloksets en afwijkende editorstates

Nog niet opgepakt:

  • matching-pairs UI-flow
  • functionele bevestiging van succesvol opslaan nog explicieter maken in de output
  • opschonen van oude, ongebruikte delete-helpers in de runner

Veiligheidsafspraken

Tot nu toe gehanteerd:

  • headed browser
  • slow motion
  • reviewmodus zonder mutaties
  • execute zonder --save stopt vóór save en laat het scherm open
  • geen directe backend writes
  • artifacts per stap
  • execute-flow gebruikt nu geen delete-acties meer

Bewust nog niet gedaan:

  • extra verificatie van succesvol opslaan na klik op Opslaan als -> Concept
  • API writes
  • bulkimport in productie

Aanbevolen aanvullende veiligheidsafspraak:

  • als een run bestaande content zou moeten verwijderen, laat dat alleen gebeuren na expliciete gebruikersbevestiging
  • voor het standaard execute-pad heeft een flow zonder delete-acties de voorkeur

Run-instructies

In /Users/nico/skillstown:

Benodigd op macOS:

  • Terminal
  • Node.js
  • npm

Installeren:

npm install

Credentials lokaal in .env zetten:

OA_EMAIL=jouw.email@voorbeeld.nl
OA_PASSWORD=jouwWachtwoordHier

Dry-run parser:

node markdown-to-onlineacademy-json.mjs trainings/hoofdstuk-04-basisqueries/content.md

Zichtbare review-run zonder mutaties:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env

Zichtbare review-run op een trainingsmap volgens de nieuwe gebruikersstructuur:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env

Zichtbare execute-run tot reviewstop, zonder save:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env \
  --execute \
  --output-dir artifacts/hoofdstuk-04-basisqueries

Zichtbare execute-run zonder save:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env \
  --execute

Zichtbare execute-run met save-klik:

node onlineacademy-playwright-runner.mjs \
  --training-dir trainings/hoofdstuk-04-basisqueries \
  --env-file .env \
  --execute \
  --save

Directe volgende stap

Pragmatische vervolgstappen:

  1. save-bevestiging explicieter maken in de output
  2. package scripts laten aansluiten op de huidige --training-dir flow
  3. ondersteuning uitbreiden voor extra bloktypes zoals matching-pairs
  4. oude, ongebruikte helpers verder opschonen

Eindconclusie

De drag/drop Playwright-route is technisch haalbaar en veiliger passend bij deze productiecontext dan direct backend writes.

De basis is gelegd en live gevalideerd. De huidige flow ondersteunt nu review, execute zonder save en execute met save via Opslaan als -> Concept, vanuit een vaste trainingsmap-structuur met content.md, training.json en assets/.