Hyperion: Fix instructor checklist bugs and improve UI/UX#12546
Hyperion: Fix instructor checklist bugs and improve UI/UX#12546
Hyperion: Fix instructor checklist bugs and improve UI/UX#12546Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds robust JSON extraction/parsing for LLM checklist analysis with longer per-task timeouts; implements competency multi-select (select/deselect all, apply selected, dismiss selected) with UI, logic, styles, and tests; migrates several components to callable viewChilds for Monaco editor access and updates related tests and i18n strings. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~65 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html (2)
363-417:⚠️ Potential issue | 🟠 MajorAdd accessible names to the new per-competency controls.
The row checkbox has no associated label, and the trash button is icon-only with just a
title. That makes selecting or dismissing a specific competency hard to use with screen readers.Suggested fix
<p-checkbox [binary]="true" [ngModel]="isCompetencySelected(i)" (ngModelChange)="toggleCompetencySelection(i)" [disabled]="isLoading() || isApplyingAction() || isSyncingCompetencies() || sectionLoading().size > 0" [inputId]="'competency-select-' + i" + [ariaLabel]="comp.competencyTitle" [attr.data-testid]="'competency-checkbox-' + i" /> @@ <button pButton severity="secondary" size="small" [text]="true" [disabled]="isLoading() || isApplyingAction() || isSyncingCompetencies() || sectionLoading().size > 0" (click)="discardCompetency(i)" + [attr.aria-label]="('artemisApp.programmingExercise.instructorChecklist.competencies.discardCompetency' | artemisTranslate) + ': ' + comp.competencyTitle" [attr.title]="'artemisApp.programmingExercise.instructorChecklist.competencies.discardCompetency' | artemisTranslate" [attr.data-testid]="'discard-competency-' + i" >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html` around lines 363 - 417, The checkbox and icon-only trash button lack accessible names; update the p-checkbox (used with isCompetencySelected/toggleCompetencySelection) to include an aria-label or aria-labelledby that identifies the competency (e.g., aria-label="Select competency {{ comp.competencyTitle }}" or aria-labelledby pointing to a visually-hidden span containing comp.competencyTitle), and add an explicit accessible name to the discard button (discardCompetency) by adding aria-label="Discard competency {{ comp.competencyTitle }}" or a visually-hidden text node tied with aria-labelledby; ensure any new visually-hidden spans use a consistent sr-only class so screen readers get the competency context while visual layout remains unchanged.
358-420:⚠️ Potential issue | 🟠 MajorDon't key mutable competency state by
$index.The new selection/expand/discard flow is all index-based here. If
discardCompetency(i)or a re-analysis removes/reorders an earlier item, the checked/expanded state can shift to a different competency on the next render, and bulk actions can target the wrong rows. Please switch this state to a stable competency key instead of$index.Verify whether the component currently reindexes these sets after every mutation. Expected result: either a stable identifier is used for selection/expansion state, or all stored indices are updated after remove/reorder operations.
#!/bin/bash set -euo pipefail FILE="src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts" echo "== Relevant state and handlers ==" rg -n -C3 'selectedCompetencyIndices|toggleCompetencySelection|selectAllCompetencies|deselectAllCompetencies|discardCompetency|discardSelectedCompetencies|isCompetencyExpanded|toggleCompetencyExpand|applySelectedCompetencies' "$FILE" echo echo "== Full method bodies around discard / selection logic ==" sed -n '/selectedCompetencyIndices/,+80p' "$FILE" sed -n '/discardCompetency/,+80p' "$FILE" sed -n '/discardSelectedCompetencies/,+80p' "$FILE" sed -n '/toggleCompetencyExpand/,+40p' "$FILE"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html` around lines 358 - 420, The template and component currently key selection/expansion by $index (used in selectedCompetencyIndices, toggleCompetencySelection, isCompetencyExpanded, toggleCompetencyExpand, discardCompetency, discardSelectedCompetencies, applySelectedCompetencies), which will mis-assign state after removals/reorders; change these to use a stable competency identifier (e.g., comp.id or comp.competencyId) instead of $index in the template and store selection/expanded state as sets/maps of that id in the component; update toggleCompetencySelection, toggleCompetencyExpand, discardCompetency, discardSelectedCompetencies and any bulk actions to operate on ids (or to remap stored indices to new indices immediately after any mutation), and ensure the *ngFor uses a trackBy that returns the stable id for result.inferredCompetencies; finally, verify whether the component currently reindexes after mutations by checking selectedCompetencyIndices and the handlers listed above and confirm either ids are used or all stored indices are updated on remove/reorder.
🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts (1)
632-717: Consider extracting a shared selection/discard helper to deduplicate with quality-issue logic.The new competency methods (
toggleCompetencySelection,isCompetencySelected,selectAllCompetencies,deselectAllCompetencies,allCompetenciesSelected,discardCompetency,discardSelectedCompetencies) mirror the corresponding quality-issue methods (toggleIssueSelection,isIssueSelected,selectAllIssues,deselectAllIssues,allIssuesSelected,discardQualityIssue,discardSelectedIssues) almost line-for-line, including the identical re-indexing logic on discard. A generic helper parameterized by the selection signal and a(response) => T[]accessor would remove this duplication and keep the two flows in sync if the pattern is extended further (e.g., a third list later on). Not blocking — happy to defer to a follow-up.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts` around lines 632 - 717, The competency selection/discard methods duplicate the quality-issue methods; extract a generic helper (e.g., createSelectionHelpers) that accepts a selection signal (like selectedCompetencyIndices / selectedQualityIssueIndices) and an accessor function for the list (e.g., (r) => r.inferredCompetencies or (r) => r.qualityIssues) and implements toggle, isSelected, selectAll, deselectAll, allSelected, discard(index) and discardSelected(), then replace toggleCompetencySelection, isCompetencySelected, selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected, discardCompetency and discardSelectedCompetencies to delegate to the appropriate helper instance so the re-indexing logic and optimistic update call sites (updateAnalysisOptimistically, alertService.success) are reused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Line 406: The change replaced alertService.success with alertService.info
inside applyAction, which unintentionally makes all AI apply actions show an
info (blue) alert; restore success for quality-fix actions and only use info for
adaptDifficulty by adding a boolean flag (e.g., useInfoAlert) to applyAction and
its callers; update callers fixQualityIssue, fixAllQualityIssues,
fixSelectedIssues to call applyAction(..., useInfoAlert = false) and
adaptDifficulty to call applyAction(..., useInfoAlert = true), then branch
inside applyAction to call alertService.success(...) when useInfoAlert is false
and alertService.info(...) when true so behavior matches
discardCompetency/discardQualityIssue consistency.
- Around line 708-717: The method applySelectedCompetencies builds
selectedInferred but can pass an empty array into applyCompetenciesFromList
which triggers a full sync and a misleading "allLinked" warning; add an
early-return after computing selectedInferred in applySelectedCompetencies: if
selectedInferred.length === 0 return; so you don't call
applyCompetenciesFromList([]) (which leads to
loadCourseCompetencies/reconcileCompetencies/finishApply showing the warning).
---
Outside diff comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`:
- Around line 363-417: The checkbox and icon-only trash button lack accessible
names; update the p-checkbox (used with
isCompetencySelected/toggleCompetencySelection) to include an aria-label or
aria-labelledby that identifies the competency (e.g., aria-label="Select
competency {{ comp.competencyTitle }}" or aria-labelledby pointing to a
visually-hidden span containing comp.competencyTitle), and add an explicit
accessible name to the discard button (discardCompetency) by adding
aria-label="Discard competency {{ comp.competencyTitle }}" or a visually-hidden
text node tied with aria-labelledby; ensure any new visually-hidden spans use a
consistent sr-only class so screen readers get the competency context while
visual layout remains unchanged.
- Around line 358-420: The template and component currently key
selection/expansion by $index (used in selectedCompetencyIndices,
toggleCompetencySelection, isCompetencyExpanded, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies, applySelectedCompetencies),
which will mis-assign state after removals/reorders; change these to use a
stable competency identifier (e.g., comp.id or comp.competencyId) instead of
$index in the template and store selection/expanded state as sets/maps of that
id in the component; update toggleCompetencySelection, toggleCompetencyExpand,
discardCompetency, discardSelectedCompetencies and any bulk actions to operate
on ids (or to remap stored indices to new indices immediately after any
mutation), and ensure the *ngFor uses a trackBy that returns the stable id for
result.inferredCompetencies; finally, verify whether the component currently
reindexes after mutations by checking selectedCompetencyIndices and the handlers
listed above and confirm either ids are used or all stored indices are updated
on remove/reorder.
---
Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Around line 632-717: The competency selection/discard methods duplicate the
quality-issue methods; extract a generic helper (e.g., createSelectionHelpers)
that accepts a selection signal (like selectedCompetencyIndices /
selectedQualityIssueIndices) and an accessor function for the list (e.g., (r) =>
r.inferredCompetencies or (r) => r.qualityIssues) and implements toggle,
isSelected, selectAll, deselectAll, allSelected, discard(index) and
discardSelected(), then replace toggleCompetencySelection, isCompetencySelected,
selectAllCompetencies, deselectAllCompetencies, allCompetenciesSelected,
discardCompetency and discardSelectedCompetencies to delegate to the appropriate
helper instance so the re-indexing logic and optimistic update call sites
(updateAnalysisOptimistically, alertService.success) are reused.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 720a4e96-226b-45d7-8e5d-0ae5c3b476ce
📒 Files selected for processing (9)
src/main/java/de/tum/cit/aet/artemis/hyperion/service/HyperionChecklistService.javasrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.htmlsrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.scsssrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.tssrc/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.htmlsrc/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.tssrc/main/webapp/i18n/de/programmingExercise.jsonsrc/main/webapp/i18n/en/programmingExercise.jsonsrc/test/java/de/tum/cit/aet/artemis/hyperion/service/HyperionChecklistServiceTest.java
|
@HawKhiem Test coverage could not be fully measured because some tests failed. Please check the workflow logs for details. |
End-to-End Test Results
Test Strategy: Two-phase execution
Overall: ✅ All E2E tests passed (both phases) 🔗 Workflow Run · 📊 Test Report |
|
@HawKhiem Test coverage could not be fully measured because some tests failed. Please check the workflow logs for details. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts (1)
632-703: Consider extracting the selection/discard boilerplate into reusable helpers.The new competency multi-select API (
toggleCompetencySelection,isCompetencySelected,selectAllCompetencies,deselectAllCompetencies,allCompetenciesSelected,discardCompetency,discardSelectedCompetencies) is an almost verbatim copy of the existing quality-issue counterparts (toggleIssueSelectionat Line 548,isIssueSelectedat Line 563,selectAllIssues/deselectAllIssues/allIssuesSelectedat Lines 570–588, and the reindex-on-discard block at Lines 533–541). The two sets only differ by which signal and which list onanalysisResult()they touch.A small generic helper would remove the duplication and keep future behavioral tweaks (e.g., how selections are reindexed after discard) in one place, e.g.:
private toggleInSet<T>(sig: WritableSignal<Set<T>>, item: T) { ... } private reindexAfterRemoval(sig: WritableSignal<Set<number>>, removedIndex: number) { ... } private allSelected(sig: WritableSignal<Set<number>>, count: number): boolean { ... }Non-blocking; safe to defer.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts` around lines 632 - 703, The competency selection/discard methods duplicate the quality-issue counterparts (e.g., toggleCompetencySelection vs toggleIssueSelection, discardCompetency vs the reindex-on-discard block) — extract shared helpers to remove boilerplate: add a generic toggleInSet<T>(sig: WritableSignal<Set<T>>, item: T) and reuse it from toggleCompetencySelection/toggleIssueSelection; add reindexAfterRemoval(sig: WritableSignal<Set<number>>, removedIndex: number) to centralize the reindex loop used in discardCompetency and the issue discard path; add helpers allSelected(sig: WritableSignal<Set<number>>, count: number), selectAll(sig: WritableSignal<Set<number>>, count: number) and deselectAll(sig: WritableSignal<Set<number>>) and replace implementations that touch selectedCompetencyIndices/selectedIssueIndices and updateAnalysisOptimistically to call these helpers so behavior stays identical but duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.html`:
- Around line 409-423: The expand/collapse state stored in the
expandedCompetencies Set isn't reindexed when items are removed, so
discardCompetency(i) and discardSelectedCompetencies(...) should update
expandedCompetencies the same way selectedCompetencyIndices is adjusted: when
removing a single index in discardCompetency(i), create a new Set remapping each
stored index > i to index-1 (and discarding the removed index); when removing
multiple selected indices in discardSelectedCompetencies, rebuild
expandedCompetencies by skipping removed indices and shifting higher indices
down according to how many removed indices precede them. Update the code paths
in discardCompetency and discardSelectedCompetencies to perform this reindexing
so isCompetencyExpanded($index) and toggleCompetencyExpand($index) remain
consistent.
---
Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.ts`:
- Around line 632-703: The competency selection/discard methods duplicate the
quality-issue counterparts (e.g., toggleCompetencySelection vs
toggleIssueSelection, discardCompetency vs the reindex-on-discard block) —
extract shared helpers to remove boilerplate: add a generic toggleInSet<T>(sig:
WritableSignal<Set<T>>, item: T) and reuse it from
toggleCompetencySelection/toggleIssueSelection; add reindexAfterRemoval(sig:
WritableSignal<Set<number>>, removedIndex: number) to centralize the reindex
loop used in discardCompetency and the issue discard path; add helpers
allSelected(sig: WritableSignal<Set<number>>, count: number), selectAll(sig:
WritableSignal<Set<number>>, count: number) and deselectAll(sig:
WritableSignal<Set<number>>) and replace implementations that touch
selectedCompetencyIndices/selectedIssueIndices and updateAnalysisOptimistically
to call these helpers so behavior stays identical but duplication is removed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f899eb2b-fc77-4838-830f-36771400d8a6
📒 Files selected for processing (6)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.htmlsrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.tssrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.tssrc/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.tssrc/main/webapp/i18n/de/programmingExercise.jsonsrc/main/webapp/i18n/en/programmingExercise.json
🚧 Files skipped from review as they are similar to previous changes (3)
- src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
- src/main/webapp/i18n/en/programmingExercise.json
- src/main/webapp/i18n/de/programmingExercise.json
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
1 similar comment
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts (1)
1022-1039: Assert the created competency request uses the selected item.Line 1023 returns
Sortingfor everycreate()call, so this test could still pass if the implementation accidentally creates unselectedRecursionand receives the mockedSortingresponse. Capture the spy and assert the request payload targetsSorting.Proposed test tightening
- vi.spyOn(competencyService, 'create').mockReturnValue(of(new HttpResponse({ body: createdSorting })) as any); + const createSpy = vi.spyOn(competencyService, 'create').mockReturnValue(of(new HttpResponse({ body: createdSorting })) as any); @@ expect(competencyService.getAllForCourse).toHaveBeenCalledWith(courseId); + expect(createSpy).toHaveBeenCalledTimes(1); + expect(createSpy).toHaveBeenCalledWith(expect.objectContaining({ title: 'Sorting' }), courseId); expect(emitSpy).toHaveBeenCalled();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts` around lines 1022 - 1039, The test currently stubs competencyService.create to always return a Competency titled "Sorting", masking whether the code actually created the selected item; update the spec to capture and assert the create call payload: replace the static mockReturnValue with a spy/mockImplementation that records the argument (or keep the spy and inspect competencyService.create.mock.calls), then after component.applySelectedCompetencies() assert that competencyService.create was invoked with an object representing the selected competency (title 'Sorting' or the exact competency instance from the selected index) and that no create call was made for 'Recursion'; reference component.applySelectedCompetencies and competencyService.create when locating the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.ts`:
- Around line 1022-1039: The test currently stubs competencyService.create to
always return a Competency titled "Sorting", masking whether the code actually
created the selected item; update the spec to capture and assert the create call
payload: replace the static mockReturnValue with a spy/mockImplementation that
records the argument (or keep the spy and inspect
competencyService.create.mock.calls), then after
component.applySelectedCompetencies() assert that competencyService.create was
invoked with an object representing the selected competency (title 'Sorting' or
the exact competency instance from the selected index) and that no create call
was made for 'Recursion'; reference component.applySelectedCompetencies and
competencyService.create when locating the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 91af568d-609b-4c9a-9558-bbf8a1419d39
📒 Files selected for processing (3)
src/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.spec.tssrc/main/webapp/app/programming/manage/update/update-components/problem/checklist-panel/checklist-panel.component.tssrc/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/main/webapp/app/shared/markdown-editor/monaco/markdown-editor-monaco.component.ts
…bugs-and-improve-ui
…ve-ui' of https://github.com/ls1intum/Artemis into bugfix/hyperion/fix-instructor-checklist-bugs-and-improve-ui
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
1 similar comment
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
1 similar comment
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
Hyperion: Fix instructor checklist bugs and improve UIHyperion: Fix instructor checklist bugs and improve UI/UX
Claudia-Anthropica
left a comment
There was a problem hiding this comment.
@HawKhiem Clean work — the per-Mono timeout fix correctly isolates failures, the defensive JSON extraction handles the common LLM wrapping cases well, and the competency multi-select is well-implemented with proper index reindexing. The viewChild signal migration is comprehensive and correct. Just one minor nit inline.
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
Claudia-Anthropica
left a comment
There was a problem hiding this comment.
@HawKhiem Solid work. The timeout isolation fix, JSON extraction, viewChild migration, and competency multi-select are all clean and well-tested. Approving as-is.
…bugs-and-improve-ui
|
@HawKhiem Test coverage has been automatically updated in the PR description. |
Summary
Fix several bugs and usability issues in the Hyperion instructor checklist discovered during testing. The main issues were: (1) backend analysis timing out due to a single shared timeout cancelling all three concurrent LLM calls, (2) LLM responses wrapped in markdown code blocks causing JSON parse failures, (3) no way to individually select/manage inferred learning goals, (4) diff view resize handle being hidden behind diff headers, (5) a misleading success alert after applying difficulty changes, and (6) stale task/test counts and declared difficulty in the Difficulty Assessment section.
Checklist
General
Server
Client
Motivation and Context
The Hyperion instructor checklist (Analyze Problem Statement) was unreliable during testing:
Mono.zip().timeout()cancelled all three concurrent LLM calls (competency inference, difficulty assessment, quality analysis) as soon as any one of them was slow, causingInterruptedExceptionin the Azure OpenAI SDK. This is mentioned in issueHyperion: Instructor checklist analysis result empty #12565```json ... ```), which theObjectMappercould not parse directly.Hyperion: Resize draggable pushed out of visible field when in diff mode #12404Description
Server —
HyperionChecklistService.java:.timeout(ANALYSIS_TIMEOUT)fromMono.zip()to each individual Mono (competenciesMono,difficultyMono,qualityMono). This ensures a slow call only affects itself — the other two analyses complete independently. Increased timeout from 60 seconds to 5 minutes to accommodate slower LLM responses.extractJsonPayload()method with a compiledJSON_CODE_BLOCK_PATTERNregex (now lazy to avoid over-matching). It tries three strategies in order: (1) extract from markdown code fences, (2) extract embedded{...}substring, (3) fall back to raw text. Applied to all three analysis methods.Server tests —
HyperionChecklistServiceTest.java:analyzeChecklist_handlesJsonWrappedInCodeBlockandanalyzeChecklist_handlesJsonWithLeadingTextverifying the JSON extraction handles wrapped/embedded responses correctly.Client —
checklist-panel.component.ts/html/scss:selectedCompetencyIndicessignal and 8 new methods (toggleCompetencySelection,isCompetencySelected,selectAllCompetencies,deselectAllCompetencies,allCompetenciesSelected,discardCompetency,discardSelectedCompetencies,applySelectedCompetencies). The UI now includes a toolbar with Select All checkbox, Apply Selected, Discard Selected, and Apply All buttons. Each competency item has an individual checkbox, expand toggle, and discard button.localTaskTestCounts, acomputed()signal that parses[task]markers from the live problem statement. The counts update immediately on every problem statement edit — no re-analysis required.declaredDifficultyinput (primitive string) and alocalDeclaredDifficultysignal. The "vs. Declared" row now shows a badge with the current declared difficulty level and reacts immediately to both: (a) clicking an "Adapt to" button in the checklist panel, and (b) changing the difficulty in the exercise form outside the panel. The "Adapt to" buttons also update their highlighted/disabled state instantly.alertService.success()toalertService.info()inapplyAction()and updated the message to prompt review before saving.Client —
markdown-editor-monaco.component.ts/html:viewChild('diffHeader')signal to track the diff pane header element. UpdatedgetEditorHeight()to subtract the header's height from the available space, preventing the Monaco editor from overflowing below the resize handle. RenameddiffSashMovedoutput todiffOriginalPaneLayoutChangedfor clarity.viewChild()migration: Migrated all@ViewChilddecorators inmarkdown-editor-monaco.component.tsto Angular's signal-basedviewChild()API. Mixing decorator-based@ViewChildwith signal-basedviewChild()in the same component caused ng-mocks to fail during test compilation, so a full migration of the component was necessary. This required updating several consumer components and their tests that reference the editor's view children (e.g.,programming-exercise-editable-instruction.component.ts,posting-markdown-editor.component.ts,short-answer-question-edit.component.ts,multiple-choice-question-edit.component.spec.ts,monaco-editor.component.ts).Translations —
en/de programmingExercise.json:applyAll,applySelected,selectAll,deselectAll,discardSelected,discarded,discardedMultiple,discardCompetency).actions.successmessage in both languages to prompt the user to review changes.SCSS —
monaco-editor.component.scss:@import 'node_modules/@vscode/codicons/dist/codicon.css'to@import '@vscode/codicons/dist/codicon.css', removing the hardcodednode_modules/prefix so the SCSS resolver can find the package in CI environments where the working directory differs from the project root.Steps for Testing
Prerequisites:
Bug fix — Analysis timeout:
Bug fix — JSON code block parsing:
./gradlew test --tests HyperionChecklistServiceTest -x webappFeature — Competency multi-select:
Bug fix — Diff view resize handle:
Bug fix — Alert tone:
Improvement — Live Tasks/Tests counts:
[task]marker.Improvement — Live "vs. Declared" difficulty:
Testserver States
You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.
Review Progress
Performance Review
Code Review
Manual Tests
Test Coverage
Client
Server
Last updated: 2026-04-21 15:01:24 UTC
Screenshots