Skip to content

Commit

Permalink
Development: Migrate exercise group client code to signals (#10332)
Browse files Browse the repository at this point in the history
  • Loading branch information
coolchock authored Feb 17, 2025
1 parent b80e594 commit 696d645
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 142 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@if (fileUploadExercise.type === exerciseType.FILE_UPLOAD) {
{{ fileUploadExercise.filePattern || '' }}
@if (exercise().type === exerciseType.FILE_UPLOAD) {
{{ exercise().filePattern || '' }}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, Input } from '@angular/core';
import { Component, input } from '@angular/core';
import { ExerciseType } from 'app/entities/exercise.model';
import { FileUploadExercise } from 'app/entities/file-upload-exercise.model';
import { Exercise, ExerciseType } from 'app/entities/exercise.model';

@Component({
selector: 'jhi-file-upload-exercise-group-cell',
Expand All @@ -9,11 +9,5 @@ import { Exercise, ExerciseType } from 'app/entities/exercise.model';
})
export class FileUploadExerciseGroupCellComponent {
exerciseType = ExerciseType;

fileUploadExercise: FileUploadExercise;

@Input()
set exercise(exercise: Exercise) {
this.fileUploadExercise = exercise as FileUploadExercise;
}
exercise = input.required<FileUploadExercise>();
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@if (modelingExercise.type === exerciseType.MODELING) {
{{ 'artemisApp.DiagramType.' + modelingExercise.diagramType | artemisTranslate }}
@if (exercise().type === exerciseType.MODELING) {
{{ 'artemisApp.DiagramType.' + exercise().diagramType | artemisTranslate }}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { Exercise, ExerciseType } from 'app/entities/exercise.model';
import { Component, input } from '@angular/core';
import { ExerciseType } from 'app/entities/exercise.model';
import { ModelingExercise } from 'app/entities/modeling-exercise.model';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';

Expand All @@ -11,10 +11,5 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
})
export class ModelingExerciseGroupCellComponent {
exerciseType = ExerciseType;
modelingExercise: ModelingExercise;

@Input()
set exercise(exercise: Exercise) {
this.modelingExercise = exercise as ModelingExercise;
}
exercise = input.required<ModelingExercise>();
}
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
@if (programmingExercise) {
@if (displayShortName) {
@if (exercise()) {
@if (displayShortName()) {
<div>
{{ programmingExercise.shortName || '' }}
{{ exercise().shortName || '' }}
</div>
}
@if (displayRepositoryUri) {
@if (displayRepositoryUri()) {
<div>
<div>
@if (programmingExercise.templateParticipation?.repositoryUri) {
@if (exercise().templateParticipation?.repositoryUri) {
<!--Checks if the programming exercise has a setup with VCS and CI, if this not the case
the links/clone-buttons are disabled--->
@if (!localVCEnabled) {
<span>
<a href="{{ programmingExercise.templateParticipation?.repositoryUri || '' }}" target="_blank">Template</a>
<a href="{{ exercise().templateParticipation?.repositoryUri || '' }}" target="_blank">Template</a>
</span>
} @else {
<a [routerLink]="" (click)="downloadRepository(RepositoryType.TEMPLATE)"> <fa-icon [icon]="faDownload" /> Template </a>
}
}
@if (programmingExercise.templateParticipation?.results?.length) {
@if (exercise().templateParticipation?.results?.length) {
<jhi-programming-exercise-instructor-status
[participationType]="participationType.TEMPLATE"
[participation]="programmingExercise.templateParticipation!"
[exercise]="programmingExercise"
[participation]="exercise().templateParticipation!"
[exercise]="exercise()"
/>
}
</div>
<div>
@if (programmingExercise.solutionParticipation?.repositoryUri) {
@if (exercise().solutionParticipation?.repositoryUri) {
@if (!localVCEnabled) {
<span>
<a href="{{ programmingExercise.solutionParticipation?.repositoryUri || '' }}" target="_blank">Solution</a>
<a href="{{ exercise().solutionParticipation?.repositoryUri || '' }}" target="_blank">Solution</a>
</span>
} @else {
<a [routerLink]="" (click)="downloadRepository(RepositoryType.SOLUTION)"> <fa-icon [icon]="faDownload" /> Solution </a>
}
}
@if (programmingExercise.solutionParticipation?.results?.length) {
@if (exercise().solutionParticipation?.results?.length) {
<jhi-programming-exercise-instructor-status
[participationType]="participationType.SOLUTION"
[participation]="programmingExercise.solutionParticipation!"
[exercise]="programmingExercise"
[participation]="exercise().solutionParticipation!"
[exercise]="exercise()"
/>
}
</div>
<div>
@if (programmingExercise.testRepositoryUri) {
@if (exercise().testRepositoryUri) {
@if (!localVCEnabled) {
<span>
<a href="{{ programmingExercise.testRepositoryUri }}" target="_blank">Test</a>
<a href="{{ exercise().testRepositoryUri }}" target="_blank">Test</a>
</span>
} @else {
<a [routerLink]="" (click)="downloadRepository(RepositoryType.TESTS)"> <fa-icon [icon]="faDownload" /> Test </a>
Expand All @@ -57,44 +57,44 @@
</div>
</div>
}
@if (displayTemplateUrls) {
@if (displayTemplateUrls()) {
<div>
@if (programmingExercise.templateParticipation?.buildPlanId) {
@if (exercise().templateParticipation?.buildPlanId) {
<span>
@if (!localVCEnabled) {
<a target="_blank" rel="noreferrer" href="{{ programmingExercise.templateParticipation!.buildPlanUrl }}">Template</a>
<a target="_blank" rel="noreferrer" href="{{ exercise().templateParticipation!.buildPlanUrl }}">Template</a>
} @else {
{{ programmingExercise.templateParticipation!.buildPlanId }}
{{ exercise().templateParticipation!.buildPlanId }}
}
</span>
}
<br />
@if (programmingExercise.solutionParticipation?.buildPlanId) {
@if (exercise().solutionParticipation?.buildPlanId) {
<span>
@if (!localVCEnabled) {
<a target="_blank" rel="noreferrer" href="{{ programmingExercise.solutionParticipation!.buildPlanUrl }}">Solution</a>
<a target="_blank" rel="noreferrer" href="{{ exercise().solutionParticipation!.buildPlanUrl }}">Solution</a>
} @else {
{{ programmingExercise.solutionParticipation!.buildPlanId }}
{{ exercise().solutionParticipation!.buildPlanId }}
}
</span>
}
<br />
</div>
}
@if (displayEditorModus) {
@if (displayEditorModus()) {
<div>
<div class="d-flex justify-content-between">
<span class="colon-suffix" [jhiTranslate]="'artemisApp.programmingExercise.offlineIde'"></span>
<span [jhiTranslate]="programmingExercise.allowOfflineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
<span [jhiTranslate]="exercise().allowOfflineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
<div class="d-flex justify-content-between">
<span class="colon-suffix" [jhiTranslate]="'artemisApp.programmingExercise.onlineEditor'"></span>
<span [jhiTranslate]="programmingExercise.allowOnlineEditor ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
<span [jhiTranslate]="exercise().allowOnlineEditor ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
@if (onlineIdeEnabled) {
<div class="d-flex justify-content-between">
<span class="colon-suffix" [jhiTranslate]="'artemisApp.programmingExercise.onlineIde'"></span>
<span [jhiTranslate]="programmingExercise.allowOnlineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
<span [jhiTranslate]="exercise().allowOnlineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Component, Input, OnInit, inject } from '@angular/core';
import { Component, OnInit, inject, input } from '@angular/core';
import { HttpResponse } from '@angular/common/http';
import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model';
import { ProgrammingExerciseParticipationType } from 'app/entities/programming/programming-exercise-participation.model';
import { Exercise } from 'app/entities/exercise.model';
import { ProfileService } from 'app/shared/layouts/profiles/profile.service';
import { createBuildPlanUrl } from 'app/exercises/programming/shared/utils/programming-exercise.utils';
import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service';
Expand Down Expand Up @@ -31,45 +30,32 @@ export class ProgrammingExerciseGroupCellComponent implements OnInit {

protected readonly RepositoryType = RepositoryType;

programmingExercise: ProgrammingExercise;

localVCEnabled = false;
onlineIdeEnabled = false;

@Input()
displayShortName = false;
@Input()
displayRepositoryUri = false;
@Input()
displayTemplateUrls = false;
@Input()
displayEditorModus = false;

@Input()
set exercise(exercise: Exercise) {
this.programmingExercise = exercise as ProgrammingExercise;
}
displayShortName = input(false);
displayRepositoryUri = input(false);
displayTemplateUrls = input(false);
displayEditorModus = input(false);
exercise = input.required<ProgrammingExercise>();

faDownload = faDownload;

ngOnInit(): void {
this.profileService.getProfileInfo().subscribe((profileInfo) => {
this.localVCEnabled = profileInfo.activeProfiles.includes(PROFILE_LOCALVC);
this.onlineIdeEnabled = profileInfo.activeProfiles.includes(PROFILE_THEIA);
if (this.programmingExercise.projectKey) {
if (this.programmingExercise.solutionParticipation?.buildPlanId) {
this.programmingExercise.solutionParticipation!.buildPlanUrl = createBuildPlanUrl(
profileInfo.buildPlanURLTemplate,
this.programmingExercise.projectKey,
this.programmingExercise.solutionParticipation.buildPlanId,
);

const projectKey = this.exercise()?.projectKey;
if (projectKey) {
const solutionParticipation = this.exercise()?.solutionParticipation;
if (solutionParticipation?.buildPlanId) {
solutionParticipation.buildPlanUrl = createBuildPlanUrl(profileInfo.buildPlanURLTemplate, projectKey, solutionParticipation.buildPlanId);
}
if (this.programmingExercise.templateParticipation?.buildPlanId) {
this.programmingExercise.templateParticipation!.buildPlanUrl = createBuildPlanUrl(
profileInfo.buildPlanURLTemplate,
this.programmingExercise.projectKey,
this.programmingExercise.templateParticipation.buildPlanId,
);

const templateParticipation = this.exercise()?.templateParticipation;
if (templateParticipation?.buildPlanId) {
templateParticipation.buildPlanUrl = createBuildPlanUrl(profileInfo.buildPlanURLTemplate, projectKey, templateParticipation.buildPlanId);
}
}
});
Expand All @@ -82,10 +68,11 @@ export class ProgrammingExerciseGroupCellComponent implements OnInit {
*
* @param repositoryType
*/
downloadRepository(repositoryType: RepositoryType) {
if (this.programmingExercise.id) {
downloadRepository(repositoryType: RepositoryType): void {
const programmingExerciseId = this.exercise()?.id;
if (programmingExerciseId) {
// Repository type cannot be 'AUXILIARY' as auxiliary repositories are currently not supported for the local VCS.
this.programmingExerciseService.exportInstructorRepository(this.programmingExercise.id, repositoryType, undefined).subscribe((response: HttpResponse<Blob>) => {
this.programmingExerciseService.exportInstructorRepository(programmingExerciseId, repositoryType, undefined).subscribe((response: HttpResponse<Blob>) => {
downloadZipFileFromResponse(response);
this.alertService.success('artemisApp.programmingExercise.export.successMessageRepos');
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@if (quizExercise.type === exerciseType.QUIZ) {
{{ quizExercise.quizQuestions?.length || 0 }}
@if (exercise().type === exerciseType.QUIZ) {
{{ exercise().quizQuestions?.length || 0 }}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { Exercise, ExerciseType } from 'app/entities/exercise.model';
import { Component, input } from '@angular/core';
import { ExerciseType } from 'app/entities/exercise.model';
import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model';

@Component({
Expand All @@ -9,10 +9,5 @@ import { QuizExercise } from 'app/entities/quiz/quiz-exercise.model';
})
export class QuizExerciseGroupCellComponent {
exerciseType = ExerciseType;
quizExercise: QuizExercise;

@Input()
set exercise(exercise: Exercise) {
this.quizExercise = exercise as QuizExercise;
}
exercise = input.required<QuizExercise>();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ArtemisTestModule } from '../../test.module';
import { TranslatePipeMock } from '../../helpers/mocks/service/mock-translate.service';
import { ExamExerciseRowButtonsComponent } from 'app/exercises/shared/exam-exercise-row-buttons/exam-exercise-row-buttons.component';
import { Course } from 'app/entities/course.model';
import { TextExercise } from 'app/entities/text/text-exercise.model';
Expand All @@ -18,9 +17,7 @@ import { of, throwError } from 'rxjs';
import { HttpErrorResponse } from '@angular/common/http';
import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service';
import { ProgrammingExercise } from 'app/entities/programming/programming-exercise.model';
import { MockDirective, MockProvider } from 'ng-mocks';
import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive';
import { MockRouterLinkDirective } from '../../helpers/mocks/directive/mock-router-link.directive';
import { MockProvider } from 'ng-mocks';

describe('ExamExerciseRowButtonsComponent', () => {
const course = { id: 3 } as Course;
Expand Down Expand Up @@ -55,7 +52,6 @@ describe('ExamExerciseRowButtonsComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ArtemisTestModule],
declarations: [ExamExerciseRowButtonsComponent, TranslatePipeMock, MockDirective(DeleteButtonDirective), MockRouterLinkDirective],
providers: [
MockProvider(TextExerciseService),
MockProvider(FileUploadExerciseService),
Expand Down
Loading

0 comments on commit 696d645

Please sign in to comment.