Files
markdown_to_skillstown/HANDOVER.md
T
2026-05-09 08:34:58 +02:00

18 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
  • reviewstop vóór save

Reden:

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

Huidige bestanden

Input / referentie

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
    • login
    • editorverificatie
    • pagina-aanmaak
    • blokinsertie/invulling
    • DOM-snapshot voor detectie van nieuw ingevoegde blokken
    • drop-targeting op de onderkant van het laatste bestaande blok
    • reviewstop vóór save

Testdata

Config

Wat werkt al

Lokaal

  • Markdown parsing werkt
  • dry-run JSON generatie werkt
  • plan/validatie-export werkt

Live in de zichtbare browser

Bewezen:

  • login werkt
  • editorherkenning werkt
  • reviewmodus zonder mutaties werkt
  • 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
  • er is niet opgeslagen

Artifacts / bewijs

Belangrijkste artifacts:

Pilot na drag/drop-hardening:

Pilot voor multiple-choice afwerking:

Pilot voor multiple-response afwerking:

Pilot voor image afwerking:

Pilot voor table verkenning:

Pilot voor grotere table validatie:

Pilot voor open-question afwerking:

Pilot voor hoofdstukaanmaak:

Pilot voor grotere hoofdstukvalidatie:

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 nieuwe drop-strategie en execute-flow zijn live gevalideerd voor pilots met text, heading, quote, multiple-choice, multiple-response, image, table, open-question en hoofdstukken/pagina's
  • scoped targeting per bloktype blijft verder hardening nodig hebben voor bredere bloksets en afwijkende editorstates
  • de nieuwe "altijd nieuw hoofdstuk"-strategie moet nog live opnieuw gevalideerd worden

Nog niet opgepakt:

  • matching-pairs UI-flow
  • save-flow
  • opschonen van oude, ongebruikte delete-helpers in de runner

Veiligheidsafspraken

Tot nu toe gehanteerd:

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

Bewust nog niet gedaan:

  • automatisch opslaan
  • 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:

Installeren:

npm install

Dry-run parser:

node markdown-to-onlineacademy-json.mjs pilot-mvp.md

Zichtbare review-run zonder mutaties:

# verwacht een lokaal `.env` bestand met ten minste:
# OA_EMAIL='...'
# OA_PASSWORD='...'

Credentials laden uit .env:

set -a
source .env
set +a

Zichtbare review-run zonder mutaties:

node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6'

Zichtbare execute-run tot reviewstop, zonder save:

set -a; source .env; set +a
node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6' \
  --execute \
  --output-dir artifacts/oa-runner-pilot

Zichtbare execute-run zonder save:

set -a
source .env
set +a
node onlineacademy-playwright-runner.mjs \
  --markdown pilot-mvp.md \
  --url 'https://create.onlineacademy.nl/8602e048-d7ee-4764-aafb-43412d0f65f3/edit?idsVersion=6' \
  --execute

Directe volgende stap

Niet meer werken met "laatste blok = nieuw blok".

Hardeningvoorstel:

  1. multiple-choice volledig afmaken: Status: afgerond voor de pilot-run.
  2. multiple-response Status: afgerond voor de pilot-run.
  3. image Status: afgerond voor de pilot-run.
  4. table Status: afgerond voor de pilot-run.
  5. open-question Status: afgerond voor de pilot-run.
  6. hoofdstukaanmaak Status: afgerond voor de pilot-run, maar execute-flow is inmiddels vereenvoudigd naar "altijd nieuw hoofdstuk" en moet daarop opnieuw live gevalideerd worden.
  7. verdere hardening voor andere bloktypes en editorvarianten
  8. save-flow

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 veiligste huidige koers is om in execute-runs alleen nieuwe hoofdstukken op te bouwen en geen bestaande content te verwijderen. Verdere hardening blijft nodig op blokpositie, veldtargeting en uiteindelijk de save-flow voordat dit betrouwbaar genoeg is voor herhaalbaar gebruik.