Skip to content

Commit

Permalink
improve integration of monaco code editor and preliminary feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
dmytropolityka committed Nov 14, 2024
1 parent 8205b58 commit 539ab1d
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
import de.tum.cit.aet.artemis.assessment.domain.Result;
import de.tum.cit.aet.artemis.assessment.repository.ResultRepository;
import de.tum.cit.aet.artemis.assessment.service.ResultService;
import de.tum.cit.aet.artemis.athena.dto.ProgrammingFeedbackDTO;
import de.tum.cit.aet.artemis.athena.service.AthenaFeedbackSuggestionsService;
import de.tum.cit.aet.artemis.communication.service.notifications.GroupNotificationService;
import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.exercise.service.SubmissionService;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingExerciseStudentParticipation;
import de.tum.cit.aet.artemis.programming.domain.ProgrammingSubmission;
import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseStudentParticipationRepository;

/**
Expand Down Expand Up @@ -137,8 +137,12 @@ public void generateAutomaticNonGradedFeedback(ProgrammingExerciseStudentPartici

log.debug("Submission id: {}", submission.getId());

var athenaResponse = this.athenaFeedbackSuggestionsService.orElseThrow().getProgrammingFeedbackSuggestions(programmingExercise, (ProgrammingSubmission) submission,
false);
/*
* var athenaResponse = this.athenaFeedbackSuggestionsService.orElseThrow().getProgrammingFeedbackSuggestions(programmingExercise, (ProgrammingSubmission) submission,
* false);
*/
var athenaResponse = List.of(new ProgrammingFeedbackDTO(0, 1, 2, "aaa1", "aaas", 3, null, "Xpense/XpenseModel/Model Objects/Transaction.swift", 0, 1),
new ProgrammingFeedbackDTO(1, 1, 2, "bbb2", "bbbs", 3, null, "Xpense/XpenseModel/Model Objects/Transaction.swift", 3, 4));

List<Feedback> feedbacks = athenaResponse.stream().filter(individualFeedbackItem -> individualFeedbackItem.filePath() != null)
.filter(individualFeedbackItem -> individualFeedbackItem.description() != null).map(individualFeedbackItem -> {
Expand All @@ -147,11 +151,11 @@ public void generateAutomaticNonGradedFeedback(ProgrammingExerciseStudentPartici
if (Objects.nonNull(individualFeedbackItem.lineStart())) {
if (Objects.nonNull(individualFeedbackItem.lineEnd()) && !individualFeedbackItem.lineStart().equals(individualFeedbackItem.lineEnd())) {
feedbackText = String.format(NON_GRADED_FEEDBACK_SUGGESTION + "File %s at lines %d-%d", individualFeedbackItem.filePath(),
individualFeedbackItem.lineStart(), individualFeedbackItem.lineEnd());
individualFeedbackItem.lineStart() + 1, individualFeedbackItem.lineEnd() + 1);
}
else {
feedbackText = String.format(NON_GRADED_FEEDBACK_SUGGESTION + "File %s at line %d", individualFeedbackItem.filePath(),
individualFeedbackItem.lineStart());
individualFeedbackItem.lineStart() + 1);
}
feedback.setReference(String.format("file:%s_line:%d", individualFeedbackItem.filePath(), individualFeedbackItem.lineStart()));
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/webapp/app/entities/feedback.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ export const buildFeedbackTextForReview = (feedback: Feedback, addFeedbackText =
}
} else if (feedback.detailText) {
feedbackText = feedback.detailText;
if (feedback.text && feedback.text.includes('lines')) {
const linesInfo = feedback.text.match(/lines .*/);
if (linesInfo) {
feedbackText += ` (${linesInfo[0]})`;
}
}
} else if (addFeedbackText && feedback.text) {
feedbackText = feedback.text;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,28 @@
}
</div>
} @else {
<div class="p-1">
<div class="p-1 position-relative">
<button
type="button"
class="btn-close position-absolute top-0 end-0 m-1 rounded-circle"
aria-label="Close"
(click)="deleteFeedback()"
[ngbTooltip]="'artemisApp.assessment.subsequentFeedback' | artemisTranslate"
style="width: 20px; height: 20px; padding: 2px; display: flex; align-items: center; justify-content: center; border: 1px solid #000; color: #000"
>
<span aria-hidden="true" style="font-size: 10px; line-height: 1">&times;</span>
</button>
<div class="row flex-nowrap align-items-top m-1">
<div class="col flex-grow-0 ps-0">
<h5 class="d-inline">
@if (!Feedback.isNonGradedFeedbackSuggestion(feedback)) {
<span
class="badge"
[class.bg-success]="feedback.credits! > 0 && feedback.isSubsequent === undefined"
[class.bg-danger]="feedback.credits! < 0 && feedback.isSubsequent === undefined"
[class.bg-warning]="feedback.credits === 0 && feedback.isSubsequent === undefined"
[class.bg-secondary]="readOnly && feedback.isSubsequent"
>{{ roundScoreSpecifiedByCourseSettings(feedback.credits, course) + 'P' }}</span
>
}
<span
class="badge"
[class.bg-success]="feedback.credits! > 0 && feedback.isSubsequent === undefined"
[class.bg-danger]="feedback.credits! < 0 && feedback.isSubsequent === undefined"
[class.bg-warning]="feedback.credits === 0 && feedback.isSubsequent === undefined"
[class.bg-secondary]="readOnly && feedback.isSubsequent"
>{{ roundScoreSpecifiedByCourseSettings(feedback.credits, course) + 'P' }}</span
>
</h5>
</div>
<div class="col-10 ps-0 flex-grow-1 flex-shrink-1">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@
[showEditorInstructions]="showEditorInstructions"
[isTutorAssessment]="hasTutorAssessment"
[readOnlyManualFeedback]="true"
[latestResult]="latestResult"
[course]="course"
>
>
<div editorTitle>
<span>{{ exercise?.title }}</span>
<!-- prettier-ignore -->
Expand Down Expand Up @@ -73,7 +75,8 @@
[showBadge]="true"
[participation]="participation"
[personalParticipation]="true"
(onParticipationChange)="receivedNewResult()"
(onParticipationChange)="receivedParticipationChange()"
(showResult)="receivedNewResult($event)"
class="me-2"
/>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ExerciseHintService } from 'app/exercises/shared/exercise-hint/shared/e
import { HttpResponse } from '@angular/common/http';
import { AlertService } from 'app/core/util/alert.service';
import { isManualResult as isManualResultFunction } from 'app/exercises/shared/result/result.utils';
import { StudentParticipation } from 'app/entities/participation/student-participation.model';

