Assessment & read-only
Apollon has a grading workflow on top of the editor: switch the editor into
assessment mode, attach a score and feedback to individual diagram elements,
highlight elements, and subscribe to which element the grader selected. The same
readonly switch also gives you a plain non-editable viewer. This is the
workflow Artemis uses to grade modeling exercises.
Read-only viewer
Pass readonly to render a diagram nobody can edit — for previews, summaries,
or a graded result.
import { Apollon, type UMLModel } from "@tumaet/apollon"
import "@tumaet/apollon/style.css"
export function DiagramViewer({ model }: { model: UMLModel }) {
return <Apollon readonly defaultModel={model} style={{ height: 400 }} />
}
Imperatively, it's the readonly constructor option (toggle later with
editor.setReadonly(true)):
import { ApollonEditor, type UMLModel } from "@tumaet/apollon"
function mountViewer(container: HTMLElement, model: UMLModel) {
return new ApollonEditor(container, { model, readonly: true })
}
Assessment mode
Construct the editor in ApollonMode.Assessment (or call
editor.setMode(ApollonMode.Assessment) later), then attach an Assessment to
each element you grade with addOrUpdateAssessment.
import { ApollonEditor, ApollonMode, type Assessment } from "@tumaet/apollon"
import "@tumaet/apollon/style.css"
const container = document.getElementById("apollon")
if (!container) throw new Error("#apollon container missing")
const editor = new ApollonEditor(container, { mode: ApollonMode.Assessment })
const assessment: Assessment = {
modelElementId: "node-1",
elementType: "Class",
score: 2,
feedback: "Good — but the association multiplicity is missing.",
}
editor.addOrUpdateAssessment(assessment)
// Assessments live on the model, keyed by element id:
const all: Record<string, Assessment> = editor.model.assessments
The Assessment shape
| Field | Type | Notes |
|---|---|---|
modelElementId | string | The diagram element this assessment grades. Required. |
elementType | string | The element's type (e.g. "Class"). Required. |
score | number | Points awarded. Required. |
feedback | string? | Free-text feedback. |
label | string? | Short label shown on the element. |
labelColor | string? | CSS color for the label. |
correctionStatus | { status: "CORRECT" | "INCORRECT" | "NOT_VALIDATED"; description?: string }? | For automated/suggested feedback review. |
Drive the canvas from a feedback list
A host that lists feedback beside the diagram has a problem the list alone cannot solve: an entry says what a tutor wrote, never where it applies. The reader is left matching text against boxes by eye.
revealAssessment closes that loop. It selects the element, opens its feedback
popover, and pans the canvas to it — keeping the reader's zoom, because the zoom
is theirs.
import { ApollonEditor } from "@tumaet/apollon"
function showFeedbackFor(
editor: ApollonEditor,
feedback: { elementId: string }
) {
editor.revealAssessment(feedback.elementId)
}
// Closing the list, or deselecting, puts the canvas back:
function clearFeedback(editor: ApollonEditor) {
editor.revealAssessment(null)
}
Pass { reveal: false } to select without panning — useful when the element is
already on screen and moving the canvas would be disorienting.
Pair it with subscribeToAssessmentSelection for the other direction, so
clicking an element marks its entry in the list. Together the two halves explain
each other instead of sitting side by side.
The popover only opens in ApollonMode.Assessment. In assessment with
readonly — a student reading a graded diagram — it opens the read-only
feedback popover; without readonly, the tutor's editable one.
Highlight elements
setElementHighlights rings elements by id with a CSS color — e.g. to mark the
elements that still need feedback. It draws an outline rather than a fill, so use
opaque colors: the element's own content, including its assessment badge,
stays fully visible underneath. Highlights are ephemeral: they are not serialized into
the model and not shared over collaboration. Pass null or an empty map to clear.
To color a whole group of attributes/methods at once — e.g. by a build result — address them by tag first; see Element tags & group coloring.
import { ApollonEditor } from "@tumaet/apollon"
function highlightMissing(editor: ApollonEditor) {
editor.setElementHighlights(
new Map([
["node-2", "#0d6efd"],
["node-5", "#0d6efd"],
])
)
}
React to the element being assessed
subscribeToAssessmentSelection fires with the ids of the elements the grader
selected, so you can show the matching feedback form. Like every subscribeTo*
method it returns a numeric id you pass to editor.unsubscribe to tear down.
import { ApollonEditor } from "@tumaet/apollon"
function watchAssessmentSelection(editor: ApollonEditor) {
const subId = editor.subscribeToAssessmentSelection((selectedElementIds) => {
// open the feedback form for selectedElementIds[0], etc.
console.log("assessing", selectedElementIds)
})
return () => editor.unsubscribe(subId)
}
See also
- Model contract — the
UMLModelandAssessmentshapes in full. - Overlay controls — inject a feedback panel into the editor canvas.