Check failure on line 30 in src/main/webapp/app/exercises/programming/participate/code-editor-student-container.component.ts

View workflow job for this annotation

GitHub Actions / client-style

'StudentParticipation' is defined but never used

@Component({
selector: 'jhi-code-editor-student',
Expand Down Expand Up @@ -177,11 +178,15 @@ export class CodeEditorStudentContainerComponent implements OnInit, OnDestroy {
return [];
}

receivedNewResult() {
receivedParticipationChange() {
this.loadStudentExerciseHints();
this.getNumberOfSubmissionsForSubmissionPolicy();
}

receivedNewResult(result: Result) {
this.latestResult = result;
}

loadStudentExerciseHints() {
this.exerciseHintService.getActivatedExerciseHints(this.exercise.id!).subscribe((activatedRes?: HttpResponse<ExerciseHint[]>) => {
this.activatedExerciseHints = activatedRes!.body!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { Feedback } from 'app/entities/feedback.model';
import { Course } from 'app/entities/course.model';
import { ConnectionError } from 'app/exercises/programming/shared/code-editor/service/code-editor-repository.service';
import { Annotation, CodeEditorMonacoComponent } from 'app/exercises/programming/shared/code-editor/monaco/code-editor-monaco.component';
import { Result } from 'app/entities/result.model';

export enum CollapsableCodeEditorElement {
FileBrowser,
Expand Down Expand Up @@ -87,6 +88,8 @@ export class CodeEditorContainerComponent implements OnChanges {
onDiscardSuggestion = new EventEmitter<Feedback>();
@Input()
course?: Course;
@Input()
latestResult?: Result;

/** Work in Progress: temporary properties needed to get first prototype working */

Expand Down Expand Up @@ -116,9 +119,12 @@ export class CodeEditorContainerComponent implements OnChanges {
}

ngOnChanges(changes: SimpleChanges) {
// Update file badges when feedback suggestions change
// Update file badges when feedback or feedback suggestions change
if (changes.feedbackSuggestions) {
this.updateFileBadges();
this.updateFileBadgesForFeedbackSuggestions();
}
if (changes.latestResult) {
this.updateFileBadgesForPreliminaryFeedback();
}
}

Expand Down Expand Up @@ -149,9 +155,9 @@ export class CodeEditorContainerComponent implements OnChanges {
}

/**
* Update the file badges for the code editor (currently only feedback suggestions)
* Update the file badges for the code editor for feedback suggestions
*/
updateFileBadges() {
updateFileBadgesForFeedbackSuggestions() {
this.fileBadges = {};
// Create badges for feedback suggestions
// Get file paths from feedback suggestions:
Expand All @@ -165,6 +171,22 @@ export class CodeEditorContainerComponent implements OnChanges {
}
}

/**
* Update the file badges for the code editor for preliminary feedback
*/
updateFileBadgesForPreliminaryFeedback() {
this.fileBadges = {};
// Create badges for preliminary feedback
const feedbacks = this.latestResult?.feedbacks ?? [];
// Get file paths from feedback:
const filePaths = feedbacks.map((feedback) => Feedback.getReferenceFilePath(feedback)).filter((filePath) => filePath !== undefined) as string[];
for (const filePath of filePaths) {
// Count the number of feedback for this file
const feedbackCount = feedbacks.filter((feedback) => Feedback.getReferenceFilePath(feedback) === filePath).length;
this.fileBadges[filePath] = [new FileBadge(FileBadgeType.PRELIMINARY_FEEDBACK, feedbackCount)];
}
}

/**
* Resets all variables of this class.
* When a new variable is added, it needs to be added to this method!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { IconDefinition, faLightbulb } from '@fortawesome/free-solid-svg-icons';
import { faLightbulb, IconDefinition } from '@fortawesome/free-solid-svg-icons';

Check failure on line 2 in src/main/webapp/app/exercises/programming/shared/code-editor/file-browser/code-editor-file-browser-badge.component.ts

View workflow job for this annotation

GitHub Actions / client-style

Member 'IconDefinition' of the import declaration should be sorted alphabetically
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
import { FileBadge, FileBadgeType } from 'app/exercises/programming/shared/code-editor/model/code-editor.model';
Expand All @@ -20,6 +20,8 @@ export class CodeEditorFileBrowserBadgeComponent {
switch (this.badge.type) {
case FileBadgeType.FEEDBACK_SUGGESTION:
return this.translateService.instant('artemisApp.editor.fileBrowser.fileBadgeTooltips.feedbackSuggestions');
case FileBadgeType.PRELIMINARY_FEEDBACK:
return this.translateService.instant('artemisApp.editor.fileBrowser.fileBadgeTooltips.preliminaryFeedback');
default:
return undefined;
}
Expand All @@ -29,6 +31,8 @@ export class CodeEditorFileBrowserBadgeComponent {
switch (this.badge.type) {
case FileBadgeType.FEEDBACK_SUGGESTION:
return faLightbulb;
case FileBadgeType.PRELIMINARY_FEEDBACK:
return faLightbulb;
default:
return undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export enum GitConflictState {
*/
export enum FileBadgeType {
FEEDBACK_SUGGESTION = 'FEEDBACK_SUGGESTION',
PRELIMINARY_FEEDBACK = 'PRELIMINARY_FEEDBACK',
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class UpdatingResultComponent implements OnChanges, OnDestroy {
@Input() showIcon = true;
@Input() isInSidebarCard = false;
@Input() showCompletion = true;
@Output() showResult = new EventEmitter<void>();
@Output() showResult = new EventEmitter<Result>();
/**
* @property personalParticipation Whether the participation belongs to the user (by being a student) or not (by being an instructor)
*/
Expand Down Expand Up @@ -70,7 +70,7 @@ export class UpdatingResultComponent implements OnChanges, OnDestroy {
}

if (this.result) {
this.showResult.emit();
this.showResult.emit(this.result);
}
}
}
Expand Down Expand Up @@ -115,7 +115,7 @@ export class UpdatingResultComponent implements OnChanges, OnDestroy {
}
this.onParticipationChange.emit();
if (result) {
this.showResult.emit();
this.showResult.emit(this.result);
}
}),
)
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/i18n/de/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"deleteFile": "Datei löschen",
"compressTree": "Leere Verzeichnisse zusammenfassen",
"fileBadgeTooltips": {
"feedbackSuggestions": "Anzahl von Feedback-Vorschlägen in dieser Datei / diesem Ordner"
"feedbackSuggestions": "Anzahl von Feedback-Vorschlägen in dieser Datei / diesem Ordner",
"feedback": "Anzahl von Feedback Elementen in dieser Datei / diesem Ordner"
}
},
"errors": {
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/i18n/en/editor.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"deleteFile": "Delete file",
"compressTree": "Combine empty folders",
"fileBadgeTooltips": {
"feedbackSuggestions": "Number of feedback suggestions in this file/folder"
"feedbackSuggestions": "Number of feedback suggestions in this file/folder",
"preliminaryFeedback": "Number of preliminary feedback items in this file/folder"
}
},
"errors": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,6 @@ describe('CodeEditorStudentContainerComponent', () => {
expect(getParticipationSubmissionCountSpy).not.toHaveBeenCalled();
},
);

it('Should invalidate old feedback suggestions when new feedback arrives', () => {});
});

0 comments on commit 539ab1d

Please sign in to comment.