From d9a08703c6acf33be156c44a2bb53a186617b457 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 13 May 2024 01:07:35 +0200 Subject: [PATCH 001/117] Adding endpoint that returns the checkout directories for all programming languages --- .../web/rest/dto/CheckoutDirectoryInfo.java | 7 ++++ .../dto/RepositoryCheckoutDirectoryDTO.java | 12 +++++++ .../ProgrammingExerciseResource.java | 36 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java new file mode 100644 index 000000000000..15725d02f559 --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java @@ -0,0 +1,7 @@ +package de.tum.in.www1.artemis.web.rest.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record CheckoutDirectoryInfo(String exerciseCheckoutDirectory, String solutionCheckoutDirectory, String testCheckoutDirectory) { +} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java new file mode 100644 index 000000000000..046ec9f0eb6a --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java @@ -0,0 +1,12 @@ +package de.tum.in.www1.artemis.web.rest.dto; + +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record RepositoryCheckoutDirectoryDTO(Map checkoutDirectories) { + +} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 6a3ac819ecdb..ed9e5ed0b7ab 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -7,6 +7,7 @@ import java.net.URISyntaxException; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -81,7 +82,9 @@ import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseService; import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseTestCaseService; import de.tum.in.www1.artemis.web.rest.dto.BuildLogStatisticsDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoryInfo; import de.tum.in.www1.artemis.web.rest.dto.ProgrammingExerciseResetOptionsDTO; +import de.tum.in.www1.artemis.web.rest.dto.RepositoryCheckoutDirectoryDTO; import de.tum.in.www1.artemis.web.rest.dto.SearchResultPageDTO; import de.tum.in.www1.artemis.web.rest.dto.pageablesearch.SearchTermPageableSearchDTO; import de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException; @@ -875,4 +878,37 @@ public ResponseEntity getBuildLogStatistics(@PathVariable return ResponseEntity.ok(buildLogStatistics); } + /** + * GET programming-exercises/checkout-directories + * + * @return a DTO containing the checkout directories for the exercise, solution, and test repository for each programming language. + */ + @GetMapping("programming-exercises/repository-checkout-directories") + // @EnforceAtLeastEditor + @FeatureToggle(Feature.ProgrammingExercises) + public ResponseEntity getRepositoryCheckoutDirectories() { + log.debug("REST request to get checkout directories"); + + String ROOT_DIRECTORY = "/"; + + RepositoryCheckoutDirectoryDTO repositoryCheckoutDirectories = new RepositoryCheckoutDirectoryDTO(new HashMap<>()); + + for (ProgrammingLanguage programmingLanguage : ProgrammingLanguage.values()) { + + String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); + String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); + String solutionCheckoutDirectory = ROOT_DIRECTORY; + try { + solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + } + catch (IllegalArgumentException exception) { + // assume that the checkout directory is the root directory if the solution repository does not exist + } + + CheckoutDirectoryInfo checkoutDirectoryInfo = new CheckoutDirectoryInfo(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); + repositoryCheckoutDirectories.checkoutDirectories().put(programmingLanguage, checkoutDirectoryInfo); + } + + return ResponseEntity.ok(repositoryCheckoutDirectories); + } } From cc6ca336365e2b48f45ae66ea5a0544ca006fbb2 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 13 May 2024 01:22:37 +0200 Subject: [PATCH 002/117] Adjusting endpoint to only return the checkout directories for the displayed programming exercise --- .../web/rest/dto/CheckoutDirectoryInfo.java | 7 --- .../dto/RepositoriesCheckoutDirectoryDTO.java | 8 ++++ .../dto/RepositoryCheckoutDirectoryDTO.java | 12 ----- .../ProgrammingExerciseResource.java | 44 ++++++++++--------- 4 files changed, 32 insertions(+), 39 deletions(-) delete mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java delete mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java deleted file mode 100644 index 15725d02f559..000000000000 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoryInfo.java +++ /dev/null @@ -1,7 +0,0 @@ -package de.tum.in.www1.artemis.web.rest.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public record CheckoutDirectoryInfo(String exerciseCheckoutDirectory, String solutionCheckoutDirectory, String testCheckoutDirectory) { -} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java new file mode 100644 index 000000000000..5b4ca1e4ec5b --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java @@ -0,0 +1,8 @@ +package de.tum.in.www1.artemis.web.rest.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record RepositoriesCheckoutDirectoryDTO(String exerciseCheckoutDirectory, String solutionCheckoutDirectory, String testCheckoutDirectory) { + +} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java deleted file mode 100644 index 046ec9f0eb6a..000000000000 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoryCheckoutDirectoryDTO.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.tum.in.www1.artemis.web.rest.dto; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonInclude; - -import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage; - -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public record RepositoryCheckoutDirectoryDTO(Map checkoutDirectories) { - -} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index ed9e5ed0b7ab..55de4d724e6f 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -7,7 +7,6 @@ import java.net.URISyntaxException; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -82,9 +81,8 @@ import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseService; import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseTestCaseService; import de.tum.in.www1.artemis.web.rest.dto.BuildLogStatisticsDTO; -import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoryInfo; import de.tum.in.www1.artemis.web.rest.dto.ProgrammingExerciseResetOptionsDTO; -import de.tum.in.www1.artemis.web.rest.dto.RepositoryCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; import de.tum.in.www1.artemis.web.rest.dto.SearchResultPageDTO; import de.tum.in.www1.artemis.web.rest.dto.pageablesearch.SearchTermPageableSearchDTO; import de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException; @@ -886,29 +884,35 @@ public ResponseEntity getBuildLogStatistics(@PathVariable @GetMapping("programming-exercises/repository-checkout-directories") // @EnforceAtLeastEditor @FeatureToggle(Feature.ProgrammingExercises) - public ResponseEntity getRepositoryCheckoutDirectories() { + public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories"); String ROOT_DIRECTORY = "/"; - RepositoryCheckoutDirectoryDTO repositoryCheckoutDirectories = new RepositoryCheckoutDirectoryDTO(new HashMap<>()); - - for (ProgrammingLanguage programmingLanguage : ProgrammingLanguage.values()) { - - String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); - String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); - String solutionCheckoutDirectory = ROOT_DIRECTORY; - try { - solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - } - catch (IllegalArgumentException exception) { - // assume that the checkout directory is the root directory if the solution repository does not exist - } + String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); + String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); + String solutionCheckoutDirectory = ""; + try { + solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + } + catch (IllegalArgumentException exception) { + // assume that the checkout directory is the root directory if the solution repository does not exist + } - CheckoutDirectoryInfo checkoutDirectoryInfo = new CheckoutDirectoryInfo(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); - repositoryCheckoutDirectories.checkoutDirectories().put(programmingLanguage, checkoutDirectoryInfo); + // TODO verify assumption + if (exerciseCheckoutDirectory.isEmpty()) { + exerciseCheckoutDirectory = ROOT_DIRECTORY; + } + if (solutionCheckoutDirectory.isEmpty()) { + solutionCheckoutDirectory = ROOT_DIRECTORY; } + if (testCheckoutDirectory.isEmpty()) { + testCheckoutDirectory = ROOT_DIRECTORY; + } + + RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, + testCheckoutDirectory); - return ResponseEntity.ok(repositoryCheckoutDirectories); + return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } } From 807a197cf970435da60e6b2f2713b1d3ab6d37be Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 13 May 2024 01:34:35 +0200 Subject: [PATCH 003/117] Reuse translation --- .../programming-exercise-information.component.html | 2 +- src/main/webapp/i18n/de/programmingExercise.json | 2 +- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index acdf192cba22..182cbb5299db 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -77,7 +77,7 @@ /> - + Date: Mon, 13 May 2024 01:36:40 +0200 Subject: [PATCH 004/117] Adding hardcoded preview --- ...ans-and-repositories-preview.component.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 6cbba474b951..970ac1cbe8f5 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -62,6 +62,24 @@ + } @else { +
+
+ +
+
+
    +
  • + exercise +
  • +
  • + solution +
  • +
  • + test +
  • +
+
} } From f91639c4075105e293cb3cddf5ec76f4097cb80a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 13 May 2024 02:02:16 +0200 Subject: [PATCH 005/117] Call server endpoint from service --- .../repositories-checkout-directories-dto.ts | 8 ++++ .../services/programming-exercise.service.ts | 11 ++++- ...ns-and-repositories-preview.component.html | 6 +-- ...lans-and-repositories-preview.component.ts | 40 ++++++++++++++++++- 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts diff --git a/src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts b/src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts new file mode 100644 index 000000000000..3ceb26cf94af --- /dev/null +++ b/src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts @@ -0,0 +1,8 @@ +export class RepositoriesCheckoutDirectoriesDTO { + exerciseCheckoutDirectory?: string; + solutionCheckoutDirectory?: string; + testCheckoutDirectory?: string; +} + +// TODO is the file placed correctly here? +// TODO is this how we define DTOs? read docs! diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index 1cf987c5f950..07a5bed0e1d5 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -7,7 +7,7 @@ import { omit as _omit } from 'lodash-es'; import { createRequestOption } from 'app/shared/util/request.util'; import { ExerciseService } from 'app/exercises/shared/exercise/exercise.service'; -import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; +import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { TextPlagiarismResult } from 'app/exercises/shared/plagiarism/types/text/TextPlagiarismResult'; @@ -25,6 +25,7 @@ import { SortService } from 'app/shared/service/sort.service'; import { Result } from 'app/entities/result.model'; import { Participation } from 'app/entities/participation/participation.model'; import { PlagiarismResultDTO } from 'app/exercises/shared/plagiarism/types/PlagiarismResultDTO'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; export type EntityResponseType = HttpResponse; export type EntityArrayResponseType = HttpResponse; @@ -652,4 +653,12 @@ export class ProgrammingExerciseService { .post(url, formData, { observe: 'response' }) .pipe(map((res: EntityResponseType) => this.processProgrammingExerciseEntityResponse(res))); } + + getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { + return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { + params: { + programmingLanguage, + }, + }); + } } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 970ac1cbe8f5..0247877962fa 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -70,13 +70,13 @@
  • - exercise + {{ exerciseCheckoutDirectory }}
  • - solution + {{ solutionCheckoutDirectory }}
  • - test + {{ testCheckoutDirectory }}
diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 8eb2da99f4e5..ce2b26dce25c 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -1,6 +1,7 @@ -import { Component, Input } from '@angular/core'; +import { Component, Input, SimpleChanges } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; +import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -11,10 +12,47 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { @Input() programmingExercise: ProgrammingExercise | null; @Input() isLocal: boolean; + constructor(private programmingExerciseService: ProgrammingExerciseService) {} + getCourseShortName(): string | undefined { if (!this.programmingExercise) { return undefined; } return getCourseFromExercise(this.programmingExercise)?.shortName; } + + solutionCheckoutDirectory: string | undefined; + exerciseCheckoutDirectory: string | undefined; + testCheckoutDirectory: string | undefined; + + ngOnInit() { + if (!this.programmingExercise?.programmingLanguage) { + return; + } + + this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise?.programmingLanguage).subscribe((checkoutDirectories) => { + if (this.programmingExercise) { + this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; + this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; + this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; + } + }); + } + + // TODO fix change detection + ngOnChanges(changes: SimpleChanges) { + if ( + changes.programmingExercise && + changes.programmingExercise.currentValue.programmingLanguage !== changes.programmingExercise.previousValue.programmingLanguage && + this.programmingExercise?.programmingLanguage + ) { + this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise?.programmingLanguage).subscribe((checkoutDirectories) => { + if (this.programmingExercise) { + this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; + this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; + this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; + } + }); + } + } } From 825c8ea88d0a76423c7b7b46742ea404b6644d4d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 20:52:13 +0200 Subject: [PATCH 006/117] Fixing change detection and exchanging translations --- ...lans-and-repositories-preview.component.ts | 28 +++++++++---------- ...amming-exercise-information.component.html | 12 +++++--- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index ce2b26dce25c..39c333a84291 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -2,6 +2,7 @@ import { Component, Input, SimpleChanges } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; +import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -11,6 +12,7 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { @Input() programmingExercise: ProgrammingExercise | null; @Input() isLocal: boolean; + @Input() programmingExerciseCreationConfig: ProgrammingExerciseCreationConfig; constructor(private programmingExerciseService: ProgrammingExerciseService) {} @@ -26,33 +28,29 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { testCheckoutDirectory: string | undefined; ngOnInit() { - if (!this.programmingExercise?.programmingLanguage) { - return; - } - - this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise?.programmingLanguage).subscribe((checkoutDirectories) => { - if (this.programmingExercise) { + this.programmingExerciseService + .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) + .subscribe((checkoutDirectories) => { this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; - } - }); + }); } // TODO fix change detection ngOnChanges(changes: SimpleChanges) { if ( - changes.programmingExercise && - changes.programmingExercise.currentValue.programmingLanguage !== changes.programmingExercise.previousValue.programmingLanguage && - this.programmingExercise?.programmingLanguage + changes.programmingExerciseCreationConfig && + changes.programmingExerciseCreationConfig.currentValue.selectedProgrammingLanguage !== + changes.programmingExerciseCreationConfig.previousValue.selectedProgrammingLanguage ) { - this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise?.programmingLanguage).subscribe((checkoutDirectories) => { - if (this.programmingExercise) { + this.programmingExerciseService + .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) + .subscribe((checkoutDirectories) => { this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; - } - }); + }); } } } diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 182cbb5299db..727f6fcf6902 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -51,7 +51,11 @@ - + @if (!programmingExerciseCreationConfig.isImportFromExistingExercise && programmingExerciseCreationConfig.auxiliaryRepositoriesSupported) {
@if (programmingExercise.auxiliaryRepositories && programmingExercise.auxiliaryRepositories.length > 0) { @@ -110,16 +114,16 @@ @if (programmingExerciseCreationConfig.auxiliaryRepositoryDuplicateNames || programmingExerciseCreationConfig.auxiliaryRepositoryDuplicateDirectories) { @if (programmingExerciseCreationConfig.auxiliaryRepositoryDuplicateNames) { - {{ 'artemisApp.programmingExercise.auxiliaryRepository.duplicateRepositoryNames' | artemisTranslate }} + } @if (programmingExerciseCreationConfig.auxiliaryRepositoryDuplicateDirectories) { - {{ 'artemisApp.programmingExercise.auxiliaryRepository.duplicateDirectoryNames' | artemisTranslate }} + } } @if (programmingExerciseCreationConfig && !isLocal) { - {{ 'artemisApp.programmingExercise.auxiliaryRepository.warning' | artemisTranslate }} + } Date: Tue, 14 May 2024 21:02:46 +0200 Subject: [PATCH 007/117] Reducing code duplication and unsubscribe on destroy --- ...lans-and-repositories-preview.component.ts | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 39c333a84291..72c861027682 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -3,6 +3,7 @@ import { getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; +import { Subscription } from 'rxjs'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -27,7 +28,9 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { exerciseCheckoutDirectory: string | undefined; testCheckoutDirectory: string | undefined; - ngOnInit() { + programmingExerciseServiceSubscription: Subscription; + + private updateCheckoutDirectories() { this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) .subscribe((checkoutDirectories) => { @@ -37,20 +40,23 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { }); } - // TODO fix change detection + ngOnInit() { + this.updateCheckoutDirectories(); + } + ngOnChanges(changes: SimpleChanges) { if ( changes.programmingExerciseCreationConfig && changes.programmingExerciseCreationConfig.currentValue.selectedProgrammingLanguage !== changes.programmingExerciseCreationConfig.previousValue.selectedProgrammingLanguage ) { - this.programmingExerciseService - .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) - .subscribe((checkoutDirectories) => { - this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; - this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; - this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; - }); + this.updateCheckoutDirectories(); + } + } + + ngOnDestroy() { + if (this.programmingExerciseServiceSubscription) { + this.programmingExerciseServiceSubscription.unsubscribe(); } } } From 11363615014dbc3698a395f50bba3b64c7707877 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 21:05:53 +0200 Subject: [PATCH 008/117] Only display the checkout directories once they have been loaded --- ...mming-exercise-plans-and-repositories-preview.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 0247877962fa..8afdb36e193c 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -62,7 +62,7 @@
- } @else { + } @else if (exerciseCheckoutDirectory || solutionCheckoutDirectory || testCheckoutDirectory) {
From 000f3e5ef5f168703a4f6938eac44ea9f28571fa Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 21:21:26 +0200 Subject: [PATCH 009/117] Displaying checkout directories of auxiliary repositories --- ...xercise-plans-and-repositories-preview.component.html | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 8afdb36e193c..c401cdf6f71a 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -78,6 +78,15 @@
  • {{ testCheckoutDirectory }}
  • + @if (programmingExercise.auxiliaryRepositories) { + @for (auxiliaryRepository of programmingExercise.auxiliaryRepositories; track auxiliaryRepository) { +
    +
  • + {{ auxiliaryRepository.checkoutDirectory }} +
  • +
    + } + }
    } From 19e8b39697eab331d4bfdd42389001d21283ff6d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 21:22:11 +0200 Subject: [PATCH 010/117] Fixing console errors --- ...g-exercise-plans-and-repositories-preview.component.ts | 5 ++++- .../update/programming-exercise-update.component.ts | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 72c861027682..69b1e57b73d2 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -46,9 +46,12 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { ngOnChanges(changes: SimpleChanges) { if ( + this.programmingExerciseCreationConfig && + this.programmingExerciseCreationConfig.selectedProgrammingLanguage && changes.programmingExerciseCreationConfig && + changes.programmingExerciseCreationConfig.currentValue && changes.programmingExerciseCreationConfig.currentValue.selectedProgrammingLanguage !== - changes.programmingExerciseCreationConfig.previousValue.selectedProgrammingLanguage + changes.programmingExerciseCreationConfig.previousValue?.selectedProgrammingLanguage ) { this.updateCheckoutDirectories(); } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts index eb56735c16dc..ca764bdb87d3 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts @@ -211,12 +211,12 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest let legalNameAndDirs = false; // Check that there are no duplicate names. const names = new Set(); - const auxReposWithName = this.programmingExercise.auxiliaryRepositories!.filter((auxiliaryRepository) => auxiliaryRepository.name); - auxReposWithName.forEach((auxiliaryRepository) => { + const auxReposWithName = this.programmingExercise.auxiliaryRepositories?.filter((auxiliaryRepository) => auxiliaryRepository.name); + auxReposWithName?.forEach((auxiliaryRepository) => { names.add(auxiliaryRepository.name); legalNameAndDirs ||= !this.invalidRepositoryNamePattern.test(auxiliaryRepository.name!); }); - this.auxiliaryRepositoryDuplicateNames = names.size !== auxReposWithName.length; + this.auxiliaryRepositoryDuplicateNames = names.size !== auxReposWithName?.length; // Check that there are no duplicate checkout directories const directories = new Set(); @@ -228,7 +228,7 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest this.auxiliaryRepositoryDuplicateDirectories = directories.size !== auxReposWithDirectory.length; // Check that there are no empty/incorrect repository names and directories - this.auxiliaryRepositoryNamedCorrectly = this.programmingExercise.auxiliaryRepositories!.length === auxReposWithName.length && !legalNameAndDirs; + this.auxiliaryRepositoryNamedCorrectly = this.programmingExercise.auxiliaryRepositories!.length === auxReposWithName?.length && !legalNameAndDirs; // Combining auxiliary variables to one to keep the template readable this.auxiliaryRepositoriesValid = this.auxiliaryRepositoryNamedCorrectly && !this.auxiliaryRepositoryDuplicateNames && !this.auxiliaryRepositoryDuplicateDirectories; From 1a7ae44b92d98707879999fcc4ee3931fa803ab5 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 21:42:38 +0200 Subject: [PATCH 011/117] Fixing console error due to regex and define re-used regex as constant --- .../exam-exercise-import/exam-exercise-import.component.ts | 4 ++-- .../manage/update/programming-exercise-update.component.ts | 7 +++---- src/main/webapp/app/shared/constants/input.constants.ts | 2 ++ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts index 0f212060dccf..5331a1fc6954 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts @@ -3,7 +3,7 @@ import { Exam } from 'app/entities/exam.model'; import { faCheckDouble, faFont } from '@fortawesome/free-solid-svg-icons'; import { Exercise, ExerciseType, getIcon } from 'app/entities/exercise.model'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; -import { SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; +import { SHORT_NAME_PATTERN, TITLE_NAME_PATTERN } from 'app/shared/constants/input.constants'; @Component({ selector: 'jhi-exam-exercise-import', @@ -34,7 +34,7 @@ export class ExamExerciseImportComponent implements OnInit { // Patterns // length of < 3 is also accepted in order to provide more accurate validation error messages readonly shortNamePattern = RegExp('(^(?![\\s\\S]))|^[a-zA-Z][a-zA-Z0-9]*$|' + SHORT_NAME_PATTERN); // must start with a letter and cannot contain special characters - readonly titleNamePattern = RegExp('^[a-zA-Z0-9-_ ]+'); // must only contain alphanumeric characters, or whitespaces, or '_' or '-' + readonly titleNamePattern = RegExp(TITLE_NAME_PATTERN); // Icons faCheckDouble = faCheckDouble; diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts index ca764bdb87d3..26b7cbfdc78b 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts @@ -18,7 +18,7 @@ import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-group.service'; import { ProgrammingLanguageFeatureService } from 'app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; -import { SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; +import { SHORT_NAME_PATTERN, TITLE_NAME_PATTERN } from 'app/shared/constants/input.constants'; import { ExerciseCategory } from 'app/entities/exercise-category.model'; import { cloneDeep } from 'lodash-es'; import { ExerciseUpdateWarningService } from 'app/exercises/shared/exercise-update-warning/exercise-update-warning.service'; @@ -119,7 +119,6 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest // length of < 3 is also accepted in order to provide more accurate validation error messages readonly shortNamePattern = RegExp('(^(?![\\s\\S]))|^[a-zA-Z][a-zA-Z0-9]*$|' + SHORT_NAME_PATTERN); // must start with a letter and cannot contain special characters - titleNamePattern = '^[a-zA-Z0-9-_ ]+'; // must only contain alphanumeric characters, or whitespaces, or '_' or '-' exerciseCategories: ExerciseCategory[]; existingCategories: ExerciseCategory[]; @@ -843,7 +842,7 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest translateKey: 'artemisApp.exercise.form.title.undefined', translateValues: {}, }); - } else if (this.programmingExercise.title.match(this.titleNamePattern) === null || this.programmingExercise.title?.match(this.titleNamePattern)?.length === 0) { + } else if (this.programmingExercise.title.match(TITLE_NAME_PATTERN) === null || this.programmingExercise.title?.match(TITLE_NAME_PATTERN)?.length === 0) { validationErrorReasons.push({ translateKey: 'artemisApp.exercise.form.title.pattern', translateValues: {}, @@ -1063,7 +1062,7 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest customBuildPlansSupported: this.customBuildPlansSupported, invalidDirectoryNamePattern: this.invalidDirectoryNamePattern, invalidRepositoryNamePattern: this.invalidRepositoryNamePattern, - titleNamePattern: this.titleNamePattern, + titleNamePattern: TITLE_NAME_PATTERN, shortNamePattern: this.shortNamePattern, updateRepositoryName: this.updateRepositoryName, updateCheckoutDirectory: this.updateCheckoutDirectory, diff --git a/src/main/webapp/app/shared/constants/input.constants.ts b/src/main/webapp/app/shared/constants/input.constants.ts index 69817d0051be..683069e6a9cc 100644 --- a/src/main/webapp/app/shared/constants/input.constants.ts +++ b/src/main/webapp/app/shared/constants/input.constants.ts @@ -13,6 +13,8 @@ export const MAX_SUBMISSION_TEXT_LENGTH = 30 * 1000; export const MAX_QUIZ_SHORT_ANSWER_TEXT_LENGTH = 255; // Must be consistent with database column definition /** Short names must start with a letter and cannot contain special characters **/ export const SHORT_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{2,}$/; +/** Programming exercise titles must only contain alphanumeric characters, or whitespaces, or '_' or '-' **/ +export const TITLE_NAME_PATTERN = '^[a-zA-Z0-9_\\-\\s]*'; /** Prefixes must follow the login pattern **/ export const LOGIN_PATTERN = /^[_'.@A-Za-z0-9-]*$/; export const MAX_QUIZ_QUESTION_POINTS = 9999; From 71dc62dc486334e1798b645a6066ccaf18e3b3ef Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 21:45:28 +0200 Subject: [PATCH 012/117] Adhere to naming conventions --- .../exam-exercise-import.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts index 5331a1fc6954..ce25ddcc47f7 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts @@ -33,8 +33,8 @@ export class ExamExerciseImportComponent implements OnInit { // Patterns // length of < 3 is also accepted in order to provide more accurate validation error messages - readonly shortNamePattern = RegExp('(^(?![\\s\\S]))|^[a-zA-Z][a-zA-Z0-9]*$|' + SHORT_NAME_PATTERN); // must start with a letter and cannot contain special characters - readonly titleNamePattern = RegExp(TITLE_NAME_PATTERN); + readonly SHORT_NAME_REGEX = RegExp('(^(?![\\s\\S]))|^[a-zA-Z][a-zA-Z0-9]*$|' + SHORT_NAME_PATTERN); // must start with a letter and cannot contain special characters + readonly TITLE_NAME_REGEX = RegExp(TITLE_NAME_PATTERN); // Icons faCheckDouble = faCheckDouble; @@ -217,7 +217,7 @@ export class ExamExerciseImportComponent implements OnInit { validateTitleOfProgrammingExercise(exercise: Exercise): boolean { return ( !!exercise.title?.length && - this.titleNamePattern.test(exercise.title!) && + this.TITLE_NAME_REGEX.test(exercise.title!) && !this.exercisesWithDuplicatedTitles.has(exercise.id!) && (exercise.title !== this.getBlocklistTitleOfProgrammingExercise(exercise.id!) || this.getBlocklistShortNameOfProgrammingExercise(exercise.id!) === '') ); @@ -231,7 +231,7 @@ export class ExamExerciseImportComponent implements OnInit { return ( // eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain exercise.shortName?.length! > 2 && - this.shortNamePattern.test(exercise.shortName!) && + this.SHORT_NAME_REGEX.test(exercise.shortName!) && !this.exercisesWithDuplicatedShortNames.has(exercise.id!) && exercise.shortName !== this.getBlocklistShortNameOfProgrammingExercise(exercise.id!) ); From 92acf3434b4ca0f9c0947a73e16b8515099c3315 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 22:04:15 +0200 Subject: [PATCH 013/117] Fixing console error --- .../manage/update/programming-exercise-update.component.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts index 26b7cbfdc78b..6707f0eb6333 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts @@ -207,6 +207,10 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest * used in the template to display warnings. */ refreshAuxiliaryRepositoryChecks() { + if (!this.programmingExercise?.auxiliaryRepositories) { + return; + } + let legalNameAndDirs = false; // Check that there are no duplicate names. const names = new Set(); From 4b9ca36808c248b76c8090c4f93b3675bcd167e1 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 22:09:54 +0200 Subject: [PATCH 014/117] Adding leading slash if not present --- ...ns-and-repositories-preview.component.html | 12 ++++----- ...lans-and-repositories-preview.component.ts | 27 ++++++++++++++++--- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index c401cdf6f71a..89be9cbf802d 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -78,13 +78,11 @@
  • {{ testCheckoutDirectory }}
  • - @if (programmingExercise.auxiliaryRepositories) { - @for (auxiliaryRepository of programmingExercise.auxiliaryRepositories; track auxiliaryRepository) { -
    -
  • - {{ auxiliaryRepository.checkoutDirectory }} -
  • -
    + @if (auxiliaryRepositoryCheckoutDirectories?.length) { + @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { +
  • + {{ auxiliaryRepositoryCheckoutDirectory }} +
  • } } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 69b1e57b73d2..cc0f7aa9f0aa 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -5,6 +5,8 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; +const ROOT_DIRECTORY: string = '/'; + @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', templateUrl: './programming-exercise-plans-and-repositories-preview.component.html', @@ -27,21 +29,36 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { solutionCheckoutDirectory: string | undefined; exerciseCheckoutDirectory: string | undefined; testCheckoutDirectory: string | undefined; + auxiliaryRepositoryCheckoutDirectories: string[] = []; programmingExerciseServiceSubscription: Subscription; + private addLeadingSlashIfNotPresent(directory: string | undefined): string { + if (!directory) { + return ROOT_DIRECTORY; + } + + return directory.startsWith(ROOT_DIRECTORY) ? directory : ROOT_DIRECTORY + directory; + } + private updateCheckoutDirectories() { this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) .subscribe((checkoutDirectories) => { - this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; - this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; - this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; + this.solutionCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.solutionCheckoutDirectory); + this.exerciseCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.exerciseCheckoutDirectory); + this.testCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.testCheckoutDirectory); }); } + private updateAuxiliaryRepositoryCheckoutDirectories() { + this.auxiliaryRepositoryCheckoutDirectories = + this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; + } + ngOnInit() { this.updateCheckoutDirectories(); + this.updateAuxiliaryRepositoryCheckoutDirectories(); } ngOnChanges(changes: SimpleChanges) { @@ -55,6 +72,10 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { ) { this.updateCheckoutDirectories(); } + + if (this.programmingExercise?.auxiliaryRepositories) { + this.updateAuxiliaryRepositoryCheckoutDirectories(); + } } ngOnDestroy() { From a5510fde48eea9692b9e27107438278f9b5b845f Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 14 May 2024 22:11:44 +0200 Subject: [PATCH 015/117] Simplify html --- ...rcise-plans-and-repositories-preview.component.html | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 89be9cbf802d..cc6ba86b571a 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -78,12 +78,10 @@
  • {{ testCheckoutDirectory }}
  • - @if (auxiliaryRepositoryCheckoutDirectories?.length) { - @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { -
  • - {{ auxiliaryRepositoryCheckoutDirectory }} -
  • - } + @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { +
  • + {{ auxiliaryRepositoryCheckoutDirectory }} +
  • }
    From 8bc847369b8cf0c05cef40b8767498e825ac4849 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 16:22:44 +0200 Subject: [PATCH 016/117] Defining checkout directories for solution repository within enum --- .../service/connectors/ci/ContinuousIntegrationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 12260b2e7448..159bbf7b99a6 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -237,8 +237,8 @@ public String forProgrammingLanguage(ProgrammingLanguage language) { @Override public String forProgrammingLanguage(ProgrammingLanguage language) { return switch (language) { + case JAVA, PYTHON, C, KOTLIN, VHDL, ASSEMBLER, SWIFT, EMPTY -> "assignment"; case HASKELL, OCAML -> "solution"; - default -> throw new IllegalArgumentException("Repository checkout path for solution repo has not yet been defined for " + language); }; } } From 08cf7a85e33487b5e191311684ddd1a247a66d47 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 21:10:09 +0200 Subject: [PATCH 017/117] Simplify endpoint for retrieval of checkout repository --- .../ProgrammingExerciseResource.java | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 55de4d724e6f..00e6b8bcb284 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -104,6 +104,8 @@ public class ProgrammingExerciseResource { private static final String ENTITY_NAME = "programmingExercise"; + private static final String ROOT_DIRECTORY = "/"; + private final ChannelRepository channelRepository; @Value("${jhipster.clientApp.name}") @@ -879,40 +881,33 @@ public ResponseEntity getBuildLogStatistics(@PathVariable /** * GET programming-exercises/checkout-directories * - * @return a DTO containing the checkout directories for the exercise, solution, and test repository for each programming language. + * @return a DTO containing the checkout directories for the exercise, solution, and test repository for the requested programming language. */ @GetMapping("programming-exercises/repository-checkout-directories") - // @EnforceAtLeastEditor + @EnforceAtLeastEditor @FeatureToggle(Feature.ProgrammingExercises) public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { - log.debug("REST request to get checkout directories"); - - String ROOT_DIRECTORY = "/"; + log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); + String solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); - String solutionCheckoutDirectory = ""; - try { - solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - } - catch (IllegalArgumentException exception) { - // assume that the checkout directory is the root directory if the solution repository does not exist - } - // TODO verify assumption - if (exerciseCheckoutDirectory.isEmpty()) { - exerciseCheckoutDirectory = ROOT_DIRECTORY; - } - if (solutionCheckoutDirectory.isEmpty()) { - solutionCheckoutDirectory = ROOT_DIRECTORY; - } - if (testCheckoutDirectory.isEmpty()) { - testCheckoutDirectory = ROOT_DIRECTORY; - } + exerciseCheckoutDirectory = setEmptyPathToRootDirectory(exerciseCheckoutDirectory); + solutionCheckoutDirectory = setEmptyPathToRootDirectory(solutionCheckoutDirectory); + testCheckoutDirectory = setEmptyPathToRootDirectory(testCheckoutDirectory); RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } + + private String setEmptyPathToRootDirectory(String checkoutDirectoryPath) { + if (checkoutDirectoryPath.isEmpty()) { + return ROOT_DIRECTORY; + } + + return checkoutDirectoryPath; + } } From 268246d0e665656ced69135a5d43435e2cf4ab18 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 21:32:31 +0200 Subject: [PATCH 018/117] Moving code for checkout directory retrieval to interface --- .../ci/ContinuousIntegrationService.java | 3 +++ .../connectors/gitlabci/GitLabCIService.java | 8 ++++++ .../connectors/jenkins/JenkinsService.java | 8 ++++++ .../connectors/localci/LocalCIService.java | 26 +++++++++++++++++++ .../ProgrammingExerciseResource.java | 22 +--------------- .../ContinuousIntegrationTestService.java | 6 +++-- 6 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 159bbf7b99a6..a92838dc74a7 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -17,6 +17,7 @@ import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseParticipation; import de.tum.in.www1.artemis.exception.ContinuousIntegrationException; import de.tum.in.www1.artemis.service.connectors.ConnectorHealth; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; /** * Abstract service for managing entities related to continuous integration. @@ -255,4 +256,6 @@ interface CustomizableCheckoutPath { */ String forProgrammingLanguage(ProgrammingLanguage language); } + + RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage); } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index c5d53ff178b6..b127ba60f4ee 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -28,6 +28,7 @@ import de.tum.in.www1.artemis.domain.ProgrammingExercise; import de.tum.in.www1.artemis.domain.ProgrammingSubmission; import de.tum.in.www1.artemis.domain.VcsRepositoryUri; +import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage; import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseParticipation; import de.tum.in.www1.artemis.exception.ContinuousIntegrationException; import de.tum.in.www1.artemis.exception.GitLabCIException; @@ -37,6 +38,7 @@ import de.tum.in.www1.artemis.service.connectors.ci.AbstractContinuousIntegrationService; import de.tum.in.www1.artemis.service.connectors.ci.CIPermission; import de.tum.in.www1.artemis.service.connectors.ci.notification.dto.TestResultsDTO; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; @Profile("gitlabci") @Service @@ -322,4 +324,10 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { log.error("Unsupported action: GitLabCIService.getWebHookUrl()"); return Optional.empty(); } + + @Override + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + // Not needed since the checkout directories are defined in the build plans stored in GitLab + return null; + } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index ef063ee97388..dd23e06369fd 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -22,6 +22,7 @@ import de.tum.in.www1.artemis.domain.ProgrammingExercise; import de.tum.in.www1.artemis.domain.VcsRepositoryUri; import de.tum.in.www1.artemis.domain.enumeration.BuildPlanType; +import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage; import de.tum.in.www1.artemis.domain.enumeration.RepositoryType; import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseParticipation; import de.tum.in.www1.artemis.exception.ContinuousIntegrationException; @@ -36,6 +37,7 @@ import de.tum.in.www1.artemis.service.connectors.ci.notification.dto.TestResultsDTO; import de.tum.in.www1.artemis.service.connectors.jenkins.build_plan.JenkinsBuildPlanService; import de.tum.in.www1.artemis.service.connectors.jenkins.jobs.JenkinsJobService; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; @Profile("jenkins") @Service @@ -253,4 +255,10 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th throw new JenkinsException("Error creating folder for exercise " + programmingExercise, e); } } + + @Override + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + // Not needed since the checkout directories are defined in the build plans in Jenkins + return null; + } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index 957f36e056f5..c4d80a38ed61 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -15,6 +15,7 @@ import de.tum.in.www1.artemis.domain.ProgrammingExercise; import de.tum.in.www1.artemis.domain.VcsRepositoryUri; +import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage; import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseParticipation; import de.tum.in.www1.artemis.exception.LocalCIException; import de.tum.in.www1.artemis.repository.ProgrammingExerciseRepository; @@ -24,6 +25,8 @@ import de.tum.in.www1.artemis.service.connectors.aeolus.Windfile; import de.tum.in.www1.artemis.service.connectors.ci.AbstractContinuousIntegrationService; import de.tum.in.www1.artemis.service.connectors.ci.CIPermission; +import de.tum.in.www1.artemis.service.connectors.ci.ContinuousIntegrationService; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; /** * Implementation of ContinuousIntegrationService for local CI. Contains methods for communication with the local CI system. @@ -42,6 +45,8 @@ public class LocalCIService extends AbstractContinuousIntegrationService { private final ProgrammingExerciseRepository programmingExerciseRepository; + private static final String ROOT_DIRECTORY = "/"; + public LocalCIService(BuildScriptProviderService buildScriptProviderService, AeolusTemplateService aeolusTemplateService, ProgrammingExerciseRepository programmingExerciseRepository) { this.buildScriptProviderService = buildScriptProviderService; @@ -206,4 +211,25 @@ public boolean checkIfBuildPlanExists(String projectKey, String buildPlanId) { private String getCleanPlanName(String name) { return name.toUpperCase().replaceAll("[^A-Z0-9]", ""); } + + @Override + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); + String solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); + + exerciseCheckoutDirectory = setEmptyPathToRootDirectory(exerciseCheckoutDirectory); + solutionCheckoutDirectory = setEmptyPathToRootDirectory(solutionCheckoutDirectory); + testCheckoutDirectory = setEmptyPathToRootDirectory(testCheckoutDirectory); + + return new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); + } + + private String setEmptyPathToRootDirectory(String checkoutDirectoryPath) { + if (checkoutDirectoryPath.isEmpty()) { + return ROOT_DIRECTORY; + } + + return checkoutDirectoryPath; + } } diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 00e6b8bcb284..a234e72f5964 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -104,8 +104,6 @@ public class ProgrammingExerciseResource { private static final String ENTITY_NAME = "programmingExercise"; - private static final String ROOT_DIRECTORY = "/"; - private final ChannelRepository channelRepository; @Value("${jhipster.clientApp.name}") @@ -889,25 +887,7 @@ public ResponseEntity getBuildLogStatistics(@PathVariable public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); - String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); - String solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); - - exerciseCheckoutDirectory = setEmptyPathToRootDirectory(exerciseCheckoutDirectory); - solutionCheckoutDirectory = setEmptyPathToRootDirectory(solutionCheckoutDirectory); - testCheckoutDirectory = setEmptyPathToRootDirectory(testCheckoutDirectory); - - RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, - testCheckoutDirectory); - + RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow().getCheckoutDirectories(programmingLanguage); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } - - private String setEmptyPathToRootDirectory(String checkoutDirectoryPath) { - if (checkoutDirectoryPath.isEmpty()) { - return ROOT_DIRECTORY; - } - - return checkoutDirectoryPath; - } } diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java index 3a5e1c3f523a..392da69c7995 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java @@ -4,6 +4,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.reset; +import java.io.File; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; @@ -16,6 +17,7 @@ import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; +import de.tum.in.www1.artemis.domain.Course; import de.tum.in.www1.artemis.domain.ProgrammingExercise; import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseStudentParticipation; import de.tum.in.www1.artemis.participation.ParticipationUtilService; @@ -64,7 +66,7 @@ public void setup(String testPrefix, MockDelegate mockDelegate, ContinuousIntegr this.continuousIntegrationService = continuousIntegrationService; userUtilService.addUsers(testPrefix, 2, 0, 0, 1); - var course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); + Course course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); programmingExercise = (ProgrammingExercise) course.getExercises().iterator().next(); // init local repo @@ -74,7 +76,7 @@ public void setup(String testPrefix, MockDelegate mockDelegate, ContinuousIntegr localRepo.configureRepos("testLocalRepo", "testOriginRepo"); // add file to the repository folder Path filePath = Path.of(localRepo.localRepoFile + "/" + currentLocalFileName); - var file = Files.createFile(filePath).toFile(); + File file = Files.createFile(filePath).toFile(); // write content to the created file FileUtils.write(file, currentLocalFileContent, Charset.defaultCharset()); // add folder to the repository folder From c09a878da272334912c88083c8c5130a55de231d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 21:33:59 +0200 Subject: [PATCH 019/117] Adding javadoc --- .../service/connectors/ci/ContinuousIntegrationService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index a92838dc74a7..03b666b7d4c3 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -257,5 +257,11 @@ interface CustomizableCheckoutPath { String forProgrammingLanguage(ProgrammingLanguage language); } + /** + * Get the checkout directories for the default repositories (exercise, solution, test) for a given programming language. + * + * @param programmingLanguage for which the checkout directories should be retrieved + * @return the paths of the checkout directories for the default repositories + */ RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage); } From 8db9017ab6bd3a86a6a35727a6be35f1615dfba2 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 21:51:37 +0200 Subject: [PATCH 020/117] Add tests for checkout directory retrieval --- .../connectors/localci/LocalCIService.java | 14 ++++------- .../artemis/localvcci/LocalCIServiceTest.java | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index c4d80a38ed61..8eccdc945e01 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -218,18 +218,14 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLangua String solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); - exerciseCheckoutDirectory = setEmptyPathToRootDirectory(exerciseCheckoutDirectory); - solutionCheckoutDirectory = setEmptyPathToRootDirectory(solutionCheckoutDirectory); - testCheckoutDirectory = setEmptyPathToRootDirectory(testCheckoutDirectory); + exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); + solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); + testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); return new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); } - private String setEmptyPathToRootDirectory(String checkoutDirectoryPath) { - if (checkoutDirectoryPath.isEmpty()) { - return ROOT_DIRECTORY; - } - - return checkoutDirectoryPath; + private String startPathWithRootDirectory(String checkoutDirectoryPath) { + return checkoutDirectoryPath.startsWith(ROOT_DIRECTORY) ? checkoutDirectoryPath : ROOT_DIRECTORY + checkoutDirectoryPath; } } diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 201083921fd7..c745639a0af8 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -6,6 +6,7 @@ import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -27,6 +28,7 @@ import de.tum.in.www1.artemis.service.connectors.aeolus.AeolusTemplateService; import de.tum.in.www1.artemis.service.connectors.aeolus.Windfile; import de.tum.in.www1.artemis.service.connectors.ci.ContinuousIntegrationService.BuildStatus; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; class LocalCIServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -106,4 +108,25 @@ void testUnsupportedMethods() { assertThat(latestArtifactResponse.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); assertThat(latestArtifactResponse.getBody()).hasSize(0); } + + @Nested + class GetCheckoutDirectoriesTests { + + @Test + void getCheckoutDirectoriesForJava() { + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.JAVA); + assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); + } + + @Test + void getCheckoutDirectoriesForOcaml() { + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML); + assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/solution"); + assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); + } + } + } From 53400b2ae2200404fbdb09efccabadd8d330ad18 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 21:52:24 +0200 Subject: [PATCH 021/117] Remove unused method --- .../programming/ContinuousIntegrationTestService.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java index 392da69c7995..0fc01427e235 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ContinuousIntegrationTestService.java @@ -104,10 +104,6 @@ public ProgrammingExerciseStudentParticipation getParticipation() { return participation; } - public LocalRepository getLocalRepo() { - return localRepo; - } - public void testGetBuildStatusNotFound() throws Exception { mockDelegate.mockGetBuildPlan(participation.getProgrammingExercise().getProjectKey(), participation.getBuildPlanId(), false, false, false, false); From dc79451c83e670a5877a9ab5655e48f75d5c069b Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 22:06:08 +0200 Subject: [PATCH 022/117] Adding tests --- ...ExerciseLocalVCLocalCIIntegrationTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index d65634dfce6f..a4ce8988163b 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -32,6 +32,7 @@ import de.tum.in.www1.artemis.participation.ParticipationUtilService; import de.tum.in.www1.artemis.service.connectors.localvc.LocalVCRepositoryUri; import de.tum.in.www1.artemis.util.LocalRepository; +import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -66,7 +67,7 @@ class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringInt @BeforeEach void setup() throws Exception { - userUtilService.addUsers(TEST_PREFIX, 1, 1, 0, 1); + userUtilService.addUsers(TEST_PREFIX, 1, 1, 1, 1); course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); programmingExercise = exerciseUtilService.getFirstExerciseWithType(course, ProgrammingExercise.class); @@ -239,4 +240,20 @@ void testImportProgrammingExercise() throws Exception { localVCLocalCITestService.testLatestSubmission(templateParticipation.getId(), null, 0, false); localVCLocalCITestService.testLatestSubmission(solutionParticipation.getId(), null, 13, false); } + + @Test + @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") + void testGetCheckoutDirectories() throws Exception { + RepositoriesCheckoutDirectoryDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, + RepositoriesCheckoutDirectoryDTO.class); + assertThat(checkoutDirectoryDTO.exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectoryDTO.solutionCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectoryDTO.testCheckoutDirectory()).isEqualTo("/"); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TUTOR") + void testGetCheckoutDirectoriesAccessForbidden() throws Exception { + request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, RepositoriesCheckoutDirectoryDTO.class); + } } From a7b1c16239b3d48e3a6f555098cffa27bde700ce Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 22:25:51 +0200 Subject: [PATCH 023/117] Adding client tests --- ...and-repositories-preview.component.spec.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts new file mode 100644 index 000000000000..325a7f67b69c --- /dev/null +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -0,0 +1,50 @@ +import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; +import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; + +describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { + let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent], + providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], + }) + .compileComponents() + .then(() => { + fixture = TestBed.createComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + }); + + it('should create', () => { + fixture.detectChanges(); + expect(component).not.toBeNull(); + }); + + it('should display checkout directories when they exist', () => { + component.exerciseCheckoutDirectory = 'exerciseDirectory'; + component.solutionCheckoutDirectory = 'solutionDirectory'; + component.testCheckoutDirectory = 'testDirectory'; + fixture.detectChanges(); + + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('.preview-box')).toBeTruthy(); + expect(compiled.querySelector('.preview-box').textContent).toContain('exerciseDirectory'); + expect(compiled.querySelector('.preview-box').textContent).toContain('solutionDirectory'); + expect(compiled.querySelector('.preview-box').textContent).toContain('testDirectory'); + }); + + it('should not display checkout directories when they do not exist', () => { + component.exerciseCheckoutDirectory = undefined; + component.solutionCheckoutDirectory = undefined; + component.testCheckoutDirectory = undefined; + fixture.detectChanges(); + + const compiled = fixture.debugElement.nativeElement; + expect(compiled.querySelector('.preview-box')).toBeFalsy(); + }); +}); From 99a416e33ce21f1ab3072e2ce7f9937e57633d8a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 22:56:07 +0200 Subject: [PATCH 024/117] Adding useful client tests --- ...ns-and-repositories-preview.component.html | 2 +- ...and-repositories-preview.component.spec.ts | 47 ++++++++++--------- .../mock-programming-exercise.service.ts | 2 + 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index cc6ba86b571a..e319b72fa353 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -63,7 +63,7 @@ } @else if (exerciseCheckoutDirectory || solutionCheckoutDirectory || testCheckoutDirectory) { -
    +
    diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 325a7f67b69c..759effa7f47b 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -2,49 +2,52 @@ import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exe import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; +import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; +import { HelpIconComponent } from 'app/shared/components/help-icon.component'; +import { MockComponent } from 'ng-mocks'; +import { of } from 'rxjs'; describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; let fixture: ComponentFixture; + let programmingExerciseService: ProgrammingExerciseService; beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent], + declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent)], providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], }) .compileComponents() .then(() => { fixture = TestBed.createComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent); component = fixture.componentInstance; - fixture.detectChanges(); + programmingExerciseService = TestBed.inject(ProgrammingExerciseService); }); }); - it('should create', () => { - fixture.detectChanges(); - expect(component).not.toBeNull(); - }); - it('should display checkout directories when they exist', () => { - component.exerciseCheckoutDirectory = 'exerciseDirectory'; - component.solutionCheckoutDirectory = 'solutionDirectory'; - component.testCheckoutDirectory = 'testDirectory'; - fixture.detectChanges(); + const checkoutDirectories: RepositoriesCheckoutDirectoriesDTO = { + solutionCheckoutDirectory: '/assignment', + exerciseCheckoutDirectory: '/assignment', + testCheckoutDirectory: '/', + }; - const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('.preview-box')).toBeTruthy(); - expect(compiled.querySelector('.preview-box').textContent).toContain('exerciseDirectory'); - expect(compiled.querySelector('.preview-box').textContent).toContain('solutionDirectory'); - expect(compiled.querySelector('.preview-box').textContent).toContain('testDirectory'); - }); + component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; + component.isLocal = true; + + component.programmingExerciseCreationConfig = { selectedProgrammingLanguage: ProgrammingLanguage.C } as ProgrammingExerciseCreationConfig; + + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockReturnValue(of(checkoutDirectories)); - it('should not display checkout directories when they do not exist', () => { - component.exerciseCheckoutDirectory = undefined; - component.solutionCheckoutDirectory = undefined; - component.testCheckoutDirectory = undefined; fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('.preview-box')).toBeFalsy(); + const previewElement = compiled.querySelector('#checkout-directory-preview'); + expect(previewElement).toBeTruthy(); + expect(previewElement.textContent).toContain('/assignment'); + expect(previewElement.textContent).toContain('/assignment'); + expect(previewElement.textContent).toContain('/'); }); }); diff --git a/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts b/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts index b3a397f64b44..84efbbe3bf94 100644 --- a/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts +++ b/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts @@ -1,6 +1,7 @@ import { of } from 'rxjs'; import { ProgrammingExerciseInstructorRepositoryType } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { Participation } from 'app/entities/participation/participation.model'; +import { ProgrammingLanguage } from 'app/entities/programming-exercise.model'; export class MockProgrammingExerciseService { updateProblemStatement = (exerciseId: number, problemStatement: string) => of(); @@ -25,4 +26,5 @@ export class MockProgrammingExerciseService { generateStructureOracle = (exerciseId: number) => of({}); unlockAllRepositories = (exerciseId: number) => of({}); getDiffReportForCommits = (exerciseId: number, participationId: number, olderCommitHash: string, newerCommitHash: string, repositoryType: string) => of({}); + getCheckoutDirectoriesForProgrammingLanguage = (programmingLanguage: ProgrammingLanguage) => of(); } From b60303709b9e71957197b4185f9cce09970a7bf5 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 23:06:26 +0200 Subject: [PATCH 025/117] Adding test that only necessary calls to the server are made --- ...lans-and-repositories-preview.component.ts | 9 ++++--- ...and-repositories-preview.component.spec.ts | 27 ++++++++++++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index cc0f7aa9f0aa..ad213e2f3944 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -57,12 +57,15 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { } ngOnInit() { - this.updateCheckoutDirectories(); - this.updateAuxiliaryRepositoryCheckoutDirectories(); + if (this.isLocal) { + this.updateCheckoutDirectories(); + this.updateAuxiliaryRepositoryCheckoutDirectories(); + } } ngOnChanges(changes: SimpleChanges) { if ( + this.isLocal && this.programmingExerciseCreationConfig && this.programmingExerciseCreationConfig.selectedProgrammingLanguage && changes.programmingExerciseCreationConfig && @@ -73,7 +76,7 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { this.updateCheckoutDirectories(); } - if (this.programmingExercise?.auxiliaryRepositories) { + if (this.isLocal && this.programmingExercise?.auxiliaryRepositories) { this.updateAuxiliaryRepositoryCheckoutDirectories(); } } diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 759effa7f47b..bba53076c34f 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -24,6 +24,10 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture = TestBed.createComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent); component = fixture.componentInstance; programmingExerciseService = TestBed.inject(ProgrammingExerciseService); + + component.programmingExerciseCreationConfig = { selectedProgrammingLanguage: ProgrammingLanguage.C } as ProgrammingExerciseCreationConfig; + component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; + component.isLocal = true; }); }); @@ -33,12 +37,6 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { exerciseCheckoutDirectory: '/assignment', testCheckoutDirectory: '/', }; - - component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; - component.isLocal = true; - - component.programmingExerciseCreationConfig = { selectedProgrammingLanguage: ProgrammingLanguage.C } as ProgrammingExerciseCreationConfig; - jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockReturnValue(of(checkoutDirectories)); fixture.detectChanges(); @@ -50,4 +48,21 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(previewElement.textContent).toContain('/assignment'); expect(previewElement.textContent).toContain('/'); }); + + it('should send request if localCI is used', () => { + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); + + fixture.detectChanges(); + + expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); + }); + + it('should NOT send request if localCI is NOT used', () => { + component.isLocal = false; + const spy = jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); + + fixture.detectChanges(); + + expect(spy).not.toHaveBeenCalled(); + }); }); From b00f7f416e1ebf2f1a62ac0961d8613991a78acc Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 23:18:07 +0200 Subject: [PATCH 026/117] Adding tests for the amount of rest calls --- ...and-repositories-preview.component.spec.ts | 32 +++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index bba53076c34f..1fd912df5cff 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -14,6 +14,8 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { let fixture: ComponentFixture; let programmingExerciseService: ProgrammingExerciseService; + const CHECKOUT_DIRECTORY_PREVIEW = '#checkout-directory-preview'; + beforeEach(() => { TestBed.configureTestingModule({ declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent)], @@ -28,21 +30,20 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { component.programmingExerciseCreationConfig = { selectedProgrammingLanguage: ProgrammingLanguage.C } as ProgrammingExerciseCreationConfig; component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; component.isLocal = true; + + const checkoutDirectories: RepositoriesCheckoutDirectoriesDTO = { + solutionCheckoutDirectory: '/assignment', + exerciseCheckoutDirectory: '/assignment', + testCheckoutDirectory: '', // Empty string should be converted to '/' + }; + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockReturnValue(of(checkoutDirectories)); }); }); it('should display checkout directories when they exist', () => { - const checkoutDirectories: RepositoriesCheckoutDirectoriesDTO = { - solutionCheckoutDirectory: '/assignment', - exerciseCheckoutDirectory: '/assignment', - testCheckoutDirectory: '/', - }; - jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockReturnValue(of(checkoutDirectories)); - fixture.detectChanges(); - const compiled = fixture.debugElement.nativeElement; - const previewElement = compiled.querySelector('#checkout-directory-preview'); + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); expect(previewElement).toBeTruthy(); expect(previewElement.textContent).toContain('/assignment'); expect(previewElement.textContent).toContain('/assignment'); @@ -65,4 +66,17 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(spy).not.toHaveBeenCalled(); }); + + it('should display checkoutDirectory preview if localCI is used', () => { + fixture.detectChanges(); + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); + expect(previewElement).toBeTruthy(); + }); + + it('should NOT display checkoutDirectory preview if localCI is NOT used', () => { + component.isLocal = false; + fixture.detectChanges(); + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); + expect(previewElement).toBeFalsy(); + }); }); From fdd626b0e72a51cb42af55025b0d99ca023943d8 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 23:22:15 +0200 Subject: [PATCH 027/117] Adding test for auxiliary repositories --- ...e-plans-and-repositories-preview.component.spec.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 1fd912df5cff..d90c25d7e4b1 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -8,6 +8,7 @@ import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/man import { HelpIconComponent } from 'app/shared/components/help-icon.component'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; +import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; @@ -79,4 +80,14 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); expect(previewElement).toBeFalsy(); }); + + it('should update auxiliary checkout repository directories', () => { + component.programmingExercise!.auxiliaryRepositories = [{ checkoutDirectory: 'assignment/sut' } as AuxiliaryRepository]; + + fixture.detectChanges(); + + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); + expect(previewElement).toBeTruthy(); + expect(previewElement.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added + }); }); From aac7d1893415578dc8fb88cf441ab013e108f304 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 15 May 2024 23:32:08 +0200 Subject: [PATCH 028/117] Fixing client tests --- src/main/webapp/app/shared/constants/input.constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/shared/constants/input.constants.ts b/src/main/webapp/app/shared/constants/input.constants.ts index 683069e6a9cc..77707c350a90 100644 --- a/src/main/webapp/app/shared/constants/input.constants.ts +++ b/src/main/webapp/app/shared/constants/input.constants.ts @@ -14,7 +14,7 @@ export const MAX_QUIZ_SHORT_ANSWER_TEXT_LENGTH = 255; // Must be consistent with /** Short names must start with a letter and cannot contain special characters **/ export const SHORT_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{2,}$/; /** Programming exercise titles must only contain alphanumeric characters, or whitespaces, or '_' or '-' **/ -export const TITLE_NAME_PATTERN = '^[a-zA-Z0-9_\\-\\s]*'; +export const TITLE_NAME_PATTERN = '^[a-zA-Z0-9-_ ]+'; /** Prefixes must follow the login pattern **/ export const LOGIN_PATTERN = /^[_'.@A-Za-z0-9-]*$/; export const MAX_QUIZ_QUESTION_POINTS = 9999; From c014260f3013a8a86c8a10d9dd94c099353b8525 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 00:40:12 +0200 Subject: [PATCH 029/117] Improving code quality by not calling method in html --- ...ns-and-repositories-preview.component.html | 22 +++++----------- ...lans-and-repositories-preview.component.ts | 26 ++++++++++++------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index e319b72fa353..25a1df17cb43 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -8,21 +8,15 @@
    • - - {{ getCourseShortName()?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-exercise - + {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-exercise
    • - - {{ getCourseShortName()?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-solution - + {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-solution
    • - - {{ getCourseShortName()?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-tests - + {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-tests
    • @if (programmingExercise.auxiliaryRepositories?.length) { @@ -31,7 +25,7 @@
    • - {{ getCourseShortName()?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-{{ auxiliaryRepository.name?.toLowerCase() }} + {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-{{ auxiliaryRepository.name?.toLowerCase() }}
    • @@ -49,15 +43,11 @@
      • - {{ getCourseShortName()?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-BASE + {{ shortName?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-BASE
      • - {{ getCourseShortName()?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-SOLUTION + {{ shortName?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-SOLUTION
      diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index ad213e2f3944..d4211047fd86 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -19,16 +19,11 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { constructor(private programmingExerciseService: ProgrammingExerciseService) {} - getCourseShortName(): string | undefined { - if (!this.programmingExercise) { - return undefined; - } - return getCourseFromExercise(this.programmingExercise)?.shortName; - } + shortName?: string; - solutionCheckoutDirectory: string | undefined; - exerciseCheckoutDirectory: string | undefined; - testCheckoutDirectory: string | undefined; + solutionCheckoutDirectory?: string; + exerciseCheckoutDirectory?: string; + testCheckoutDirectory?: string; auxiliaryRepositoryCheckoutDirectories: string[] = []; programmingExerciseServiceSubscription: Subscription; @@ -56,7 +51,16 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; } + private updateShortName() { + if (!this.programmingExercise) { + return; + } + this.shortName = getCourseFromExercise(this.programmingExercise)?.shortName; + } + ngOnInit() { + this.updateShortName(); + if (this.isLocal) { this.updateCheckoutDirectories(); this.updateAuxiliaryRepositoryCheckoutDirectories(); @@ -64,6 +68,10 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { } ngOnChanges(changes: SimpleChanges) { + if (changes.programmingExercise) { + this.updateShortName(); + } + if ( this.isLocal && this.programmingExerciseCreationConfig && From 02fbef7b5339b9677df79d0457d910dd43f95a49 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 00:42:04 +0200 Subject: [PATCH 030/117] Make undefined check inline --- ...mming-exercise-plans-and-repositories-preview.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index d4211047fd86..8371b710c159 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -90,8 +90,6 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { } ngOnDestroy() { - if (this.programmingExerciseServiceSubscription) { - this.programmingExerciseServiceSubscription.unsubscribe(); - } + this.programmingExerciseServiceSubscription?.unsubscribe(); } } From 443fbdb6e7efaa75d29d745a3c810ef598ede081 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 00:45:51 +0200 Subject: [PATCH 031/117] Adding test to increase coverage --- ...-plans-and-repositories-preview.component.spec.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index d90c25d7e4b1..7cd6e15e64e7 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -7,7 +7,7 @@ import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programmi import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; import { MockComponent } from 'ng-mocks'; -import { of } from 'rxjs'; +import { Subscription, of } from 'rxjs'; import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { @@ -90,4 +90,14 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(previewElement).toBeTruthy(); expect(previewElement.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added }); + + it('should unsubscribe from programmingExerciseServiceSubscription on destroy', () => { + const subscription = new Subscription(); + jest.spyOn(subscription, 'unsubscribe'); + component.programmingExerciseServiceSubscription = subscription; + + component.ngOnDestroy(); + + expect(subscription.unsubscribe).toHaveBeenCalled(); + }); }); From a8b9069bfcbfe4adbf0c3ffaa34f109189d1dfdc Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 00:55:10 +0200 Subject: [PATCH 032/117] Adding another test for the coverage --- ...and-repositories-preview.component.spec.ts | 41 ++++++++++++++++--- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 7cd6e15e64e7..2298b7d39021 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -9,6 +9,7 @@ import { HelpIconComponent } from 'app/shared/components/help-icon.component'; import { MockComponent } from 'ng-mocks'; import { Subscription, of } from 'rxjs'; import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; +import { SimpleChanges } from '@angular/core'; describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; @@ -17,6 +18,18 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { const CHECKOUT_DIRECTORY_PREVIEW = '#checkout-directory-preview'; + const JAVA_CHECKOUT_DIRECTORIES: RepositoriesCheckoutDirectoriesDTO = { + exerciseCheckoutDirectory: '/assignment', + solutionCheckoutDirectory: '/assignment', + testCheckoutDirectory: '', // Empty string should be converted to '/' + }; + + const OCAML_CHECKOUT_DIRECTORIES: RepositoriesCheckoutDirectoriesDTO = { + exerciseCheckoutDirectory: '/assignment', + solutionCheckoutDirectory: '/solution', + testCheckoutDirectory: '/tests', + }; + beforeEach(() => { TestBed.configureTestingModule({ declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent)], @@ -32,12 +45,13 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; component.isLocal = true; - const checkoutDirectories: RepositoriesCheckoutDirectoriesDTO = { - solutionCheckoutDirectory: '/assignment', - exerciseCheckoutDirectory: '/assignment', - testCheckoutDirectory: '', // Empty string should be converted to '/' - }; - jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockReturnValue(of(checkoutDirectories)); + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockImplementation((programmingLanguage: ProgrammingLanguage) => { + if (programmingLanguage === ProgrammingLanguage.JAVA) { + return of(JAVA_CHECKOUT_DIRECTORIES); + } + + return of(OCAML_CHECKOUT_DIRECTORIES); + }); }); }); @@ -100,4 +114,19 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(subscription.unsubscribe).toHaveBeenCalled(); }); + + it('should update checkout directories when selectedProgrammingLanguage changes', () => { + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); + + component.ngOnChanges({ + programmingExerciseCreationConfig: { + currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, + previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, + }, + } as unknown as SimpleChanges); + + // assertion to check if ngOnChanges was executed properly and updated the checkout directories + expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); + expect(component.solutionCheckoutDirectory).toBe('/solution'); // was '/assignment' before with JAVA as programming language + }); }); From ed8ba16db7b0992a51359397c59dddd1bae2d921 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 01:13:55 +0200 Subject: [PATCH 033/117] Another test just to raise the coverage... --- ...-and-repositories-preview.component.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 2298b7d39021..506efdbe9afb 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -129,4 +129,22 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); expect(component.solutionCheckoutDirectory).toBe('/solution'); // was '/assignment' before with JAVA as programming language }); + + it('should update auxiliary repository directories on changes', () => { + fixture.detectChanges(); + + component.programmingExercise!.auxiliaryRepositories = [{ checkoutDirectory: 'assignment/src' } as AuxiliaryRepository]; + component.ngOnChanges({ + programmingExercise: { + currentValue: { auxiliaryRepositories: [{ checkoutDirectory: 'assignment/src' } as AuxiliaryRepository] }, + previousValue: { auxiliaryRepositories: [] }, + }, + } as unknown as SimpleChanges); + + fixture.detectChanges(); + + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); + expect(previewElement).toBeTruthy(); + expect(previewElement.textContent).toContain('/assignment/src'); + }); }); From 57ee81c250cd977d8194fa26440f192742f8c3ce Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 01:20:34 +0200 Subject: [PATCH 034/117] Changing order of current and previous value --- ...-exercise-plans-and-repositories-preview.component.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 506efdbe9afb..e00e4a8e8a5d 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -120,8 +120,8 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { component.ngOnChanges({ programmingExerciseCreationConfig: { - currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, + currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, }, } as unknown as SimpleChanges); @@ -136,8 +136,8 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { component.programmingExercise!.auxiliaryRepositories = [{ checkoutDirectory: 'assignment/src' } as AuxiliaryRepository]; component.ngOnChanges({ programmingExercise: { - currentValue: { auxiliaryRepositories: [{ checkoutDirectory: 'assignment/src' } as AuxiliaryRepository] }, previousValue: { auxiliaryRepositories: [] }, + currentValue: { auxiliaryRepositories: [{ checkoutDirectory: 'assignment/src' } as AuxiliaryRepository] }, }, } as unknown as SimpleChanges); From 31f0dbcc59a92ba8b9e5b931a09042b98805c8e0 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 14:09:47 +0200 Subject: [PATCH 035/117] Display auxRepo checkout path as code, similar to the edit mode --- .../detail-overview-list/detail-overview-list.component.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 5271ec9101c0..14c624c395d2 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -103,7 +103,9 @@

      {{ section }
      @if (auxiliaryRepository.checkoutDirectory) { - Checkout Directory: {{ auxiliaryRepository.checkoutDirectory }} + Checkout Directory: {{ auxiliaryRepository.checkoutDirectory }} + } @else { From 29e8dec9d9bfe191256bde6a4a8ee99b56cb6739 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 15:27:11 +0200 Subject: [PATCH 036/117] RootDirectory vs RootDirectoryPath --- ...ing-exercise-plans-and-repositories-preview.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 8371b710c159..8bb59439e5ff 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -5,7 +5,7 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; -const ROOT_DIRECTORY: string = '/'; +const ROOT_DIRECTORY_PATH: string = '/'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -30,10 +30,10 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { private addLeadingSlashIfNotPresent(directory: string | undefined): string { if (!directory) { - return ROOT_DIRECTORY; + return ROOT_DIRECTORY_PATH; } - return directory.startsWith(ROOT_DIRECTORY) ? directory : ROOT_DIRECTORY + directory; + return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; } private updateCheckoutDirectories() { From 17e7f99318a99940006d6155cb08771bf014e0ec Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 15:28:01 +0200 Subject: [PATCH 037/117] Display checkout directories in overview --- .../detail-overview-list.component.html | 9 +++++++-- src/main/webapp/app/detail-overview-list/detail.model.ts | 5 +++++ .../manage/programming-exercise-detail.component.ts | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 14c624c395d2..61fe85404ba8 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -76,6 +76,11 @@

      {{ section }

      +
      + + Checkout Directory: {{ 'test' }} + +
      } @else { } @@ -103,8 +108,8 @@

      {{ section }
      @if (auxiliaryRepository.checkoutDirectory) { - Checkout Directory: {{ auxiliaryRepository.checkoutDirectory }} + + Checkout Directory: {{ auxiliaryRepository.checkoutDirectory }} } @else { diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index e87603a5b13b..5bf739f56353 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -82,6 +82,10 @@ interface ProgrammingIrisEnabledDetail extends DetailBase { data: { exercise?: ProgrammingExercise; course?: Course; disabled: boolean; subSettingsType: IrisSubSettingsType }; } +/** + * {@link ProgrammingRepositoryButtonsDetail.data.checkoutDirectory} is only needed for localCI, as otherwise the information + * about the checkout directories will be present in the build plans (for the base repositories exercise, solution, tests) + */ interface ProgrammingRepositoryButtonsDetail extends DetailBase { type: DetailType.ProgrammingRepositoryButtons; data: { @@ -89,6 +93,7 @@ interface ProgrammingRepositoryButtonsDetail extends DetailBase { participation?: TemplateProgrammingExerciseParticipation | SolutionProgrammingExerciseParticipation; showOpenLink?: boolean; type: ProgrammingExerciseInstructorRepositoryType; + checkoutDirectory?: string; }; } diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 6a25143811ec..a819cc47cda1 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -341,6 +341,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TEMPLATE', showOpenLink: !this.localVCEnabled, + checkoutDirectory: this.localVCEnabled ? 'test' : undefined, }, }, { @@ -351,6 +352,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'SOLUTION', showOpenLink: !this.localVCEnabled, + checkoutDirectory: this.localVCEnabled ? 'test' : undefined, }, }, { @@ -361,6 +363,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TESTS', showOpenLink: !this.localVCEnabled, + checkoutDirectory: this.localVCEnabled ? 'test' : undefined, }, }, this.supportsAuxiliaryRepositories && From 1751f3cb480fc6ed029ca89f1e2cc1899c49a776 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 15:49:38 +0200 Subject: [PATCH 038/117] Moving the root directory logic to the services to simplify usage in other views --- .../services/programming-exercise.service.ts | 20 +++++++++++++----- ...lans-and-repositories-preview.component.ts | 21 ++++++------------- src/main/webapp/app/shared/util/utils.ts | 10 +++++++++ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index 67521032ab2e..bee90910dbd8 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -26,6 +26,7 @@ import { Result } from 'app/entities/result.model'; import { Participation } from 'app/entities/participation/participation.model'; import { PlagiarismResultDTO } from 'app/exercises/shared/plagiarism/types/PlagiarismResultDTO'; import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; export type EntityResponseType = HttpResponse; export type EntityArrayResponseType = HttpResponse; @@ -667,10 +668,19 @@ export class ProgrammingExerciseService { } getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { - return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { - params: { - programmingLanguage, - }, - }); + return this.http + .get(`${this.resourceUrl}/repository-checkout-directories`, { + params: { + programmingLanguage, + }, + }) + .pipe( + map((checkoutDirectories: RepositoriesCheckoutDirectoriesDTO) => { + checkoutDirectories.exerciseCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.exerciseCheckoutDirectory); + checkoutDirectories.solutionCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.solutionCheckoutDirectory); + checkoutDirectories.testCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.testCheckoutDirectory); + return checkoutDirectories; + }), + ); } } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 8bb59439e5ff..64f1b61e2b9b 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -4,8 +4,7 @@ import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; - -const ROOT_DIRECTORY_PATH: string = '/'; +import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -28,27 +27,19 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { programmingExerciseServiceSubscription: Subscription; - private addLeadingSlashIfNotPresent(directory: string | undefined): string { - if (!directory) { - return ROOT_DIRECTORY_PATH; - } - - return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; - } - private updateCheckoutDirectories() { - this.programmingExerciseService + this.programmingExerciseServiceSubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) .subscribe((checkoutDirectories) => { - this.solutionCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.solutionCheckoutDirectory); - this.exerciseCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.exerciseCheckoutDirectory); - this.testCheckoutDirectory = this.addLeadingSlashIfNotPresent(checkoutDirectories.testCheckoutDirectory); + this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; + this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; + this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; }); } private updateAuxiliaryRepositoryCheckoutDirectories() { this.auxiliaryRepositoryCheckoutDirectories = - this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; + this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; } private updateShortName() { diff --git a/src/main/webapp/app/shared/util/utils.ts b/src/main/webapp/app/shared/util/utils.ts index 9e9d40d0ca36..62b25551ba17 100644 --- a/src/main/webapp/app/shared/util/utils.ts +++ b/src/main/webapp/app/shared/util/utils.ts @@ -166,3 +166,13 @@ export function scrollToTopOfPage() { pageWrapper.scroll(0, 0); } } + +const ROOT_DIRECTORY_PATH: string = '/'; + +export function addLeadingSlashIfNotPresent(directory: string | undefined): string { + if (!directory) { + return ROOT_DIRECTORY_PATH; + } + + return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; +} From a39d4de166c4799d990fff5b32829f8d55b4faee Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 15:52:59 +0200 Subject: [PATCH 039/117] Simplify usage of service --- ...xercise-plans-and-repositories-preview.component.html | 8 ++++---- ...-exercise-plans-and-repositories-preview.component.ts | 9 +++------ 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 25a1df17cb43..1bc5fadd1a80 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -52,7 +52,7 @@

    - } @else if (exerciseCheckoutDirectory || solutionCheckoutDirectory || testCheckoutDirectory) { + } @else if (checkoutDirectories) {
    @@ -60,13 +60,13 @@
    • - {{ exerciseCheckoutDirectory }} + {{ checkoutDirectories.exerciseCheckoutDirectory }}
    • - {{ solutionCheckoutDirectory }} + {{ checkoutDirectories.solutionCheckoutDirectory }}
    • - {{ testCheckoutDirectory }} + {{ checkoutDirectories.testCheckoutDirectory }}
    • @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) {
    • diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 64f1b61e2b9b..025f89802cfc 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -5,6 +5,7 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -20,9 +21,7 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { shortName?: string; - solutionCheckoutDirectory?: string; - exerciseCheckoutDirectory?: string; - testCheckoutDirectory?: string; + checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; auxiliaryRepositoryCheckoutDirectories: string[] = []; programmingExerciseServiceSubscription: Subscription; @@ -31,9 +30,7 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { this.programmingExerciseServiceSubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) .subscribe((checkoutDirectories) => { - this.exerciseCheckoutDirectory = checkoutDirectories.exerciseCheckoutDirectory; - this.solutionCheckoutDirectory = checkoutDirectories.solutionCheckoutDirectory; - this.testCheckoutDirectory = checkoutDirectories.testCheckoutDirectory; + this.checkoutDirectories = checkoutDirectories; }); } From 086da3948aa16537594306c94f2be623977725a9 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 16:07:29 +0200 Subject: [PATCH 040/117] Loading checkout directories on details page --- .../detail-overview-list.component.html | 2 +- .../programming-exercise-detail.component.ts | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 61fe85404ba8..1f30a22f1c11 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -78,7 +78,7 @@

      {{ section

    - Checkout Directory: {{ 'test' }} + Checkout Directory: {{ detail.data.checkoutDirectory }}
    } @else { diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index a819cc47cda1..b36d0d50436d 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -56,6 +56,7 @@ import { IrisSubSettingsType } from 'app/entities/iris/settings/iris-sub-setting import { Detail } from 'app/detail-overview-list/detail.model'; import { Competency } from 'app/entities/competency.model'; import { AeolusService } from 'app/exercises/programming/shared/service/aeolus.service'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-detail', @@ -101,6 +102,8 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { plagiarismCheckSupported = false; // default value + checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; + private dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); @@ -231,6 +234,12 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { this.exerciseDetailSections = this.getExerciseDetails(); }); + if (this.programmingExercise.programmingLanguage) { + this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage).subscribe((checkoutDirectories) => { + this.checkoutDirectories = checkoutDirectories; + }); + } + this.statisticsService.getExerciseStatistics(exerciseId!).subscribe((statistics: ExerciseManagementStatisticsDto) => { this.doughnutStats = statistics; }); @@ -341,7 +350,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TEMPLATE', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? 'test' : undefined, + checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.exerciseCheckoutDirectory : undefined, }, }, { @@ -352,7 +361,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'SOLUTION', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? 'test' : undefined, + checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.solutionCheckoutDirectory : undefined, }, }, { @@ -363,7 +372,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TESTS', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? 'test' : undefined, + checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.testCheckoutDirectory : undefined, }, }, this.supportsAuxiliaryRepositories && From c9f94c7e46b9d07dfd5a13b57815aab91b925088 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 16:12:40 +0200 Subject: [PATCH 041/117] Using translations instead of hardcoded strings --- .../detail-overview-list.component.html | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 1f30a22f1c11..95dc232c6004 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -77,9 +77,8 @@

    {{ section }

    - - Checkout Directory: {{ detail.data.checkoutDirectory }} - + : + {{ detail.data.checkoutDirectory }}
    } @else { @@ -108,9 +107,8 @@

    {{ section }
    @if (auxiliaryRepository.checkoutDirectory) { - - Checkout Directory: {{ auxiliaryRepository.checkoutDirectory }} - + : + {{ auxiliaryRepository.checkoutDirectory }} } @else { From ff259d0af2e20c07f69d0b8c8f1fe3847424bd0f Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 22:32:55 +0200 Subject: [PATCH 042/117] Fixing client test --- ...ng-exercise-plans-and-repositories-preview.component.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index e00e4a8e8a5d..5f595428006b 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -127,7 +127,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { // assertion to check if ngOnChanges was executed properly and updated the checkout directories expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); - expect(component.solutionCheckoutDirectory).toBe('/solution'); // was '/assignment' before with JAVA as programming language + expect(component.checkoutDirectories?.solutionCheckoutDirectory).toBe('/solution'); // was '/assignment' before with JAVA as programming language }); it('should update auxiliary repository directories on changes', () => { From 049806132aeb83700af82ef389a34f39fb09897d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 22:37:09 +0200 Subject: [PATCH 043/117] Unsubscribing on destroy --- .../manage/programming-exercise-detail.component.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index b36d0d50436d..43e23ba83d1e 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -1,7 +1,7 @@ import { Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { SafeHtml } from '@angular/platform-browser'; -import { Subject } from 'rxjs'; +import { Subject, Subscription } from 'rxjs'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { AlertService, AlertType } from 'app/core/util/alert.service'; @@ -104,6 +104,8 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; + programmingExerciseServiceSubscription: Subscription; + private dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); @@ -235,9 +237,11 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { }); if (this.programmingExercise.programmingLanguage) { - this.programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage).subscribe((checkoutDirectories) => { - this.checkoutDirectories = checkoutDirectories; - }); + this.programmingExerciseServiceSubscription = this.programmingExerciseService + .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage) + .subscribe((checkoutDirectories) => { + this.checkoutDirectories = checkoutDirectories; + }); } this.statisticsService.getExerciseStatistics(exerciseId!).subscribe((statistics: ExerciseManagementStatisticsDto) => { @@ -248,6 +252,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.dialogErrorSource.unsubscribe(); + this.programmingExerciseServiceSubscription?.unsubscribe(); } getExerciseDetails(): DetailOverviewSection[] { From 72312db0798de907f7eff7b4f911f491382ee834 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 16 May 2024 22:43:42 +0200 Subject: [PATCH 044/117] Fixing previous code, unsubscribing from subscriptions on destroy --- .../programming-exercise-detail.component.ts | 143 +++++++++++------- 1 file changed, 85 insertions(+), 58 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 43e23ba83d1e..1f7fe6c88851 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -104,7 +104,14 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; - programmingExerciseServiceSubscription: Subscription; + private checkoutDirectoriesSubscription: Subscription; + private activatedRouteSubscription: Subscription; + private templateAndSolutionParticipationSubscription: Subscription; + private profileInfoSubscription: Subscription; + private irisSettingsSubscription: Subscription; + private submissionPolicySubscription: Subscription; + private buildLogsSubscription: Subscription; + private exerciseStatisticsSubscription: Subscription; private dialogErrorSource = new Subject(); dialogError$ = this.dialogErrorSource.asObservable(); @@ -152,7 +159,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { ngOnInit() { this.checkBuildPlanEditable(); - this.activatedRoute.data.subscribe(({ programmingExercise }) => { + this.activatedRouteSubscription = this.activatedRoute.data.subscribe(({ programmingExercise }) => { this.programmingExercise = programmingExercise; this.competencies = programmingExercise.competencies; const exerciseId = this.programmingExercise.id!; @@ -175,76 +182,89 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { `/exercise-groups/${this.programmingExercise.exerciseGroup?.id}/exercises/${this.programmingExercise.exerciseGroup?.exam?.id}/`; } - this.programmingExerciseService.findWithTemplateAndSolutionParticipationAndLatestResults(programmingExercise.id!).subscribe((updatedProgrammingExercise) => { - this.programmingExercise = updatedProgrammingExercise.body!; - - this.setLatestCoveredLineRatio(); - this.loadingTemplateParticipationResults = false; - this.loadingSolutionParticipationResults = false; - this.profileService.getProfileInfo().subscribe(async (profileInfo) => { - if (profileInfo) { - if (this.programmingExercise.projectKey && this.programmingExercise.templateParticipation && this.programmingExercise.templateParticipation.buildPlanId) { - this.programmingExercise.templateParticipation.buildPlanUrl = createBuildPlanUrl( - profileInfo.buildPlanURLTemplate, - this.programmingExercise.projectKey, - this.programmingExercise.templateParticipation.buildPlanId, - ); + this.templateAndSolutionParticipationSubscription = this.programmingExerciseService + .findWithTemplateAndSolutionParticipationAndLatestResults(programmingExercise.id!) + .subscribe((updatedProgrammingExercise) => { + this.programmingExercise = updatedProgrammingExercise.body!; + + this.setLatestCoveredLineRatio(); + this.loadingTemplateParticipationResults = false; + this.loadingSolutionParticipationResults = false; + this.profileInfoSubscription = this.profileService.getProfileInfo().subscribe(async (profileInfo) => { + if (profileInfo) { + if ( + this.programmingExercise.projectKey && + this.programmingExercise.templateParticipation && + this.programmingExercise.templateParticipation.buildPlanId + ) { + this.programmingExercise.templateParticipation.buildPlanUrl = createBuildPlanUrl( + profileInfo.buildPlanURLTemplate, + this.programmingExercise.projectKey, + this.programmingExercise.templateParticipation.buildPlanId, + ); + } + if ( + this.programmingExercise.projectKey && + this.programmingExercise.solutionParticipation && + this.programmingExercise.solutionParticipation.buildPlanId + ) { + this.programmingExercise.solutionParticipation.buildPlanUrl = createBuildPlanUrl( + profileInfo.buildPlanURLTemplate, + this.programmingExercise.projectKey, + this.programmingExercise.solutionParticipation.buildPlanId, + ); + } + this.supportsAuxiliaryRepositories = + this.programmingLanguageFeatureService.getProgrammingLanguageFeature(programmingExercise.programmingLanguage).auxiliaryRepositoriesSupported ?? + false; + this.localVCEnabled = profileInfo.activeProfiles.includes(PROFILE_LOCALVC); + this.irisEnabled = profileInfo.activeProfiles.includes(PROFILE_IRIS); + if (this.irisEnabled) { + this.irisSettingsSubscription = this.irisSettingsService.getCombinedCourseSettings(this.courseId).subscribe((settings) => { + this.irisChatEnabled = settings?.irisChatSettings?.enabled ?? false; + this.exerciseDetailSections = this.getExerciseDetails(); + }); + } } - if (this.programmingExercise.projectKey && this.programmingExercise.solutionParticipation && this.programmingExercise.solutionParticipation.buildPlanId) { - this.programmingExercise.solutionParticipation.buildPlanUrl = createBuildPlanUrl( - profileInfo.buildPlanURLTemplate, - this.programmingExercise.projectKey, - this.programmingExercise.solutionParticipation.buildPlanId, - ); - } - this.supportsAuxiliaryRepositories = - this.programmingLanguageFeatureService.getProgrammingLanguageFeature(programmingExercise.programmingLanguage).auxiliaryRepositoriesSupported ?? false; - this.localVCEnabled = profileInfo.activeProfiles.includes(PROFILE_LOCALVC); - this.irisEnabled = profileInfo.activeProfiles.includes(PROFILE_IRIS); - if (this.irisEnabled) { - this.irisSettingsService.getCombinedCourseSettings(this.courseId).subscribe((settings) => { - this.irisChatEnabled = settings?.irisChatSettings?.enabled ?? false; - this.exerciseDetailSections = this.getExerciseDetails(); - }); - } - } - this.exerciseDetailSections = this.getExerciseDetails(); - }); + this.exerciseDetailSections = this.getExerciseDetails(); + }); - this.programmingExerciseSubmissionPolicyService.getSubmissionPolicyOfProgrammingExercise(exerciseId!).subscribe((submissionPolicy) => { - this.programmingExercise.submissionPolicy = submissionPolicy; - this.exerciseDetailSections = this.getExerciseDetails(); - }); + this.submissionPolicySubscription = this.programmingExerciseSubmissionPolicyService + .getSubmissionPolicyOfProgrammingExercise(exerciseId!) + .subscribe((submissionPolicy) => { + this.programmingExercise.submissionPolicy = submissionPolicy; + this.exerciseDetailSections = this.getExerciseDetails(); + }); - this.loadGitDiffReport(); + this.loadGitDiffReport(); - // the build logs endpoint requires at least editor privileges - if (this.programmingExercise.isAtLeastEditor) { - this.programmingExerciseService - .getBuildLogStatistics(exerciseId!) - .subscribe((buildLogStatistics) => (this.programmingExercise.buildLogStatistics = buildLogStatistics)); - this.exerciseDetailSections = this.getExerciseDetails(); - } + // the build logs endpoint requires at least editor privileges + if (this.programmingExercise.isAtLeastEditor) { + this.buildLogsSubscription = this.programmingExerciseService + .getBuildLogStatistics(exerciseId!) + .subscribe((buildLogStatistics) => (this.programmingExercise.buildLogStatistics = buildLogStatistics)); + this.exerciseDetailSections = this.getExerciseDetails(); + } - this.setLatestCoveredLineRatio(); + this.setLatestCoveredLineRatio(); - this.checkAndAlertInconsistencies(); + this.checkAndAlertInconsistencies(); - this.plagiarismCheckSupported = this.programmingLanguageFeatureService.getProgrammingLanguageFeature( - programmingExercise.programmingLanguage, - ).plagiarismCheckSupported; - this.exerciseDetailSections = this.getExerciseDetails(); - }); + this.plagiarismCheckSupported = this.programmingLanguageFeatureService.getProgrammingLanguageFeature( + programmingExercise.programmingLanguage, + ).plagiarismCheckSupported; + this.exerciseDetailSections = this.getExerciseDetails(); + }); if (this.programmingExercise.programmingLanguage) { - this.programmingExerciseServiceSubscription = this.programmingExerciseService + this.checkoutDirectoriesSubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage) .subscribe((checkoutDirectories) => { this.checkoutDirectories = checkoutDirectories; }); } - this.statisticsService.getExerciseStatistics(exerciseId!).subscribe((statistics: ExerciseManagementStatisticsDto) => { + this.exerciseStatisticsSubscription = this.statisticsService.getExerciseStatistics(exerciseId!).subscribe((statistics: ExerciseManagementStatisticsDto) => { this.doughnutStats = statistics; }); }); @@ -252,7 +272,14 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.dialogErrorSource.unsubscribe(); - this.programmingExerciseServiceSubscription?.unsubscribe(); + this.checkoutDirectoriesSubscription?.unsubscribe(); + this.activatedRouteSubscription?.unsubscribe(); + this.templateAndSolutionParticipationSubscription?.unsubscribe(); + this.profileInfoSubscription?.unsubscribe(); + this.irisSettingsSubscription?.unsubscribe(); + this.submissionPolicySubscription?.unsubscribe(); + this.buildLogsSubscription?.unsubscribe(); + this.exerciseStatisticsSubscription?.unsubscribe(); } getExerciseDetails(): DetailOverviewSection[] { From ee33c46b09b4634e790f3840cbb0e74708cc19cd Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 03:39:27 +0200 Subject: [PATCH 045/117] Adjusting translations --- .../detail-overview-list.component.html | 4 ++-- ...-exercise-plans-and-repositories-preview.component.html | 2 +- .../programming-exercise-information.component.html | 2 +- src/main/webapp/i18n/de/programmingExercise.json | 5 +++-- src/main/webapp/i18n/en/programmingExercise.json | 7 ++++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 95dc232c6004..2af61331eb94 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -77,7 +77,7 @@

    {{ section }

    - : + : {{ detail.data.checkoutDirectory }}
    } @else { @@ -107,7 +107,7 @@

    {{ section }
    @if (auxiliaryRepository.checkoutDirectory) { - : + : {{ auxiliaryRepository.checkoutDirectory }} } @else { diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 1bc5fadd1a80..a4004126424a 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -55,7 +55,7 @@ } @else if (checkoutDirectories) {
    - +

      diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 727f6fcf6902..72c446bc81fe 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -81,7 +81,7 @@ /> - + Date: Sun, 19 May 2024 03:56:17 +0200 Subject: [PATCH 046/117] Adjusting tooltip for LocalVC --- .../programming-exercise-information.component.html | 6 +++++- src/main/webapp/i18n/de/programmingExercise.json | 1 + src/main/webapp/i18n/en/programmingExercise.json | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 72c446bc81fe..91316e5c9e9a 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -49,7 +49,11 @@
      - + @if (isLocal) { + + } @else { + + }
      Date: Sun, 19 May 2024 04:37:45 +0200 Subject: [PATCH 047/117] build execution vs. Build Execution --- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 05fe0545ba5e..34bbfa21b197 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -437,7 +437,7 @@ "preview": { "label": "Preview", "tooltip": "For every programming exercise, repositories and build plans will be generated. Here, you can find their generated names based on the short name of the exercise (and course)", - "tooltipLocalVC": "Here, you can find the repositories linked to the exercise and their respective checkout directories during the build execution.", + "tooltipLocalVC": "Here, you can find the repositories linked to the exercise and their respective checkout directories during the Build Execution.", "repositories": "Repositories", "buildPlans": "Build Plans", "templateRepoTooltip": "The repository which contains the template of the exercise", From 3780d147403f6f7e27099199027f027564d1b959 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 05:13:22 +0200 Subject: [PATCH 048/117] Make client style happy --- ...mming-exercise-plans-and-repositories-preview.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 025f89802cfc..f05632a6a743 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, SimpleChanges } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; @@ -12,7 +12,7 @@ import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/ma templateUrl: './programming-exercise-plans-and-repositories-preview.component.html', styleUrls: ['../programming-exercise-form.scss'], }) -export class ProgrammingExercisePlansAndRepositoriesPreviewComponent { +export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements OnInit, OnChanges, OnDestroy { @Input() programmingExercise: ProgrammingExercise | null; @Input() isLocal: boolean; @Input() programmingExerciseCreationConfig: ProgrammingExerciseCreationConfig; From 4abbed438c7bee53c69e53f8a7e29b10b8651b7a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 05:41:29 +0200 Subject: [PATCH 049/117] Lower the restriction to tutors instead of editors --- .../web/rest/programming/ProgrammingExerciseResource.java | 2 +- .../ProgrammingExerciseLocalVCLocalCIIntegrationTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index a404799de4dd..a7df003e4f19 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -885,7 +885,7 @@ public ResponseEntity getBuildLogStatistics(@PathVariable * @return a DTO containing the checkout directories for the exercise, solution, and test repository for the requested programming language. */ @GetMapping("programming-exercises/repository-checkout-directories") - @EnforceAtLeastEditor + @EnforceAtLeastTutor @FeatureToggle(Feature.ProgrammingExercises) public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index a4ce8988163b..f51c8bdac819 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -67,7 +67,7 @@ class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringInt @BeforeEach void setup() throws Exception { - userUtilService.addUsers(TEST_PREFIX, 1, 1, 1, 1); + userUtilService.addUsers(TEST_PREFIX, 1, 1, 0, 1); course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); programmingExercise = exerciseUtilService.getFirstExerciseWithType(course, ProgrammingExercise.class); @@ -242,7 +242,7 @@ void testImportProgrammingExercise() throws Exception { } @Test - @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") + @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TUTOR") void testGetCheckoutDirectories() throws Exception { RepositoriesCheckoutDirectoryDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, RepositoriesCheckoutDirectoryDTO.class); @@ -252,7 +252,7 @@ void testGetCheckoutDirectories() throws Exception { } @Test - @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TUTOR") + @WithMockUser(username = TEST_PREFIX + "student1", roles = "STUDENT") void testGetCheckoutDirectoriesAccessForbidden() throws Exception { request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, RepositoriesCheckoutDirectoryDTO.class); } From a630d6c6bf8d71533f2ab948e22d242cfcf076b9 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 05:52:42 +0200 Subject: [PATCH 050/117] Fixing unintentional typo --- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 34bbfa21b197..07738ec02710 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -456,7 +456,7 @@ "reEvaluateSuccessful": "{{number}} automatic results were successfully updated, including the template and solution.", "reEvaluateFailed": "The re-evaluation failed: {{message}}", "editSelectedModal": { - "currentlyEdiƒted": "You are editing the following exercises:", + "currentlyEdited": "You are editing the following exercises:", "errorReadButton": "Ok", "errorOccurred": "The following exercises could not be updated:" }, From e49a2dad7b7163eb00c43d32d02f31e3f586e3bf Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 15:07:14 +0200 Subject: [PATCH 051/117] Fixing test --- src/main/java/de/tum/in/www1/artemis/security/Role.java | 2 +- .../ProgrammingExerciseLocalVCLocalCIIntegrationTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/security/Role.java b/src/main/java/de/tum/in/www1/artemis/security/Role.java index bbd95ce02751..e2c87d502059 100644 --- a/src/main/java/de/tum/in/www1/artemis/security/Role.java +++ b/src/main/java/de/tum/in/www1/artemis/security/Role.java @@ -5,7 +5,7 @@ */ public enum Role { - // NOTE: we will soon rename "USER" to "STUDENT" in the database and add a new role "EDITOR" + // NOTE: we will soon rename "USER" to "STUDENT" in the database ADMIN("ADMIN"), INSTRUCTOR("INSTRUCTOR"), EDITOR("EDITOR"), TEACHING_ASSISTANT("TA"), STUDENT("USER"), ANONYMOUS("ANONYMOUS"); public static final String ROLE_PREFIX = "ROLE_"; diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index f51c8bdac819..ac4c6ca55741 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -242,7 +242,7 @@ void testImportProgrammingExercise() throws Exception { } @Test - @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TUTOR") + @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") void testGetCheckoutDirectories() throws Exception { RepositoriesCheckoutDirectoryDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, RepositoriesCheckoutDirectoryDTO.class); From 019b69b79e4562b3632415c1844a264a01886312 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 15:11:35 +0200 Subject: [PATCH 052/117] Returning null vs UnsupportedOperationException --- .../artemis/service/connectors/gitlabci/GitLabCIService.java | 3 +-- .../artemis/service/connectors/jenkins/JenkinsService.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index b127ba60f4ee..3f6ce783e766 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -327,7 +327,6 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { @Override public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { - // Not needed since the checkout directories are defined in the build plans stored in GitLab - return null; + throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index dd23e06369fd..a14a7c94bf9b 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -258,7 +258,6 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th @Override public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { - // Not needed since the checkout directories are defined in the build plans in Jenkins - return null; + throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); } } From b62362079a12cb1521871984d3421f7abbd15703 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 15:25:49 +0200 Subject: [PATCH 053/117] Use RegEx instead of custom check --- .../exam-exercise-import/exam-exercise-import.component.ts | 5 ++--- .../manage/update/programming-exercise-update.component.ts | 6 +++--- src/main/webapp/app/shared/constants/input.constants.ts | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts index ce25ddcc47f7..342c7b6fb1c1 100644 --- a/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts +++ b/src/main/webapp/app/exam/manage/exams/exam-exercise-import/exam-exercise-import.component.ts @@ -3,7 +3,7 @@ import { Exam } from 'app/entities/exam.model'; import { faCheckDouble, faFont } from '@fortawesome/free-solid-svg-icons'; import { Exercise, ExerciseType, getIcon } from 'app/entities/exercise.model'; import { ExerciseGroup } from 'app/entities/exercise-group.model'; -import { SHORT_NAME_PATTERN, TITLE_NAME_PATTERN } from 'app/shared/constants/input.constants'; +import { EXERCISE_TITLE_NAME_REGEX, SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; @Component({ selector: 'jhi-exam-exercise-import', @@ -34,7 +34,6 @@ export class ExamExerciseImportComponent implements OnInit { // Patterns // length of < 3 is also accepted in order to provide more accurate validation error messages readonly SHORT_NAME_REGEX = RegExp('(^(?![\\s\\S]))|^[a-zA-Z][a-zA-Z0-9]*$|' + SHORT_NAME_PATTERN); // must start with a letter and cannot contain special characters - readonly TITLE_NAME_REGEX = RegExp(TITLE_NAME_PATTERN); // Icons faCheckDouble = faCheckDouble; @@ -217,7 +216,7 @@ export class ExamExerciseImportComponent implements OnInit { validateTitleOfProgrammingExercise(exercise: Exercise): boolean { return ( !!exercise.title?.length && - this.TITLE_NAME_REGEX.test(exercise.title!) && + EXERCISE_TITLE_NAME_REGEX.test(exercise.title!) && !this.exercisesWithDuplicatedTitles.has(exercise.id!) && (exercise.title !== this.getBlocklistTitleOfProgrammingExercise(exercise.id!) || this.getBlocklistShortNameOfProgrammingExercise(exercise.id!) === '') ); diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts index 9dbd84f89209..764433e05c19 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.component.ts @@ -18,7 +18,7 @@ import { ProfileService } from 'app/shared/layouts/profiles/profile.service'; import { ExerciseGroupService } from 'app/exam/manage/exercise-groups/exercise-group.service'; import { ProgrammingLanguageFeatureService } from 'app/exercises/programming/shared/service/programming-language-feature/programming-language-feature.service'; import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils'; -import { SHORT_NAME_PATTERN, TITLE_NAME_PATTERN } from 'app/shared/constants/input.constants'; +import { EXERCISE_TITLE_NAME_PATTERN, EXERCISE_TITLE_NAME_REGEX, SHORT_NAME_PATTERN } from 'app/shared/constants/input.constants'; import { ExerciseCategory } from 'app/entities/exercise-category.model'; import { cloneDeep } from 'lodash-es'; import { ExerciseUpdateWarningService } from 'app/exercises/shared/exercise-update-warning/exercise-update-warning.service'; @@ -841,7 +841,7 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest translateKey: 'artemisApp.exercise.form.title.undefined', translateValues: {}, }); - } else if (this.programmingExercise.title.match(TITLE_NAME_PATTERN) === null || this.programmingExercise.title?.match(TITLE_NAME_PATTERN)?.length === 0) { + } else if (!EXERCISE_TITLE_NAME_REGEX.test(this.programmingExercise.title)) { validationErrorReasons.push({ translateKey: 'artemisApp.exercise.form.title.pattern', translateValues: {}, @@ -1061,7 +1061,7 @@ export class ProgrammingExerciseUpdateComponent implements AfterViewInit, OnDest customBuildPlansSupported: this.customBuildPlansSupported, invalidDirectoryNamePattern: this.invalidDirectoryNamePattern, invalidRepositoryNamePattern: this.invalidRepositoryNamePattern, - titleNamePattern: TITLE_NAME_PATTERN, + titleNamePattern: EXERCISE_TITLE_NAME_PATTERN, shortNamePattern: this.shortNamePattern, updateRepositoryName: this.updateRepositoryName, updateCheckoutDirectory: this.updateCheckoutDirectory, diff --git a/src/main/webapp/app/shared/constants/input.constants.ts b/src/main/webapp/app/shared/constants/input.constants.ts index 77707c350a90..8b97589a59d6 100644 --- a/src/main/webapp/app/shared/constants/input.constants.ts +++ b/src/main/webapp/app/shared/constants/input.constants.ts @@ -14,7 +14,8 @@ export const MAX_QUIZ_SHORT_ANSWER_TEXT_LENGTH = 255; // Must be consistent with /** Short names must start with a letter and cannot contain special characters **/ export const SHORT_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9]{2,}$/; /** Programming exercise titles must only contain alphanumeric characters, or whitespaces, or '_' or '-' **/ -export const TITLE_NAME_PATTERN = '^[a-zA-Z0-9-_ ]+'; +export const EXERCISE_TITLE_NAME_PATTERN = '^[a-zA-Z0-9-_ ]+'; +export const EXERCISE_TITLE_NAME_REGEX = new RegExp(EXERCISE_TITLE_NAME_PATTERN); /** Prefixes must follow the login pattern **/ export const LOGIN_PATTERN = /^[_'.@A-Za-z0-9-]*$/; export const MAX_QUIZ_QUESTION_POINTS = 9999; From c0000f7874f456989262f78afd40f465c4bf1739 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 15:31:19 +0200 Subject: [PATCH 054/117] Moving dto to entities folder --- src/main/webapp/app/detail-overview-list/detail.model.ts | 2 +- .../manage => entities}/build-log-statistics-dto.ts | 0 src/main/webapp/app/entities/programming-exercise.model.ts | 2 +- .../repositories-checkout-directories-dto.ts | 3 --- .../manage/programming-exercise-detail.component.ts | 2 +- .../manage/services/programming-exercise.service.ts | 4 ++-- ...mming-exercise-plans-and-repositories-preview.component.ts | 2 +- .../programming-exercise-detail.component.spec.ts | 2 +- ...-exercise-plans-and-repositories-preview.component.spec.ts | 2 +- 9 files changed, 8 insertions(+), 11 deletions(-) rename src/main/webapp/app/{exercises/programming/manage => entities}/build-log-statistics-dto.ts (100%) rename src/main/webapp/app/{exercises/programming/manage => entities}/repositories-checkout-directories-dto.ts (64%) diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index 5bf739f56353..f96feb9a7cef 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -6,7 +6,7 @@ import { ProgrammingExerciseInstructorRepositoryType } from 'app/exercises/progr import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; import { ProgrammingExerciseParticipationType } from 'app/entities/programming-exercise-participation.model'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/hestia/programming-exercise-git-diff-report.model'; -import { BuildLogStatisticsDTO } from 'app/exercises/programming/manage/build-log-statistics-dto'; +import { BuildLogStatisticsDTO } from 'app/entities/build-log-statistics-dto'; import { DetailType } from 'app/detail-overview-list/detail-overview-list.component'; import { SafeHtml } from '@angular/platform-browser'; import { UMLDiagramType, UMLModel } from '@ls1intum/apollon'; diff --git a/src/main/webapp/app/exercises/programming/manage/build-log-statistics-dto.ts b/src/main/webapp/app/entities/build-log-statistics-dto.ts similarity index 100% rename from src/main/webapp/app/exercises/programming/manage/build-log-statistics-dto.ts rename to src/main/webapp/app/entities/build-log-statistics-dto.ts diff --git a/src/main/webapp/app/entities/programming-exercise.model.ts b/src/main/webapp/app/entities/programming-exercise.model.ts index 653a6bfaf778..e14bc12a0beb 100644 --- a/src/main/webapp/app/entities/programming-exercise.model.ts +++ b/src/main/webapp/app/entities/programming-exercise.model.ts @@ -8,7 +8,7 @@ import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary import { SubmissionPolicy } from 'app/entities/submission-policy.model'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/hestia/programming-exercise-git-diff-report.model'; import { ExerciseHint } from 'app/entities/hestia/exercise-hint.model'; -import { BuildLogStatisticsDTO } from 'app/exercises/programming/manage/build-log-statistics-dto'; +import { BuildLogStatisticsDTO } from 'app/entities/build-log-statistics-dto'; export class BuildAction { name: string; diff --git a/src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts b/src/main/webapp/app/entities/repositories-checkout-directories-dto.ts similarity index 64% rename from src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts rename to src/main/webapp/app/entities/repositories-checkout-directories-dto.ts index 3ceb26cf94af..81d38004454b 100644 --- a/src/main/webapp/app/exercises/programming/manage/repositories-checkout-directories-dto.ts +++ b/src/main/webapp/app/entities/repositories-checkout-directories-dto.ts @@ -3,6 +3,3 @@ export class RepositoriesCheckoutDirectoriesDTO { solutionCheckoutDirectory?: string; testCheckoutDirectory?: string; } - -// TODO is the file placed correctly here? -// TODO is this how we define DTOs? read docs! diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index fdbc3382fa52..ace186598d81 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -56,7 +56,7 @@ import { IrisSubSettingsType } from 'app/entities/iris/settings/iris-sub-setting import { Detail } from 'app/detail-overview-list/detail.model'; import { Competency } from 'app/entities/competency.model'; import { AeolusService } from 'app/exercises/programming/shared/service/aeolus.service'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-detail', diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index 874d60543a31..3812f3c80cf9 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -20,13 +20,13 @@ import { ProgrammingExerciseServerSideTask } from 'app/entities/hestia/programmi import { convertDateFromClient, convertDateFromServer } from 'app/utils/date.utils'; import { ExerciseHint } from 'app/entities/hestia/exercise-hint.model'; import { ProgrammingExerciseTestCase } from 'app/entities/programming-exercise-test-case.model'; -import { BuildLogStatisticsDTO } from 'app/exercises/programming/manage/build-log-statistics-dto'; +import { BuildLogStatisticsDTO } from 'app/entities/build-log-statistics-dto'; import { SortService } from 'app/shared/service/sort.service'; import { Result } from 'app/entities/result.model'; import { Participation } from 'app/entities/participation/participation.model'; import { PlagiarismResultDTO } from 'app/exercises/shared/plagiarism/types/PlagiarismResultDTO'; import { ImportOptions } from 'app/types/programming-exercises'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; export type EntityResponseType = HttpResponse; diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index f05632a6a743..49160ee778e8 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -5,7 +5,7 @@ import { ProgrammingExerciseService } from 'app/exercises/programming/manage/ser import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-detail.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-detail.component.spec.ts index 18a788a09ab7..d92687f132e2 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-detail.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-detail.component.spec.ts @@ -24,7 +24,7 @@ import { LocalStorageService, SessionStorageService } from 'ngx-webstorage'; import { MockProgrammingExerciseGradingService } from '../../helpers/mocks/service/mock-programming-exercise-grading.service'; import { ProgrammingExerciseGitDiffReport } from 'app/entities/hestia/programming-exercise-git-diff-report.model'; import { ProgrammingExerciseSolutionEntry } from 'app/entities/hestia/programming-exercise-solution-entry.model'; -import { BuildLogStatisticsDTO } from 'app/exercises/programming/manage/build-log-statistics-dto'; +import { BuildLogStatisticsDTO } from 'app/entities/build-log-statistics-dto'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { HttpResponse } from '@angular/common/http'; diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 5f595428006b..356b19f205d5 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -2,7 +2,7 @@ import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exe import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/exercises/programming/manage/repositories-checkout-directories-dto'; +import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; From b484f477fab17c288bf0e24b468e658637dd4fc9 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 19 May 2024 15:47:07 +0200 Subject: [PATCH 055/117] Adhere to server guidelines #6 --- .../artemis/service/connectors/localci/LocalCIService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index aa810b52bfc6..5067e1804b79 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -39,8 +39,6 @@ public class LocalCIService extends AbstractContinuousIntegrationService { private static final Logger log = LoggerFactory.getLogger(LocalCIService.class); - private static final String ROOT_DIRECTORY = "/"; - private final BuildScriptProviderService buildScriptProviderService; private final AeolusTemplateService aeolusTemplateService; @@ -236,6 +234,7 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLangua } private String startPathWithRootDirectory(String checkoutDirectoryPath) { + final String ROOT_DIRECTORY = "/"; return checkoutDirectoryPath.startsWith(ROOT_DIRECTORY) ? checkoutDirectoryPath : ROOT_DIRECTORY + checkoutDirectoryPath; } } From 946a1699c8a00e4ddea25298da987e35eac7f502 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:31:42 +0200 Subject: [PATCH 056/117] Adjusting error message and adding javadoc to enum for template & submission build plan --- .../ci/ContinuousIntegrationService.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 03b666b7d4c3..6d4eff0e43b7 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -42,7 +42,7 @@ enum BuildStatus { * @param planKey the key of the plan * @param repositoryUri the URI of the assignment repository (used to separate between exercise and solution) * @param testRepositoryUri the URI of the test repository - * @param solutionRepositoryUri the URI of the solution repository. Only used for HASKELL exercises with checkoutSolutionRepository=true. Otherwise ignored. + * @param solutionRepositoryUri the URI of the solution repository. Only used for HASKELL exercises with checkoutSolutionRepository=true. Otherwise, ignored. */ void createBuildPlanForExercise(ProgrammingExercise exercise, String planKey, VcsRepositoryUri repositoryUri, VcsRepositoryUri testRepositoryUri, VcsRepositoryUri solutionRepositoryUri); @@ -125,7 +125,7 @@ String copyBuildPlan(ProgrammingExercise sourceExercise, String sourcePlanName, * Get the build artifact (JAR/WAR), if any, of the latest build * * @param participation participation for which to get the build artifact - * @return the binary build artifact. Typically a JAR/WAR ResponseEntity. + * @return the binary build artifact. Typically, a JAR/WAR ResponseEntity. */ ResponseEntity retrieveLatestArtifact(ProgrammingExerciseParticipation participation); @@ -235,11 +235,19 @@ public String forProgrammingLanguage(ProgrammingLanguage language) { }, SOLUTION { + /** + * @param language for which the checkout directory should be retrieved + * @return checkoutDirectory for the solution repository for the build execution of the template and student submissions + * @throws IllegalArgumentException if the solution is not checked out within the build process for the template or student submission + *

      + * Note: if the solution is not checked out during the submission build plan, it will be checked out + * in the assignment respective repository during the solution build + */ @Override public String forProgrammingLanguage(ProgrammingLanguage language) { return switch (language) { - case JAVA, PYTHON, C, KOTLIN, VHDL, ASSEMBLER, SWIFT, EMPTY -> "assignment"; case HASKELL, OCAML -> "solution"; + default -> throw new IllegalArgumentException("The solution repository is not checked out during the template or student submission for " + language); }; } } From d16ca1ef1962e8ae992dcf28d90e2b24a1e42757 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:38:25 +0200 Subject: [PATCH 057/117] Adjusting endpoint to only returning the template & submission build plan --- .../ci/ContinuousIntegrationService.java | 2 +- .../connectors/gitlabci/GitLabCIService.java | 2 +- .../service/connectors/jenkins/JenkinsService.java | 2 +- .../service/connectors/localci/LocalCIService.java | 14 ++++++++++---- .../programming/ProgrammingExerciseResource.java | 3 ++- .../www1/artemis/localvcci/LocalCIServiceTest.java | 6 +++--- 6 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 6d4eff0e43b7..a8cb8c3f0a5c 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -271,5 +271,5 @@ interface CustomizableCheckoutPath { * @param programmingLanguage for which the checkout directories should be retrieved * @return the paths of the checkout directories for the default repositories */ - RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage); + RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage); } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index 3f6ce783e766..5c02ad8cef69 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -326,7 +326,7 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index a14a7c94bf9b..86542f102152 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -257,7 +257,7 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index 5067e1804b79..bc45b597ec30 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -221,15 +221,21 @@ private String getCleanPlanName(String name) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); - String solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); - exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); - solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); + String solutionCheckoutDirectory = ""; + try { + solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); + } + catch (Exception e) { + // not checked out during template & submission build + } + return new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); } diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index a7df003e4f19..0646d2c1f814 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -890,7 +890,8 @@ public ResponseEntity getBuildLogStatistics(@PathVariable public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); - RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow().getCheckoutDirectories(programmingLanguage); + RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow() + .getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(programmingLanguage); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } } diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 2925c1675a12..9b836c08d87b 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -178,15 +178,15 @@ class GetCheckoutDirectoriesTests { @Test void getCheckoutDirectoriesForJava() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.JAVA); + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.JAVA); assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo(""); assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); } @Test void getCheckoutDirectoriesForOcaml() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML); + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.OCAML); assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/solution"); assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); From 9ec3615ad046c3afdba9b738c7a25f6b90bb877a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:41:55 +0200 Subject: [PATCH 058/117] Adjusting javadoc --- .../connectors/ci/ContinuousIntegrationService.java | 7 ++++--- .../service/connectors/gitlabci/GitLabCIService.java | 2 +- .../artemis/service/connectors/jenkins/JenkinsService.java | 2 +- .../artemis/service/connectors/localci/LocalCIService.java | 2 +- .../web/rest/programming/ProgrammingExerciseResource.java | 2 +- .../tum/in/www1/artemis/localvcci/LocalCIServiceTest.java | 6 ++++-- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index a8cb8c3f0a5c..9140067674a9 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -266,10 +266,11 @@ interface CustomizableCheckoutPath { } /** - * Get the checkout directories for the default repositories (exercise, solution, test) for a given programming language. + * Get the checkout directories for the template and submission build plan for a given programming language. * * @param programmingLanguage for which the checkout directories should be retrieved - * @return the paths of the checkout directories for the default repositories + * @return the paths of the checkout directories for the default repositories (exercise, solution, tests) for the + * template and submission build plan */ - RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage); + RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage); } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index 5c02ad8cef69..24dfae5316b6 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -326,7 +326,7 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index 86542f102152..1ad361fc7d47 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -257,7 +257,7 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index bc45b597ec30..b1a4f58cf9c8 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -221,7 +221,7 @@ private String getCleanPlanName(String name) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 0646d2c1f814..73a833b1c867 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -891,7 +891,7 @@ public ResponseEntity getRepositoryCheckoutDir log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow() - .getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(programmingLanguage); + .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(programmingLanguage); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } } diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 9b836c08d87b..4e13d91995bc 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -178,7 +178,8 @@ class GetCheckoutDirectoriesTests { @Test void getCheckoutDirectoriesForJava() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.JAVA); + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService + .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.JAVA); assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo(""); assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); @@ -186,7 +187,8 @@ void getCheckoutDirectoriesForJava() { @Test void getCheckoutDirectoriesForOcaml() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectoriesForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.OCAML); + RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService + .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.OCAML); assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/solution"); assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); From 6549a4ddb5862ca8b868bc93d7de808a96f315cb Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:45:06 +0200 Subject: [PATCH 059/117] Simplify null checks --- .../manage/programming-exercise-detail.component.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index ace186598d81..a86273012eca 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -193,22 +193,14 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { this.loadingSolutionParticipationResults = false; this.profileInfoSubscription = this.profileService.getProfileInfo().subscribe(async (profileInfo) => { if (profileInfo) { - if ( - this.programmingExercise.projectKey && - this.programmingExercise.templateParticipation && - this.programmingExercise.templateParticipation.buildPlanId - ) { + if (this.programmingExercise.projectKey && this.programmingExercise.templateParticipation?.buildPlanId) { this.programmingExercise.templateParticipation.buildPlanUrl = createBuildPlanUrl( profileInfo.buildPlanURLTemplate, this.programmingExercise.projectKey, this.programmingExercise.templateParticipation.buildPlanId, ); } - if ( - this.programmingExercise.projectKey && - this.programmingExercise.solutionParticipation && - this.programmingExercise.solutionParticipation.buildPlanId - ) { + if (this.programmingExercise.projectKey && this.programmingExercise.solutionParticipation?.buildPlanId) { this.programmingExercise.solutionParticipation.buildPlanUrl = createBuildPlanUrl( profileInfo.buildPlanURLTemplate, this.programmingExercise.projectKey, From 0d7b7a3de01677f7283dd8576916dd0f63ad9894 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:46:38 +0200 Subject: [PATCH 060/117] Build Execution vs. build execution --- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 07738ec02710..4040d6426f21 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -437,7 +437,7 @@ "preview": { "label": "Preview", "tooltip": "For every programming exercise, repositories and build plans will be generated. Here, you can find their generated names based on the short name of the exercise (and course)", - "tooltipLocalVC": "Here, you can find the repositories linked to the exercise and their respective checkout directories during the Build Execution.", + "tooltipLocalVC": "Here, you can find the repositories linked to the exercise and their respective checkout directories during the build execution.", "repositories": "Repositories", "buildPlans": "Build Plans", "templateRepoTooltip": "The repository which contains the template of the exercise", From a2c21dab03e369f7f078186d4a1d1849bfe71de3 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:48:00 +0200 Subject: [PATCH 061/117] Simplify null check --- ...-exercise-plans-and-repositories-preview.component.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 49160ee778e8..026d9e6ccaaf 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -62,12 +62,9 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements if ( this.isLocal && - this.programmingExerciseCreationConfig && - this.programmingExerciseCreationConfig.selectedProgrammingLanguage && - changes.programmingExerciseCreationConfig && - changes.programmingExerciseCreationConfig.currentValue && - changes.programmingExerciseCreationConfig.currentValue.selectedProgrammingLanguage !== - changes.programmingExerciseCreationConfig.previousValue?.selectedProgrammingLanguage + this.programmingExerciseCreationConfig?.selectedProgrammingLanguage && + changes.programmingExerciseCreationConfig?.currentValue?.selectedProgrammingLanguage !== + changes.programmingExerciseCreationConfig?.previousValue?.selectedProgrammingLanguage ) { this.updateCheckoutDirectories(); } From 37316d0d4bfdd98d4797a62fcd35c12c634e2c4b Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:49:58 +0200 Subject: [PATCH 062/117] Build Execution vs build execution --- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 4040d6426f21..233a7918582c 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -446,7 +446,7 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "The build plan of the template. Runs all tests on the exercise template. Used as a reference in which all tests must fail", "solutionBuildPlanTooltip": "The build plan of the solution. Runs all tests on the exercise solution. Used as a reference in which all tests must succeed", - "checkoutDirectoryDuringBuildExecution": "Checkout Directory during Build Execution" + "checkoutDirectoryDuringBuildExecution": "Checkout Directory during build execution" }, "orion": { "openEditor": "Open Editor" From 658091736b06bfce69deba664c0cc914b02be22c Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 14:53:03 +0200 Subject: [PATCH 063/117] Do not add leading slash for loaded checkout directories from server --- .../services/programming-exercise.service.ts | 20 +++++-------------- ...lans-and-repositories-preview.component.ts | 13 ++++++++++-- src/main/webapp/app/shared/util/utils.ts | 10 ---------- 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index 3812f3c80cf9..ebf2b03ba1d9 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -27,7 +27,6 @@ import { Participation } from 'app/entities/participation/participation.model'; import { PlagiarismResultDTO } from 'app/exercises/shared/plagiarism/types/PlagiarismResultDTO'; import { ImportOptions } from 'app/types/programming-exercises'; import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; -import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; export type EntityResponseType = HttpResponse; export type EntityArrayResponseType = HttpResponse; @@ -677,19 +676,10 @@ export class ProgrammingExerciseService { } getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { - return this.http - .get(`${this.resourceUrl}/repository-checkout-directories`, { - params: { - programmingLanguage, - }, - }) - .pipe( - map((checkoutDirectories: RepositoriesCheckoutDirectoriesDTO) => { - checkoutDirectories.exerciseCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.exerciseCheckoutDirectory); - checkoutDirectories.solutionCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.solutionCheckoutDirectory); - checkoutDirectories.testCheckoutDirectory = addLeadingSlashIfNotPresent(checkoutDirectories.testCheckoutDirectory); - return checkoutDirectories; - }), - ); + return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { + params: { + programmingLanguage, + }, + }); } } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 026d9e6ccaaf..474583cbaf53 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -4,7 +4,6 @@ import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; -import { addLeadingSlashIfNotPresent } from 'app/shared/util/utils'; import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; @Component({ @@ -36,7 +35,17 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements private updateAuxiliaryRepositoryCheckoutDirectories() { this.auxiliaryRepositoryCheckoutDirectories = - this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; + this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; + } + + private addLeadingSlashIfNotPresent(directory: string | undefined): string { + const ROOT_DIRECTORY_PATH: string = '/'; + + if (!directory) { + return ROOT_DIRECTORY_PATH; + } + + return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; } private updateShortName() { diff --git a/src/main/webapp/app/shared/util/utils.ts b/src/main/webapp/app/shared/util/utils.ts index 522cf1d9dd8e..0a87dd8c8efd 100644 --- a/src/main/webapp/app/shared/util/utils.ts +++ b/src/main/webapp/app/shared/util/utils.ts @@ -176,13 +176,3 @@ export function scrollToTopOfPage() { export function isExamExercise(exercise: Exercise) { return exercise.course === undefined; } - -const ROOT_DIRECTORY_PATH: string = '/'; - -export function addLeadingSlashIfNotPresent(directory: string | undefined): string { - if (!directory) { - return ROOT_DIRECTORY_PATH; - } - - return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; -} From b7431d458d5997e345eac0bf8f3f6ce6c7df738d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 15:04:50 +0200 Subject: [PATCH 064/117] Do not display a checkout directory if the solution is not checked out --- ...mming-exercise-plans-and-repositories-preview.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index a4004126424a..bff1680f6b53 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -62,7 +62,7 @@

    • {{ checkoutDirectories.exerciseCheckoutDirectory }}
    • -
    • +
    • {{ checkoutDirectories.solutionCheckoutDirectory }}
    • From 72f181619545af8b4984ca1e84e269f6c1d21069 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 15:15:18 +0200 Subject: [PATCH 065/117] Adding tooltip and hiding solution --- ...ming-exercise-plans-and-repositories-preview.component.html | 1 + src/main/webapp/i18n/de/programmingExercise.json | 3 ++- src/main/webapp/i18n/en/programmingExercise.json | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index bff1680f6b53..d12d36eb105e 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -56,6 +56,7 @@
      +

        diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 700354b8bb01..76fbc700c04a 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -446,7 +446,8 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "Der Build-Plan der Vorlage. Lässt alle Tests über die Vorlage der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests fehlschlagen müssen", "solutionBuildPlanTooltip": "Der Build-Plan der Lösung der Aufgabe. Lässt alle Tests über die Lösung der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests erfolgreich sein müssen", - "checkoutDirectoryDuringBuildExecution": "Checkout-Verzeichnis während der Build-Ausführung" + "checkoutDirectoryDuringBuildExecution": "Checkout-Verzeichnis während der Build-Ausführung", + "checkoutDirectoryDuringBuildExecutionTooltip": "Zeigt die Checkout-Verzeichnisse für Abgaben und Template-Repositories während der Build-Ausführung an. Der Lösungs-Build-Plan betrachtet die Lösung als Abgabe." }, "orion": { "openEditor": "Editor Öffnen" diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 233a7918582c..dc42d0645ab2 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -446,7 +446,8 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "The build plan of the template. Runs all tests on the exercise template. Used as a reference in which all tests must fail", "solutionBuildPlanTooltip": "The build plan of the solution. Runs all tests on the exercise solution. Used as a reference in which all tests must succeed", - "checkoutDirectoryDuringBuildExecution": "Checkout Directory during build execution" + "checkoutDirectoryDuringBuildExecution": "Checkout Directory during build execution", + "checkoutDirectoryDuringBuildExecutionTooltip": "Displays the checkout directories for submissions and the exercise template during the build execution. The solution build plan will consider the solution as a submission." }, "orion": { "openEditor": "Open Editor" From 415bd6431f16c2ddd99a2d90852ef822ed0947bd Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 19:43:02 +0200 Subject: [PATCH 066/117] Don't display the checkout directories for tutors --- .../detail-overview-list.component.html | 13 ++++++--- .../app/detail-overview-list/detail.model.ts | 2 ++ .../programming-exercise-detail.component.ts | 27 +++++++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 2af61331eb94..a799464c6c6a 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -76,10 +76,15 @@

        {{ section }

      -
      - : - {{ detail.data.checkoutDirectory }} -
      + @if (isLocalVC && detail.data.isAtLeastEditor) { +
      + : + {{ detail.data.checkoutDirectory }} + @if (!detail.data.isCheckoutDirectoryForSubmissionAndTemplateBuild) { + + } +
      + } } @else { } diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index f96feb9a7cef..051064f8bcc9 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -94,6 +94,8 @@ interface ProgrammingRepositoryButtonsDetail extends DetailBase { showOpenLink?: boolean; type: ProgrammingExerciseInstructorRepositoryType; checkoutDirectory?: string; + isCheckoutDirectoryForSubmissionAndTemplateBuild?: boolean; + isAtLeastEditor?: boolean; }; } diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index a86273012eca..4aa6eecb508b 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -250,7 +250,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { this.exerciseDetailSections = this.getExerciseDetails(); }); - if (this.programmingExercise.programmingLanguage) { + if (programmingExercise.isAtLeastEditor && this.programmingExercise.programmingLanguage) { this.checkoutDirectoriesSubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage) .subscribe((checkoutDirectories) => { @@ -377,6 +377,8 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { type: 'TEMPLATE', showOpenLink: !this.localVCEnabled, checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.exerciseCheckoutDirectory : undefined, + isCheckoutDirectoryForSubmissionAndTemplateBuild: true, + isAtLeastEditor: exercise.isAtLeastEditor, }, }, { @@ -387,7 +389,9 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'SOLUTION', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.solutionCheckoutDirectory : undefined, + checkoutDirectory: this.localVCEnabled ? this.getSolutionCheckoutDirectory().checkoutDirectory : undefined, + isCheckoutDirectoryForSubmissionAndTemplateBuild: this.getSolutionCheckoutDirectory().isCheckoutDirectoryForSubmissionAndTemplateBuild, + isAtLeastEditor: exercise.isAtLeastEditor, }, }, { @@ -399,6 +403,8 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { type: 'TESTS', showOpenLink: !this.localVCEnabled, checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.testCheckoutDirectory : undefined, + isCheckoutDirectoryForSubmissionAndTemplateBuild: true, + isAtLeastEditor: exercise.isAtLeastEditor, }, }, this.supportsAuxiliaryRepositories && @@ -729,6 +735,23 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { }); } + private getSolutionCheckoutDirectory(): { + checkoutDirectory: string; + isCheckoutDirectoryForSubmissionAndTemplateBuild: boolean; + } { + if (this.checkoutDirectories?.solutionCheckoutDirectory) { + return { + checkoutDirectory: this.checkoutDirectories.solutionCheckoutDirectory, + isCheckoutDirectoryForSubmissionAndTemplateBuild: true, + }; + } + + return { + checkoutDirectory: this.checkoutDirectories?.exerciseCheckoutDirectory ?? '', + isCheckoutDirectoryForSubmissionAndTemplateBuild: false, + }; + } + /** * Opens modal and executes a consistency check for the given programming exercise * @param exercise the programming exercise to check From bcf94bce358aa8803768185cdaa236855d368916 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 19:50:33 +0200 Subject: [PATCH 067/117] Access right from TA to EDITOR, adjust test --- .../web/rest/programming/ProgrammingExerciseResource.java | 2 +- .../ProgrammingExerciseLocalVCLocalCIIntegrationTest.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 73a833b1c867..5542de68668d 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -885,7 +885,7 @@ public ResponseEntity getBuildLogStatistics(@PathVariable * @return a DTO containing the checkout directories for the exercise, solution, and test repository for the requested programming language. */ @GetMapping("programming-exercises/repository-checkout-directories") - @EnforceAtLeastTutor + @EnforceAtLeastEditor @FeatureToggle(Feature.ProgrammingExercises) public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index ac4c6ca55741..d77d91c00f21 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -67,7 +67,7 @@ class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringInt @BeforeEach void setup() throws Exception { - userUtilService.addUsers(TEST_PREFIX, 1, 1, 0, 1); + userUtilService.addUsers(TEST_PREFIX, 1, 1, 1, 1); course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); programmingExercise = exerciseUtilService.getFirstExerciseWithType(course, ProgrammingExercise.class); @@ -242,17 +242,17 @@ void testImportProgrammingExercise() throws Exception { } @Test - @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") + @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") void testGetCheckoutDirectories() throws Exception { RepositoriesCheckoutDirectoryDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, RepositoriesCheckoutDirectoryDTO.class); assertThat(checkoutDirectoryDTO.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectoryDTO.solutionCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectoryDTO.solutionCheckoutDirectory()).isNull(); assertThat(checkoutDirectoryDTO.testCheckoutDirectory()).isEqualTo("/"); } @Test - @WithMockUser(username = TEST_PREFIX + "student1", roles = "STUDENT") + @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") void testGetCheckoutDirectoriesAccessForbidden() throws Exception { request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, RepositoriesCheckoutDirectoryDTO.class); } From 5aaa353c4133b46a9fe5a0f788975c5d6a0eff57 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 20:24:16 +0200 Subject: [PATCH 068/117] Catch specific Exception and handle null --- .../artemis/service/connectors/localci/LocalCIService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index b1a4f58cf9c8..bb5891f2d696 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -232,7 +232,7 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndS solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); } - catch (Exception e) { + catch (UnsupportedOperationException e) { // not checked out during template & submission build } @@ -241,6 +241,10 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndS private String startPathWithRootDirectory(String checkoutDirectoryPath) { final String ROOT_DIRECTORY = "/"; + if (checkoutDirectoryPath == null || checkoutDirectoryPath.isEmpty()) { + return ROOT_DIRECTORY; + } + return checkoutDirectoryPath.startsWith(ROOT_DIRECTORY) ? checkoutDirectoryPath : ROOT_DIRECTORY + checkoutDirectoryPath; } } From faa379545cfc88bf448bc2408e7c7bb38d7b052c Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 21:43:10 +0200 Subject: [PATCH 069/117] Catching actual error message --- .../www1/artemis/service/connectors/localci/LocalCIService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index bb5891f2d696..f85e4b597a3a 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -232,7 +232,7 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndS solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); } - catch (UnsupportedOperationException e) { + catch (IllegalArgumentException exception) { // not checked out during template & submission build } From 67757fbb3e6af93b59d9d2545f52e9ca16f15453 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 20 May 2024 21:43:51 +0200 Subject: [PATCH 070/117] Using translation --- ...mming-exercise-plans-and-repositories-preview.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index d12d36eb105e..ec9b3fa39966 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -56,7 +56,7 @@
      - +

        From 07dce475bb55290e31d94b33c7be277d7a108490 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 21 May 2024 15:28:30 +0200 Subject: [PATCH 071/117] Using translation --- .../detail-overview-list/detail-overview-list.component.html | 2 +- src/main/webapp/i18n/de/programmingExercise.json | 1 + src/main/webapp/i18n/en/programmingExercise.json | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index a799464c6c6a..278f1cdc88e7 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -81,7 +81,7 @@

        {{ section : {{ detail.data.checkoutDirectory }} @if (!detail.data.isCheckoutDirectoryForSubmissionAndTemplateBuild) { - + }

      } diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 76fbc700c04a..aa952a601f73 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -449,6 +449,7 @@ "checkoutDirectoryDuringBuildExecution": "Checkout-Verzeichnis während der Build-Ausführung", "checkoutDirectoryDuringBuildExecutionTooltip": "Zeigt die Checkout-Verzeichnisse für Abgaben und Template-Repositories während der Build-Ausführung an. Der Lösungs-Build-Plan betrachtet die Lösung als Abgabe." }, + "solutionCheckoutDirectoryDuringBuildExecutionTooltip": "Das Lösungs-Repository wird nicht während des Template-Builds ausgecheckt. Das Lösungs-Repository wird nur während des Lösungs-Builds ausgecheckt.", "orion": { "openEditor": "Editor Öffnen" }, diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index dc42d0645ab2..c62a2d3de5da 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -449,6 +449,7 @@ "checkoutDirectoryDuringBuildExecution": "Checkout Directory during build execution", "checkoutDirectoryDuringBuildExecutionTooltip": "Displays the checkout directories for submissions and the exercise template during the build execution. The solution build plan will consider the solution as a submission." }, + "solutionCheckoutDirectoryDuringBuildExecutionTooltip": "The solution repository will not be checked out during the submission and exercise template build. The repository will only be checked out during the solution build.", "orion": { "openEditor": "Open Editor" }, From a22862869154a18d5378c164a0a69b40e45355ce Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 22 May 2024 11:28:14 +0200 Subject: [PATCH 072/117] Adjusting endpoint to return checkout directories for exercise and solution build plan --- .../ci/ContinuousIntegrationService.java | 4 +- .../connectors/gitlabci/GitLabCIService.java | 4 +- .../connectors/jenkins/JenkinsService.java | 4 +- .../connectors/localci/LocalCIService.java | 28 ++++++++++++-- .../dto/BuildPlanCheckoutDirectoriesDTO.java | 8 ++++ .../web/rest/dto/CheckoutDirectoriesDTO.java | 7 ++++ .../dto/RepositoriesCheckoutDirectoryDTO.java | 8 ---- .../ProgrammingExerciseResource.java | 12 +++--- ...ExerciseLocalVCLocalCIIntegrationTest.java | 10 ++--- .../artemis/localvcci/LocalCIServiceTest.java | 37 ++++++++++--------- 10 files changed, 76 insertions(+), 46 deletions(-) create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java create mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoriesDTO.java delete mode 100644 src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 9140067674a9..32cfb407b581 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -17,7 +17,7 @@ import de.tum.in.www1.artemis.domain.participation.ProgrammingExerciseParticipation; import de.tum.in.www1.artemis.exception.ContinuousIntegrationException; import de.tum.in.www1.artemis.service.connectors.ConnectorHealth; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; /** * Abstract service for managing entities related to continuous integration. @@ -272,5 +272,5 @@ interface CustomizableCheckoutPath { * @return the paths of the checkout directories for the default repositories (exercise, solution, tests) for the * template and submission build plan */ - RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage); + CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage); } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index 24dfae5316b6..66152552c1a4 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -38,7 +38,7 @@ import de.tum.in.www1.artemis.service.connectors.ci.AbstractContinuousIntegrationService; import de.tum.in.www1.artemis.service.connectors.ci.CIPermission; import de.tum.in.www1.artemis.service.connectors.ci.notification.dto.TestResultsDTO; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; @Profile("gitlabci") @Service @@ -326,7 +326,7 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index 1ad361fc7d47..c595d8086bea 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -37,7 +37,7 @@ import de.tum.in.www1.artemis.service.connectors.ci.notification.dto.TestResultsDTO; import de.tum.in.www1.artemis.service.connectors.jenkins.build_plan.JenkinsBuildPlanService; import de.tum.in.www1.artemis.service.connectors.jenkins.jobs.JenkinsJobService; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; @Profile("jenkins") @Service @@ -257,7 +257,7 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index f85e4b597a3a..02b1cd397761 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; +import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -26,7 +27,8 @@ import de.tum.in.www1.artemis.service.connectors.ci.AbstractContinuousIntegrationService; import de.tum.in.www1.artemis.service.connectors.ci.CIPermission; import de.tum.in.www1.artemis.service.connectors.ci.ContinuousIntegrationService; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.BuildPlanCheckoutDirectoriesDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; /** * Implementation of ContinuousIntegrationService for local CI. Contains methods for communication with the local CI system. @@ -221,9 +223,17 @@ private String getCleanPlanName(String name) { } @Override - public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage programmingLanguage) { + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories = getSubmissionBuildPlanCheckoutDirectories(programmingLanguage); + BuildPlanCheckoutDirectoriesDTO solutionBuildPlanCheckoutDirectories = getSolutionBuildPlanCheckoutDirectories(submissionBuildPlanCheckoutDirectories); + + return new CheckoutDirectoriesDTO(submissionBuildPlanCheckoutDirectories, solutionBuildPlanCheckoutDirectories); + } + + private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectories(ProgrammingLanguage programmingLanguage) { String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); + exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); @@ -236,7 +246,9 @@ public RepositoriesCheckoutDirectoryDTO getCheckoutDirectoryPathsForTemplateAndS // not checked out during template & submission build } - return new RepositoriesCheckoutDirectoryDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); + String[] solutionCheckoutDirectories = new String[] { solutionCheckoutDirectory }; + + return new BuildPlanCheckoutDirectoriesDTO(exerciseCheckoutDirectory, solutionCheckoutDirectories, testCheckoutDirectory); } private String startPathWithRootDirectory(String checkoutDirectoryPath) { @@ -247,4 +259,14 @@ private String startPathWithRootDirectory(String checkoutDirectoryPath) { return checkoutDirectoryPath.startsWith(ROOT_DIRECTORY) ? checkoutDirectoryPath : ROOT_DIRECTORY + checkoutDirectoryPath; } + + private BuildPlanCheckoutDirectoriesDTO getSolutionBuildPlanCheckoutDirectories(BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories) { + String[] solutionCheckoutDirectories = new String[] { submissionBuildPlanCheckoutDirectories.exerciseCheckoutDirectory() }; + if (submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories() != null && submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories().length > 0) { + solutionCheckoutDirectories = ArrayUtils.addAll(solutionCheckoutDirectories, submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories()); + } + String testCheckoutDirectory = submissionBuildPlanCheckoutDirectories.testCheckoutDirectory(); + + return new BuildPlanCheckoutDirectoriesDTO(null, solutionCheckoutDirectories, testCheckoutDirectory); + } } diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java new file mode 100644 index 000000000000..983238158e26 --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java @@ -0,0 +1,8 @@ +package de.tum.in.www1.artemis.web.rest.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record BuildPlanCheckoutDirectoriesDTO(String exerciseCheckoutDirectory, String[] solutionCheckoutDirectories, String testCheckoutDirectory) { + +} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoriesDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoriesDTO.java new file mode 100644 index 000000000000..8cd4f34f434e --- /dev/null +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/CheckoutDirectoriesDTO.java @@ -0,0 +1,7 @@ +package de.tum.in.www1.artemis.web.rest.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public record CheckoutDirectoriesDTO(BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories, BuildPlanCheckoutDirectoriesDTO solutionBuildPlanCheckoutDirectories) { +} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java deleted file mode 100644 index 5b4ca1e4ec5b..000000000000 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/RepositoriesCheckoutDirectoryDTO.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.tum.in.www1.artemis.web.rest.dto; - -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonInclude(JsonInclude.Include.NON_EMPTY) -public record RepositoriesCheckoutDirectoryDTO(String exerciseCheckoutDirectory, String solutionCheckoutDirectory, String testCheckoutDirectory) { - -} diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 5542de68668d..985ab7367002 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -81,8 +81,8 @@ import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseService; import de.tum.in.www1.artemis.service.programming.ProgrammingExerciseTestCaseService; import de.tum.in.www1.artemis.web.rest.dto.BuildLogStatisticsDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; import de.tum.in.www1.artemis.web.rest.dto.ProgrammingExerciseResetOptionsDTO; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; import de.tum.in.www1.artemis.web.rest.dto.SearchResultPageDTO; import de.tum.in.www1.artemis.web.rest.dto.pageablesearch.SearchTermPageableSearchDTO; import de.tum.in.www1.artemis.web.rest.errors.BadRequestAlertException; @@ -880,18 +880,18 @@ public ResponseEntity getBuildLogStatistics(@PathVariable } /** - * GET programming-exercises/checkout-directories + * GET programming-exercises/repository-checkout-directories * - * @return a DTO containing the checkout directories for the exercise, solution, and test repository for the requested programming language. + * @return a DTO containing the checkout directories for the exercise, solution, and tests repository + * for the requested programming language for the submission and solution build. */ @GetMapping("programming-exercises/repository-checkout-directories") @EnforceAtLeastEditor @FeatureToggle(Feature.ProgrammingExercises) - public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { + public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); - RepositoriesCheckoutDirectoryDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow() - .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(programmingLanguage); + CheckoutDirectoriesDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow().getCheckoutDirectories(programmingLanguage); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } } diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index d77d91c00f21..4456792671ce 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -32,7 +32,7 @@ import de.tum.in.www1.artemis.participation.ParticipationUtilService; import de.tum.in.www1.artemis.service.connectors.localvc.LocalVCRepositoryUri; import de.tum.in.www1.artemis.util.LocalRepository; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; +import de.tum.in.www1.artemis.web.rest.dto.BuildPlanCheckoutDirectoriesDTO; class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -244,16 +244,16 @@ void testImportProgrammingExercise() throws Exception { @Test @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") void testGetCheckoutDirectories() throws Exception { - RepositoriesCheckoutDirectoryDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, - RepositoriesCheckoutDirectoryDTO.class); + BuildPlanCheckoutDirectoriesDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, + BuildPlanCheckoutDirectoriesDTO.class); assertThat(checkoutDirectoryDTO.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectoryDTO.solutionCheckoutDirectory()).isNull(); + assertThat(checkoutDirectoryDTO.solutionCheckoutDirectories()).isNull(); assertThat(checkoutDirectoryDTO.testCheckoutDirectory()).isEqualTo("/"); } @Test @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") void testGetCheckoutDirectoriesAccessForbidden() throws Exception { - request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, RepositoriesCheckoutDirectoryDTO.class); + request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, BuildPlanCheckoutDirectoriesDTO.class); } } diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 4e13d91995bc..5a2e6f4afa41 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -40,7 +40,6 @@ import de.tum.in.www1.artemis.service.connectors.localci.dto.JobTimingInfo; import de.tum.in.www1.artemis.service.connectors.localci.dto.LocalCIBuildJobQueueItem; import de.tum.in.www1.artemis.service.connectors.localci.dto.RepositoryInfo; -import de.tum.in.www1.artemis.web.rest.dto.RepositoriesCheckoutDirectoryDTO; class LocalCIServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -176,23 +175,25 @@ void testUnsupportedMethods() { @Nested class GetCheckoutDirectoriesTests { - @Test - void getCheckoutDirectoriesForJava() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService - .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.JAVA); - assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo(""); - assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); - } - - @Test - void getCheckoutDirectoriesForOcaml() { - RepositoriesCheckoutDirectoryDTO checkoutDirectories = continuousIntegrationService - .getCheckoutDirectoryPathsForTemplateAndSubmissionBuildPlan(ProgrammingLanguage.OCAML); - assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.solutionCheckoutDirectory()).isEqualTo("/solution"); - assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); - } + // TODO adjust tests + + // @Test + // void getCheckoutDirectoriesForJava() { + // BuildPlanCheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService + // .getCheckoutDirectories(ProgrammingLanguage.JAVA); + // assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); + // assertThat(checkoutDirectories.solutionCheckoutDirectories()).isEqualTo(""); + // assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); + // } + // + // @Test + // void getCheckoutDirectoriesForOcaml() { + // BuildPlanCheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService + // .getCheckoutDirectories(ProgrammingLanguage.OCAML); + // assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); + // assertThat(checkoutDirectories.solutionCheckoutDirectories()).isEqualTo("/solution"); + // assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); + // } } } From 313ca54250497c96efc5178f620dc029bec7a3e0 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 22 May 2024 14:11:54 +0200 Subject: [PATCH 073/117] Returning null if solution repository is not checked out --- .../service/connectors/localci/LocalCIService.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index 02b1cd397761..9dcc84f9ee3a 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -237,17 +237,15 @@ private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectorie exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); - String solutionCheckoutDirectory = ""; + String[] solutionCheckoutDirectories = null; try { - solutionCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectory); + String solutionCheckoutDirectoryPath = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + solutionCheckoutDirectories = new String[] { startPathWithRootDirectory(solutionCheckoutDirectoryPath) }; } catch (IllegalArgumentException exception) { // not checked out during template & submission build } - String[] solutionCheckoutDirectories = new String[] { solutionCheckoutDirectory }; - return new BuildPlanCheckoutDirectoriesDTO(exerciseCheckoutDirectory, solutionCheckoutDirectories, testCheckoutDirectory); } From 9f7fb9fb7ca973a236e98bc2de2a549840ed7dfa Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 22 May 2024 14:20:14 +0200 Subject: [PATCH 074/117] Adjusting Tests to returning checkout directories --- .../artemis/localvcci/LocalCIServiceTest.java | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 5a2e6f4afa41..c494f719fb95 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -40,6 +40,7 @@ import de.tum.in.www1.artemis.service.connectors.localci.dto.JobTimingInfo; import de.tum.in.www1.artemis.service.connectors.localci.dto.LocalCIBuildJobQueueItem; import de.tum.in.www1.artemis.service.connectors.localci.dto.RepositoryInfo; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; class LocalCIServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -175,25 +176,34 @@ void testUnsupportedMethods() { @Nested class GetCheckoutDirectoriesTests { - // TODO adjust tests - - // @Test - // void getCheckoutDirectoriesForJava() { - // BuildPlanCheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService - // .getCheckoutDirectories(ProgrammingLanguage.JAVA); - // assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - // assertThat(checkoutDirectories.solutionCheckoutDirectories()).isEqualTo(""); - // assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/"); - // } - // - // @Test - // void getCheckoutDirectoriesForOcaml() { - // BuildPlanCheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService - // .getCheckoutDirectories(ProgrammingLanguage.OCAML); - // assertThat(checkoutDirectories.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - // assertThat(checkoutDirectories.solutionCheckoutDirectories()).isEqualTo("/solution"); - // assertThat(checkoutDirectories.testCheckoutDirectory()).isEqualTo("/tests"); - // } + @Test + void getCheckoutDirectoriesForJava() { + CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.JAVA); + + // Verify submission build plan checkout directories + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); + + // Verify solution build plan checkout directories + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); + } + + @Test + void getCheckoutDirectoriesForOcaml() { + CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML); + + // Verify submission build plan checkout directories + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/solution" }); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); + + // Verify solution build plan checkout directories + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment", "/solution" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); + } } - } From cc7443fc6eb7850e1a265b4e5b06889a131bf5a6 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 22 May 2024 14:24:29 +0200 Subject: [PATCH 075/117] Adjusting Tests to returning checkout directories --- ...ExerciseLocalVCLocalCIIntegrationTest.java | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index 4456792671ce..140fd7044e7b 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -32,7 +33,7 @@ import de.tum.in.www1.artemis.participation.ParticipationUtilService; import de.tum.in.www1.artemis.service.connectors.localvc.LocalVCRepositoryUri; import de.tum.in.www1.artemis.util.LocalRepository; -import de.tum.in.www1.artemis.web.rest.dto.BuildPlanCheckoutDirectoriesDTO; +import de.tum.in.www1.artemis.web.rest.dto.CheckoutDirectoriesDTO; class ProgrammingExerciseLocalVCLocalCIIntegrationTest extends AbstractSpringIntegrationLocalCILocalVCTest { @@ -241,19 +242,33 @@ void testImportProgrammingExercise() throws Exception { localVCLocalCITestService.testLatestSubmission(solutionParticipation.getId(), null, 13, false); } - @Test - @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") - void testGetCheckoutDirectories() throws Exception { - BuildPlanCheckoutDirectoriesDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, - BuildPlanCheckoutDirectoriesDTO.class); - assertThat(checkoutDirectoryDTO.exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectoryDTO.solutionCheckoutDirectories()).isNull(); - assertThat(checkoutDirectoryDTO.testCheckoutDirectory()).isEqualTo("/"); - } - - @Test - @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") - void testGetCheckoutDirectoriesAccessForbidden() throws Exception { - request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, BuildPlanCheckoutDirectoriesDTO.class); + @Nested + class TestGetCheckoutDirectories { + + @Test + @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") + void testWithValidProgrammingLanguage() throws Exception { + CheckoutDirectoriesDTO checkoutDirectoryDTO = request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.OK, + CheckoutDirectoriesDTO.class); + + assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); + + // TODO + } + + @Test + @WithMockUser(username = TEST_PREFIX + "editor1", roles = "EDITOR") + void testWithNotSupportedProgrammingLanguage() throws Exception { + request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=languageThatDoesNotExist", HttpStatus.BAD_REQUEST, + CheckoutDirectoriesDTO.class); + } + + @Test + @WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA") + void testAccessForbidden() throws Exception { + request.get("/api/programming-exercises/repository-checkout-directories?programmingLanguage=JAVA", HttpStatus.FORBIDDEN, CheckoutDirectoriesDTO.class); + } } } From 2d56df29371b94fd22a7f2ce4881d35254e13395 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Thu, 23 May 2024 15:14:24 +0200 Subject: [PATCH 076/117] Adding checks for solution checkout directory repositories to integration test --- .../ProgrammingExerciseLocalVCLocalCIIntegrationTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index 140fd7044e7b..1c24903a1326 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -255,7 +255,10 @@ void testWithValidProgrammingLanguage() throws Exception { assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); - // TODO + // Verify solution build plan checkout directories + assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); + assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); } @Test From 047302eccf2ce34a6d40b7a031899d46aeef2e0a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 03:56:43 +0200 Subject: [PATCH 077/117] Adjust types for new endpoint, introducing new component to preview checkout directories --- .../build-plan-checkout-directories-dto.ts | 5 ++ .../app/entities/checkout-directories-dto.ts | 6 ++ .../repositories-checkout-directories-dto.ts | 5 -- .../programming-exercise-detail.component.ts | 30 +------- .../services/programming-exercise.service.ts | 6 +- ...exercise-build-plan-details.component.html | 23 ++++++ ...g-exercise-build-plan-details.component.ts | 12 ++++ ...ns-and-repositories-preview.component.html | 33 +++------ ...lans-and-repositories-preview.component.ts | 4 +- .../programming-exercise-update.module.ts | 2 + ...and-repositories-preview.component.spec.ts | 71 ++++++++++++------- 11 files changed, 111 insertions(+), 86 deletions(-) create mode 100644 src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts create mode 100644 src/main/webapp/app/entities/checkout-directories-dto.ts delete mode 100644 src/main/webapp/app/entities/repositories-checkout-directories-dto.ts create mode 100644 src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html create mode 100644 src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts diff --git a/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts b/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts new file mode 100644 index 000000000000..7d684ca68b33 --- /dev/null +++ b/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts @@ -0,0 +1,5 @@ +export class BuildPlanCheckoutDirectoriesDTO { + exerciseCheckoutDirectory?: string; + solutionCheckoutDirectories?: string[]; + testCheckoutDirectory: string; +} diff --git a/src/main/webapp/app/entities/checkout-directories-dto.ts b/src/main/webapp/app/entities/checkout-directories-dto.ts new file mode 100644 index 000000000000..71b05a32d187 --- /dev/null +++ b/src/main/webapp/app/entities/checkout-directories-dto.ts @@ -0,0 +1,6 @@ +import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/build-plan-checkout-directories-dto'; + +export class CheckoutDirectoriesDto { + submissionBuildPlanCheckoutDirectories?: BuildPlanCheckoutDirectoriesDTO; + solutionBuildPlanCheckoutDirectories?: BuildPlanCheckoutDirectoriesDTO; +} diff --git a/src/main/webapp/app/entities/repositories-checkout-directories-dto.ts b/src/main/webapp/app/entities/repositories-checkout-directories-dto.ts deleted file mode 100644 index 81d38004454b..000000000000 --- a/src/main/webapp/app/entities/repositories-checkout-directories-dto.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class RepositoriesCheckoutDirectoriesDTO { - exerciseCheckoutDirectory?: string; - solutionCheckoutDirectory?: string; - testCheckoutDirectory?: string; -} diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 4aa6eecb508b..7ef343bc5d1a 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -56,7 +56,7 @@ import { IrisSubSettingsType } from 'app/entities/iris/settings/iris-sub-setting import { Detail } from 'app/detail-overview-list/detail.model'; import { Competency } from 'app/entities/competency.model'; import { AeolusService } from 'app/exercises/programming/shared/service/aeolus.service'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; +import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-detail', @@ -103,7 +103,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { plagiarismCheckSupported = false; // default value - checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; + checkoutDirectories?: CheckoutDirectoriesDto; private checkoutDirectoriesSubscription: Subscription; private activatedRouteSubscription: Subscription; @@ -376,9 +376,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TEMPLATE', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.exerciseCheckoutDirectory : undefined, - isCheckoutDirectoryForSubmissionAndTemplateBuild: true, - isAtLeastEditor: exercise.isAtLeastEditor, }, }, { @@ -389,9 +386,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'SOLUTION', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? this.getSolutionCheckoutDirectory().checkoutDirectory : undefined, - isCheckoutDirectoryForSubmissionAndTemplateBuild: this.getSolutionCheckoutDirectory().isCheckoutDirectoryForSubmissionAndTemplateBuild, - isAtLeastEditor: exercise.isAtLeastEditor, }, }, { @@ -402,9 +396,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { exerciseId: exercise.id, type: 'TESTS', showOpenLink: !this.localVCEnabled, - checkoutDirectory: this.localVCEnabled ? this.checkoutDirectories?.testCheckoutDirectory : undefined, - isCheckoutDirectoryForSubmissionAndTemplateBuild: true, - isAtLeastEditor: exercise.isAtLeastEditor, }, }, this.supportsAuxiliaryRepositories && @@ -735,23 +726,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { }); } - private getSolutionCheckoutDirectory(): { - checkoutDirectory: string; - isCheckoutDirectoryForSubmissionAndTemplateBuild: boolean; - } { - if (this.checkoutDirectories?.solutionCheckoutDirectory) { - return { - checkoutDirectory: this.checkoutDirectories.solutionCheckoutDirectory, - isCheckoutDirectoryForSubmissionAndTemplateBuild: true, - }; - } - - return { - checkoutDirectory: this.checkoutDirectories?.exerciseCheckoutDirectory ?? '', - isCheckoutDirectoryForSubmissionAndTemplateBuild: false, - }; - } - /** * Opens modal and executes a consistency check for the given programming exercise * @param exercise the programming exercise to check diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index ebf2b03ba1d9..3f4fa2ad000c 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -26,7 +26,7 @@ import { Result } from 'app/entities/result.model'; import { Participation } from 'app/entities/participation/participation.model'; import { PlagiarismResultDTO } from 'app/exercises/shared/plagiarism/types/PlagiarismResultDTO'; import { ImportOptions } from 'app/types/programming-exercises'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; +import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; export type EntityResponseType = HttpResponse; export type EntityArrayResponseType = HttpResponse; @@ -675,8 +675,8 @@ export class ProgrammingExerciseService { .pipe(map((res: EntityResponseType) => this.processProgrammingExerciseEntityResponse(res))); } - getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { - return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { + getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { + return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { params: { programmingLanguage, }, diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html new file mode 100644 index 000000000000..43a7df7f13f8 --- /dev/null +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html @@ -0,0 +1,23 @@ +@if (checkoutDirectories) { +
      + + +
      +
      +
        +
      • + {{ checkoutDirectories.exerciseCheckoutDirectory }} +
      • +
      • + {{ checkoutDirectories.solutionCheckoutDirectories }} +
      • +
      • + {{ checkoutDirectories.testCheckoutDirectory }} +
      • + @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { +
      • + {{ auxiliaryRepositoryCheckoutDirectory }} +
      • + } +
      +} diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts new file mode 100644 index 000000000000..e715e3a6c4db --- /dev/null +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts @@ -0,0 +1,12 @@ +import { Component, Input } from '@angular/core'; +import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/build-plan-checkout-directories-dto'; + +@Component({ + selector: 'jhi-programming-exercise-build-plan-details', + templateUrl: './programming-exercise-build-plan-details.component.html', + styleUrls: ['../programming-exercise-form.scss'], +}) +export class ProgrammingExerciseBuildPlanDetailsComponent { + @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; + @Input() auxiliaryRepositoryCheckoutDirectories: string[]; +} diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index ec9b3fa39966..1199b54a94df 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -53,28 +53,17 @@
    } @else if (checkoutDirectories) { -
    -
    - - -
    -
    -
      -
    • - {{ checkoutDirectories.exerciseCheckoutDirectory }} -
    • -
    • - {{ checkoutDirectories.solutionCheckoutDirectory }} -
    • -
    • - {{ checkoutDirectories.testCheckoutDirectory }} -
    • - @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { -
    • - {{ auxiliaryRepositoryCheckoutDirectory }} -
    • - } -
    +
    + +
    +
    +
    }
    diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index 474583cbaf53..fd939f836f74 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -4,7 +4,7 @@ import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { Subscription } from 'rxjs'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; +import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-plans-and-repositories-preview', @@ -20,7 +20,7 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements shortName?: string; - checkoutDirectories?: RepositoriesCheckoutDirectoriesDTO; + checkoutDirectories?: CheckoutDirectoriesDto; auxiliaryRepositoryCheckoutDirectories: string[] = []; programmingExerciseServiceSubscription: Subscription; diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts index b2c9aeba59c9..e6313e30ba14 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts @@ -31,6 +31,7 @@ import { AceEditorModule } from 'app/shared/markdown-editor/ace-editor/ace-edito import { ProgrammingExerciseCustomBuildPlanComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-custom-build-plan.component'; import { ProgrammingExerciseDockerImageComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-docker-image/programming-exercise-docker-image.component'; import { FormsModule } from 'app/forms/forms.module'; +import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/programming/manage/update/programming-exercise-build-plan-details.component'; @NgModule({ imports: [ @@ -68,6 +69,7 @@ import { FormsModule } from 'app/forms/forms.module'; ProgrammingExercisePlansAndRepositoriesPreviewComponent, AddAuxiliaryRepositoryButtonComponent, RemoveAuxiliaryRepositoryButtonComponent, + ProgrammingExerciseBuildPlanDetailsComponent, ], exports: [ProgrammingExerciseUpdateComponent, ProgrammingExercisePlansAndRepositoriesPreviewComponent], }) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 356b19f205d5..ca8941067b03 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -2,7 +2,7 @@ import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exe import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; -import { RepositoriesCheckoutDirectoriesDTO } from 'app/entities/repositories-checkout-directories-dto'; +import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; @@ -10,29 +10,42 @@ import { MockComponent } from 'ng-mocks'; import { Subscription, of } from 'rxjs'; import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; import { SimpleChanges } from '@angular/core'; +import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/programming/manage/update/programming-exercise-build-plan-details.component'; describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; let fixture: ComponentFixture; let programmingExerciseService: ProgrammingExerciseService; - const CHECKOUT_DIRECTORY_PREVIEW = '#checkout-directory-preview'; - - const JAVA_CHECKOUT_DIRECTORIES: RepositoriesCheckoutDirectoriesDTO = { - exerciseCheckoutDirectory: '/assignment', - solutionCheckoutDirectory: '/assignment', - testCheckoutDirectory: '', // Empty string should be converted to '/' + const CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN = '#checkout-directory-preview-submission-build-plan'; + const CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN = '#checkout-directory-preview-solution-build-plan'; + + const JAVA_CHECKOUT_DIRECTORIES: CheckoutDirectoriesDto = { + submissionBuildPlanCheckoutDirectories: { + exerciseCheckoutDirectory: '/assignment', + testCheckoutDirectory: '', + }, + solutionBuildPlanCheckoutDirectories: { + solutionCheckoutDirectories: ['/assignment'], + testCheckoutDirectory: '', + }, }; - const OCAML_CHECKOUT_DIRECTORIES: RepositoriesCheckoutDirectoriesDTO = { - exerciseCheckoutDirectory: '/assignment', - solutionCheckoutDirectory: '/solution', - testCheckoutDirectory: '/tests', + const OCAML_CHECKOUT_DIRECTORIES: CheckoutDirectoriesDto = { + submissionBuildPlanCheckoutDirectories: { + exerciseCheckoutDirectory: '/assignment', + solutionCheckoutDirectories: ['/solution'], + testCheckoutDirectory: 'tests', + }, + solutionBuildPlanCheckoutDirectories: { + solutionCheckoutDirectories: ['/assignment', '/solution'], + testCheckoutDirectory: 'tests', + }, }; beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent)], + declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent), MockComponent(ProgrammingExerciseBuildPlanDetailsComponent)], providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], }) .compileComponents() @@ -58,11 +71,10 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { it('should display checkout directories when they exist', () => { fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); - expect(previewElement).toBeTruthy(); - expect(previewElement.textContent).toContain('/assignment'); - expect(previewElement.textContent).toContain('/assignment'); - expect(previewElement.textContent).toContain('/'); + const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + expect(previewElementSubmission).toBeTruthy(); + expect(previewElementSubmission.textContent).toContain('/assignment'); + expect(previewElementSubmission.textContent).toContain('/'); }); it('should send request if localCI is used', () => { @@ -84,15 +96,19 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { it('should display checkoutDirectory preview if localCI is used', () => { fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); - expect(previewElement).toBeTruthy(); + const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(previewElementSubmission).toBeTruthy(); + expect(previewElementSolution).toBeTruthy(); }); it('should NOT display checkoutDirectory preview if localCI is NOT used', () => { component.isLocal = false; fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); - expect(previewElement).toBeFalsy(); + const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(previewElementSubmission).toBeFalsy(); + expect(previewElementSolution).toBeFalsy(); }); it('should update auxiliary checkout repository directories', () => { @@ -100,9 +116,12 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); - expect(previewElement).toBeTruthy(); - expect(previewElement.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added + const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(previewElementSubmission).toBeTruthy(); + expect(previewElementSubmission.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added + expect(previewElementSolution).toBeTruthy(); + expect(previewElementSolution.textContent).toContain('/assignment/sut'); }); it('should unsubscribe from programmingExerciseServiceSubscription on destroy', () => { @@ -127,7 +146,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { // assertion to check if ngOnChanges was executed properly and updated the checkout directories expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); - expect(component.checkoutDirectories?.solutionCheckoutDirectory).toBe('/solution'); // was '/assignment' before with JAVA as programming language + expect(component.checkoutDirectories?.solutionBuildPlanCheckoutDirectories?.solutionCheckoutDirectories).toEqual(['/assignment', '/solution']); // was ['/assignment'] before with JAVA as programming language }); it('should update auxiliary repository directories on changes', () => { @@ -143,7 +162,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW); + const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); expect(previewElement).toBeTruthy(); expect(previewElement.textContent).toContain('/assignment/src'); }); From f91ebb58aef3e6b3b38c41af83d7843ad9dca758 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 04:17:00 +0200 Subject: [PATCH 078/117] Displaying solution directories properly --- ...programming-exercise-build-plan-details.component.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html index 43a7df7f13f8..3f266d076429 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html @@ -9,7 +9,13 @@ {{ checkoutDirectories.exerciseCheckoutDirectory }}
  • - {{ checkoutDirectories.solutionCheckoutDirectories }} + @for (directory of checkoutDirectories.solutionCheckoutDirectories; track directory; let index = $index) { + {{ directory }} + @if (index < checkoutDirectories.solutionCheckoutDirectories!.length - 1) { + + , + } + }
  • {{ checkoutDirectories.testCheckoutDirectory }} From a372b7403680b0d4e82df14b48e40c998bc16f06 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 04:40:22 +0200 Subject: [PATCH 079/117] Fixing tests --- ...and-repositories-preview.component.spec.ts | 64 ++++++++++++------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index ca8941067b03..7c3737b561c7 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -45,7 +45,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent), MockComponent(ProgrammingExerciseBuildPlanDetailsComponent)], + declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanDetailsComponent], providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], }) .compileComponents() @@ -71,10 +71,15 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { it('should display checkout directories when they exist', () => { fixture.detectChanges(); - const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); - expect(previewElementSubmission).toBeTruthy(); - expect(previewElementSubmission.textContent).toContain('/assignment'); - expect(previewElementSubmission.textContent).toContain('/'); + const submissionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + + expect(submissionPreviewElement).toBeTruthy(); + expect(submissionPreviewElement.textContent).toContain('/assignment'); + expect(submissionPreviewElement.textContent).toContain('/'); + expect(solutionPreviewElement).toBeTruthy(); + expect(solutionPreviewElement.textContent).toContain('/assignment'); + expect(solutionPreviewElement.textContent).toContain('/'); }); it('should send request if localCI is used', () => { @@ -96,19 +101,19 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { it('should display checkoutDirectory preview if localCI is used', () => { fixture.detectChanges(); - const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); - const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); - expect(previewElementSubmission).toBeTruthy(); - expect(previewElementSolution).toBeTruthy(); + const submissionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(submissionPreviewElement).toBeTruthy(); + expect(solutionPreviewElement).toBeTruthy(); }); it('should NOT display checkoutDirectory preview if localCI is NOT used', () => { component.isLocal = false; fixture.detectChanges(); - const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); - const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); - expect(previewElementSubmission).toBeFalsy(); - expect(previewElementSolution).toBeFalsy(); + const submissionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(submissionPreviewElement).toBeFalsy(); + expect(solutionPreviewElement).toBeFalsy(); }); it('should update auxiliary checkout repository directories', () => { @@ -116,12 +121,12 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture.detectChanges(); - const previewElementSubmission = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); - const previewElementSolution = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); - expect(previewElementSubmission).toBeTruthy(); - expect(previewElementSubmission.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added - expect(previewElementSolution).toBeTruthy(); - expect(previewElementSolution.textContent).toContain('/assignment/sut'); + const submissionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(submissionPreviewElement).toBeTruthy(); + expect(submissionPreviewElement.textContent).toContain('/assignment/sut'); // the slash for the root directory should have been added + expect(solutionPreviewElement).toBeTruthy(); + expect(solutionPreviewElement.textContent).toContain('/assignment/sut'); }); it('should unsubscribe from programmingExerciseServiceSubscription on destroy', () => { @@ -149,6 +154,21 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(component.checkoutDirectories?.solutionBuildPlanCheckoutDirectories?.solutionCheckoutDirectories).toEqual(['/assignment', '/solution']); // was ['/assignment'] before with JAVA as programming language }); + it('should not display space between solution checkout directories', () => { + component.ngOnChanges({ + programmingExerciseCreationConfig: { + previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, + currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, + }, + } as unknown as SimpleChanges); + + fixture.detectChanges(); + + const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); + expect(solutionPreviewElement).toBeTruthy(); + expect(solutionPreviewElement.textContent).toContain('/assignment, /solution'); + }); + it('should update auxiliary repository directories on changes', () => { fixture.detectChanges(); @@ -162,8 +182,8 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture.detectChanges(); - const previewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); - expect(previewElement).toBeTruthy(); - expect(previewElement.textContent).toContain('/assignment/src'); + const submissionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN); + expect(submissionPreviewElement).toBeTruthy(); + expect(submissionPreviewElement.textContent).toContain('/assignment/src'); }); }); From afbb86c25f8ca2236731c2c47c2bfaa3239d4c15 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 04:47:23 +0200 Subject: [PATCH 080/117] Adding test for comma separation --- .../programming-exercise-build-plan-details.component.html | 1 - ...-exercise-plans-and-repositories-preview.component.spec.ts | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html index 3f266d076429..8d3dc0f8de2b 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html @@ -12,7 +12,6 @@ @for (directory of checkoutDirectories.solutionCheckoutDirectories; track directory; let index = $index) { {{ directory }} @if (index < checkoutDirectories.solutionCheckoutDirectories!.length - 1) { - , } } diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 7c3737b561c7..5f4cf746ce6f 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -154,7 +154,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { expect(component.checkoutDirectories?.solutionBuildPlanCheckoutDirectories?.solutionCheckoutDirectories).toEqual(['/assignment', '/solution']); // was ['/assignment'] before with JAVA as programming language }); - it('should not display space between solution checkout directories', () => { + it('should comma separate the solution directories', () => { component.ngOnChanges({ programmingExerciseCreationConfig: { previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, @@ -166,7 +166,7 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); expect(solutionPreviewElement).toBeTruthy(); - expect(solutionPreviewElement.textContent).toContain('/assignment, /solution'); + expect(solutionPreviewElement.textContent).toContain(' /assignment, /solution '); }); it('should update auxiliary repository directories on changes', () => { From ca2792bb7ffa1faa846a5477f4689139223f4bba Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 04:56:44 +0200 Subject: [PATCH 081/117] Make test for solution repository comma separation more robust --- .../programming-exercise-build-plan-details.component.html | 2 +- ...g-exercise-plans-and-repositories-preview.component.spec.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html index 8d3dc0f8de2b..6864bbccfe5c 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html @@ -12,7 +12,7 @@ @for (directory of checkoutDirectories.solutionCheckoutDirectories; track directory; let index = $index) { {{ directory }} @if (index < checkoutDirectories.solutionCheckoutDirectories!.length - 1) { - , + , } }
  • diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 5f4cf746ce6f..3b08547bfd3c 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -164,9 +164,10 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { fixture.detectChanges(); + const OCAML_SOLUTION_CHECKOUT_DIRECTORY_REGEX = RegExp('.*\\/assignment, *\\/solution.*'); const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); expect(solutionPreviewElement).toBeTruthy(); - expect(solutionPreviewElement.textContent).toContain(' /assignment, /solution '); + expect(OCAML_SOLUTION_CHECKOUT_DIRECTORY_REGEX.test(solutionPreviewElement.textContent)).toBeTrue(); }); it('should update auxiliary repository directories on changes', () => { From eb5b82a7a898f69921800c5a62f806eb522a4243 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 05:12:37 +0200 Subject: [PATCH 082/117] Shortening translations --- .../detail-overview-list.component.html | 3 --- .../programming-exercise-build-plan-details.component.html | 4 ---- ...g-exercise-plans-and-repositories-preview.component.html | 6 ++++++ src/main/webapp/i18n/de/programmingExercise.json | 4 ++-- src/main/webapp/i18n/en/programmingExercise.json | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 278f1cdc88e7..7db9f8807b9e 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -80,9 +80,6 @@

    {{ section
    : {{ detail.data.checkoutDirectory }} - @if (!detail.data.isCheckoutDirectoryForSubmissionAndTemplateBuild) { - - }
    } } @else { diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html index 6864bbccfe5c..0a13bfcf01f5 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html @@ -1,8 +1,4 @@ @if (checkoutDirectories) { -
    - - -

    • diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 1199b54a94df..ad8904179b00 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -54,12 +54,18 @@

    } @else if (checkoutDirectories) {
    +
    + +
    +
    + +
    Date: Fri, 24 May 2024 06:17:06 +0200 Subject: [PATCH 083/117] Introducing preview as shared component --- .../detail-overview-list.component.ts | 1 + .../app/detail-overview-list/detail.model.ts | 11 ++- ...ns-and-repositories-preview.component.html | 80 ++---------------- .../programming-exercise-update.module.ts | 4 +- .../build-details/build-details.module.ts | 12 +++ ...ming-exercise-build-details.component.html | 80 ++++++++++++++++++ ...amming-exercise-build-details.component.ts | 83 +++++++++++++++++++ ...-plan-checkout-directories.component.html} | 0 ...ld-plan-checkout-directories.component.ts} | 8 +- 9 files changed, 198 insertions(+), 81 deletions(-) create mode 100644 src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts create mode 100644 src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html create mode 100644 src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts rename src/main/webapp/app/exercises/programming/{manage/update/programming-exercise-build-plan-details.component.html => shared/build-details/programming-exercise-build-plan-checkout-directories.component.html} (100%) rename src/main/webapp/app/exercises/programming/{manage/update/programming-exercise-build-plan-details.component.ts => shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts} (50%) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts index 8bdf8e132958..1c8d9a73343e 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.ts @@ -37,6 +37,7 @@ export enum DetailType { ProgrammingProblemStatement = 'detail-problem-statement', ProgrammingTimeline = 'detail-timeline', ProgrammingBuildStatistics = 'detail-build-statistics', + ProgrammingCheckoutDirectories = 'detail-checkout-directories', } @Component({ diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index 051064f8bcc9..8cf8fcb6aced 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -33,7 +33,8 @@ type ShownDetail = | ProgrammingDiffReportDetail | ProgrammingProblemStatementDetail | ProgrammingTimelineDetail - | ProgrammingBuildStatisticsDetail; + | ProgrammingBuildStatisticsDetail + | ProgrammingCheckoutDirectoriesDetail; interface DetailBase { type: DetailType; @@ -136,3 +137,11 @@ interface ProgrammingBuildStatisticsDetail extends DetailBase { buildLogStatistics: BuildLogStatisticsDTO; }; } + +interface ProgrammingCheckoutDirectoriesDetail extends DetailBase { + type: DetailType.ProgrammingCheckoutDirectories; + data: { + exercise: ProgrammingExercise; + isLocal: boolean; + }; +} diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index ad8904179b00..595405744b74 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -1,76 +1,8 @@ @if (programmingExercise && programmingExercise.shortName) { -
    -
    -
    -
    - -
    -
    -
      -
    • - {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-exercise - -
    • -
    • - {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-solution - -
    • -
    • - {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-tests - -
    • - @if (programmingExercise.auxiliaryRepositories?.length) { -
      - @for (auxiliaryRepository of programmingExercise.auxiliaryRepositories; track auxiliaryRepository) { -
      -
    • - - {{ shortName?.toLowerCase() }}{{ programmingExercise.shortName.toLowerCase() }}-{{ auxiliaryRepository.name?.toLowerCase() }} - -
    • -
      - } -
      - } -
    -
    -
    - @if (!isLocal) { -
    -
    - -
    -
    -
      -
    • - {{ shortName?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-BASE - -
    • -
    • - {{ shortName?.toUpperCase() }}{{ programmingExercise.shortName.toUpperCase() }}-SOLUTION - -
    • -
    -
    - } @else if (checkoutDirectories) { -
    -
    - -
    - -
    -
    -
    - -
    - -
    - } -
    + } diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts index e6313e30ba14..166dec0f9b9c 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts @@ -31,7 +31,7 @@ import { AceEditorModule } from 'app/shared/markdown-editor/ace-editor/ace-edito import { ProgrammingExerciseCustomBuildPlanComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-custom-build-plan.component'; import { ProgrammingExerciseDockerImageComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-docker-image/programming-exercise-docker-image.component'; import { FormsModule } from 'app/forms/forms.module'; -import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/programming/manage/update/programming-exercise-build-plan-details.component'; +import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/programming/shared/build-details/build-details.module'; @NgModule({ imports: [ @@ -55,6 +55,7 @@ import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/prog ExerciseUpdatePlagiarismModule, AceEditorModule, FormsModule, + ArtemisProgrammingExerciseBuildDetailsModule, ], declarations: [ ProgrammingExerciseUpdateComponent, @@ -69,7 +70,6 @@ import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/prog ProgrammingExercisePlansAndRepositoriesPreviewComponent, AddAuxiliaryRepositoryButtonComponent, RemoveAuxiliaryRepositoryButtonComponent, - ProgrammingExerciseBuildPlanDetailsComponent, ], exports: [ProgrammingExerciseUpdateComponent, ProgrammingExercisePlansAndRepositoriesPreviewComponent], }) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts b/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts new file mode 100644 index 000000000000..24d045e0a306 --- /dev/null +++ b/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { ProgrammingExerciseBuildDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-details.component'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; +import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; + +@NgModule({ + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], + declarations: [ProgrammingExerciseBuildDetailsComponent, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], + exports: [ProgrammingExerciseBuildDetailsComponent], +}) +export class ArtemisProgrammingExerciseBuildDetailsModule {} diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html new file mode 100644 index 000000000000..92bbd917762b --- /dev/null +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html @@ -0,0 +1,80 @@ +
    +
    +
    +
    + +
    +
    +
      +
    • + + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -exercise + + +
    • +
    • + + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -solution + + +
    • +
    • + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -tests + +
    • + @if (programmingExercise?.auxiliaryRepositories?.length) { +
      + @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) { +
      +
    • + + {{ courseShortName?.toLowerCase() }}{{ programmingExercise!.shortName?.toLowerCase() }} -{{ auxiliaryRepository.name?.toLowerCase() }} + +
    • +
      + } +
      + } +
    +
    +
    + @if (!isLocal) { +
    +
    + +
    +
    +
      +
    • + {{ courseShortName?.toUpperCase() }}{{ programmingExercise?.shortName?.toUpperCase() }} -BASE + +
    • +
    • + + {{ courseShortName?.toUpperCase() }}{{ programmingExercise?.shortName?.toUpperCase() }} -SOLUTION + + +
    • +
    +
    + } @else if (checkoutDirectories) { +
    +
    + +
    + +
    +
    +
    + +
    + +
    + } +
    diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts new file mode 100644 index 000000000000..11187b8d24b9 --- /dev/null +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts @@ -0,0 +1,83 @@ +import { Component, Input, SimpleChanges } from '@angular/core'; +import { getCourseFromExercise } from 'app/entities/exercise.model'; +import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; +import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; +import { Subscription } from 'rxjs'; +import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; + +@Component({ + selector: 'jhi-programming-exercise-build-details', + templateUrl: './programming-exercise-build-details.component.html', + styleUrls: ['../../manage/programming-exercise-form.scss'], +}) +export class ProgrammingExerciseBuildDetailsComponent { + @Input() programmingExercise: ProgrammingExercise | null; + @Input() checkoutDirectories?: CheckoutDirectoriesDto; + @Input() programmingLanguage: ProgrammingLanguage; + @Input() isLocal: boolean; + + constructor(private programmingExerciseService: ProgrammingExerciseService) {} + + courseShortName?: string; + + auxiliaryRepositoryCheckoutDirectories: string[] = []; + + programmingExerciseServiceSubscription: Subscription; + + private updateCheckoutDirectories() { + this.programmingExerciseServiceSubscription = this.programmingExerciseService + .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage) + .subscribe((checkoutDirectories) => { + this.checkoutDirectories = checkoutDirectories; + }); + } + + private updateAuxiliaryRepositoryCheckoutDirectories() { + this.auxiliaryRepositoryCheckoutDirectories = + this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; + } + + private addLeadingSlashIfNotPresent(directory: string | undefined): string { + const ROOT_DIRECTORY_PATH: string = '/'; + + if (!directory) { + return ROOT_DIRECTORY_PATH; + } + + return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; + } + + private updateShortName() { + if (!this.programmingExercise) { + return; + } + this.courseShortName = getCourseFromExercise(this.programmingExercise)?.shortName; + } + + ngOnInit() { + this.updateShortName(); + + if (this.isLocal) { + this.updateCheckoutDirectories(); + this.updateAuxiliaryRepositoryCheckoutDirectories(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.programmingExercise) { + this.updateShortName(); + } + + if (this.isLocal && changes.programmingLanguageprogrammingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { + this.updateCheckoutDirectories(); + } + + if (this.isLocal && this.programmingExercise?.auxiliaryRepositories) { + this.updateAuxiliaryRepositoryCheckoutDirectories(); + } + } + + ngOnDestroy() { + this.programmingExerciseServiceSubscription?.unsubscribe(); + } +} diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html similarity index 100% rename from src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.html rename to src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts similarity index 50% rename from src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts rename to src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts index e715e3a6c4db..8eb6d9a15e2d 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts @@ -2,11 +2,11 @@ import { Component, Input } from '@angular/core'; import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/build-plan-checkout-directories-dto'; @Component({ - selector: 'jhi-programming-exercise-build-plan-details', - templateUrl: './programming-exercise-build-plan-details.component.html', - styleUrls: ['../programming-exercise-form.scss'], + selector: 'jhi-programming-exercise-build-plan-checkout-directories', + templateUrl: './programming-exercise-build-plan-checkout-directories.component.html', + styleUrls: ['../../manage/programming-exercise-form.scss'], }) -export class ProgrammingExerciseBuildPlanDetailsComponent { +export class ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent { @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; @Input() auxiliaryRepositoryCheckoutDirectories: string[]; } From 3cf3906102498d8b6deb97abcee212ee652b44ce Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 06:47:31 +0200 Subject: [PATCH 084/117] Fixing change detection for auxiliary repositories --- ...ns-and-repositories-preview.component.html | 1 + ...lans-and-repositories-preview.component.ts | 29 ++----------------- ...amming-exercise-build-details.component.ts | 13 +++------ 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html index 595405744b74..d360535b99f6 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html @@ -2,6 +2,7 @@ diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts index fd939f836f74..8bf270864a4e 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts @@ -1,5 +1,4 @@ -import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; -import { getCourseFromExercise } from 'app/entities/exercise.model'; +import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; @@ -11,15 +10,13 @@ import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; templateUrl: './programming-exercise-plans-and-repositories-preview.component.html', styleUrls: ['../programming-exercise-form.scss'], }) -export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements OnInit, OnChanges, OnDestroy { - @Input() programmingExercise: ProgrammingExercise | null; +export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements OnChanges, OnDestroy { + @Input() programmingExercise: ProgrammingExercise; @Input() isLocal: boolean; @Input() programmingExerciseCreationConfig: ProgrammingExerciseCreationConfig; constructor(private programmingExerciseService: ProgrammingExerciseService) {} - shortName?: string; - checkoutDirectories?: CheckoutDirectoriesDto; auxiliaryRepositoryCheckoutDirectories: string[] = []; @@ -48,27 +45,7 @@ export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; } - private updateShortName() { - if (!this.programmingExercise) { - return; - } - this.shortName = getCourseFromExercise(this.programmingExercise)?.shortName; - } - - ngOnInit() { - this.updateShortName(); - - if (this.isLocal) { - this.updateCheckoutDirectories(); - this.updateAuxiliaryRepositoryCheckoutDirectories(); - } - } - ngOnChanges(changes: SimpleChanges) { - if (changes.programmingExercise) { - this.updateShortName(); - } - if ( this.isLocal && this.programmingExerciseCreationConfig?.selectedProgrammingLanguage && diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts index 11187b8d24b9..23b690acd18c 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts @@ -11,8 +11,9 @@ import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; styleUrls: ['../../manage/programming-exercise-form.scss'], }) export class ProgrammingExerciseBuildDetailsComponent { - @Input() programmingExercise: ProgrammingExercise | null; + @Input() programmingExercise: ProgrammingExercise; @Input() checkoutDirectories?: CheckoutDirectoriesDto; + @Input() auxiliaryRepositoryCheckoutDirectories: string[]; @Input() programmingLanguage: ProgrammingLanguage; @Input() isLocal: boolean; @@ -20,8 +21,6 @@ export class ProgrammingExerciseBuildDetailsComponent { courseShortName?: string; - auxiliaryRepositoryCheckoutDirectories: string[] = []; - programmingExerciseServiceSubscription: Subscription; private updateCheckoutDirectories() { @@ -64,15 +63,11 @@ export class ProgrammingExerciseBuildDetailsComponent { } ngOnChanges(changes: SimpleChanges) { - if (changes.programmingExercise) { - this.updateShortName(); - } - - if (this.isLocal && changes.programmingLanguageprogrammingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { + if (this.isLocal && changes.programmingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { this.updateCheckoutDirectories(); } - if (this.isLocal && this.programmingExercise?.auxiliaryRepositories) { + if (changes.auxiliaryRepositoryCheckoutDirectories) { this.updateAuxiliaryRepositoryCheckoutDirectories(); } } From 34c8507296b7d4961e22e45e230ad8874318beaa Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 08:53:38 +0200 Subject: [PATCH 085/117] Introduce new component for displaying the build plan checkout directories and introduce new module to share the preview component with the details page --- ...ns-and-repositories-preview.component.html | 9 --- ...lans-and-repositories-preview.component.ts | 66 ------------------- ...amming-exercise-information.component.html | 4 +- ...ming-exercise-build-details.component.html | 4 +- ...amming-exercise-build-details.component.ts | 32 ++------- ...d-plan-checkout-directories.component.html | 4 +- ...ild-plan-checkout-directories.component.ts | 5 +- ...and-repositories-preview.component.spec.ts | 23 ++++--- 8 files changed, 27 insertions(+), 120 deletions(-) delete mode 100644 src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html delete mode 100644 src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html deleted file mode 100644 index d360535b99f6..000000000000 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.html +++ /dev/null @@ -1,9 +0,0 @@ -@if (programmingExercise && programmingExercise.shortName) { - -} diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts deleted file mode 100644 index 8bf270864a4e..000000000000 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Component, Input, OnChanges, OnDestroy, SimpleChanges } from '@angular/core'; -import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; -import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; -import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; -import { Subscription } from 'rxjs'; -import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; - -@Component({ - selector: 'jhi-programming-exercise-plans-and-repositories-preview', - templateUrl: './programming-exercise-plans-and-repositories-preview.component.html', - styleUrls: ['../programming-exercise-form.scss'], -}) -export class ProgrammingExercisePlansAndRepositoriesPreviewComponent implements OnChanges, OnDestroy { - @Input() programmingExercise: ProgrammingExercise; - @Input() isLocal: boolean; - @Input() programmingExerciseCreationConfig: ProgrammingExerciseCreationConfig; - - constructor(private programmingExerciseService: ProgrammingExerciseService) {} - - checkoutDirectories?: CheckoutDirectoriesDto; - auxiliaryRepositoryCheckoutDirectories: string[] = []; - - programmingExerciseServiceSubscription: Subscription; - - private updateCheckoutDirectories() { - this.programmingExerciseServiceSubscription = this.programmingExerciseService - .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExerciseCreationConfig.selectedProgrammingLanguage) - .subscribe((checkoutDirectories) => { - this.checkoutDirectories = checkoutDirectories; - }); - } - - private updateAuxiliaryRepositoryCheckoutDirectories() { - this.auxiliaryRepositoryCheckoutDirectories = - this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; - } - - private addLeadingSlashIfNotPresent(directory: string | undefined): string { - const ROOT_DIRECTORY_PATH: string = '/'; - - if (!directory) { - return ROOT_DIRECTORY_PATH; - } - - return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; - } - - ngOnChanges(changes: SimpleChanges) { - if ( - this.isLocal && - this.programmingExerciseCreationConfig?.selectedProgrammingLanguage && - changes.programmingExerciseCreationConfig?.currentValue?.selectedProgrammingLanguage !== - changes.programmingExerciseCreationConfig?.previousValue?.selectedProgrammingLanguage - ) { - this.updateCheckoutDirectories(); - } - - if (this.isLocal && this.programmingExercise?.auxiliaryRepositories) { - this.updateAuxiliaryRepositoryCheckoutDirectories(); - } - } - - ngOnDestroy() { - this.programmingExerciseServiceSubscription?.unsubscribe(); - } -} diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 91316e5c9e9a..83285c5b50f6 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -55,10 +55,10 @@ }
    - @if (!programmingExerciseCreationConfig.isImportFromExistingExercise && programmingExerciseCreationConfig.auxiliaryRepositoriesSupported) {
    diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html index 92bbd917762b..2f03b8810d3f 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html @@ -64,7 +64,7 @@

    @@ -73,7 +73,7 @@
    } diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts index 23b690acd18c..163fd40b2312 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, SimpleChanges } from '@angular/core'; +import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; @@ -10,19 +10,19 @@ import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; templateUrl: './programming-exercise-build-details.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], }) -export class ProgrammingExerciseBuildDetailsComponent { +export class ProgrammingExerciseBuildDetailsComponent implements OnInit, OnChanges, OnDestroy { @Input() programmingExercise: ProgrammingExercise; - @Input() checkoutDirectories?: CheckoutDirectoriesDto; - @Input() auxiliaryRepositoryCheckoutDirectories: string[]; @Input() programmingLanguage: ProgrammingLanguage; @Input() isLocal: boolean; constructor(private programmingExerciseService: ProgrammingExerciseService) {} - courseShortName?: string; - programmingExerciseServiceSubscription: Subscription; + courseShortName?: string; + checkoutDirectories?: CheckoutDirectoriesDto; + auxiliaryRepositoryCheckoutDirectories: string[] = []; + private updateCheckoutDirectories() { this.programmingExerciseServiceSubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage) @@ -31,21 +31,6 @@ export class ProgrammingExerciseBuildDetailsComponent { }); } - private updateAuxiliaryRepositoryCheckoutDirectories() { - this.auxiliaryRepositoryCheckoutDirectories = - this.programmingExercise?.auxiliaryRepositories?.map((auxiliaryRepository) => this.addLeadingSlashIfNotPresent(auxiliaryRepository.checkoutDirectory)) ?? []; - } - - private addLeadingSlashIfNotPresent(directory: string | undefined): string { - const ROOT_DIRECTORY_PATH: string = '/'; - - if (!directory) { - return ROOT_DIRECTORY_PATH; - } - - return directory.startsWith(ROOT_DIRECTORY_PATH) ? directory : ROOT_DIRECTORY_PATH + directory; - } - private updateShortName() { if (!this.programmingExercise) { return; @@ -58,7 +43,6 @@ export class ProgrammingExerciseBuildDetailsComponent { if (this.isLocal) { this.updateCheckoutDirectories(); - this.updateAuxiliaryRepositoryCheckoutDirectories(); } } @@ -66,10 +50,6 @@ export class ProgrammingExerciseBuildDetailsComponent { if (this.isLocal && changes.programmingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { this.updateCheckoutDirectories(); } - - if (changes.auxiliaryRepositoryCheckoutDirectories) { - this.updateAuxiliaryRepositoryCheckoutDirectories(); - } } ngOnDestroy() { diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html index 0a13bfcf01f5..1c91fa2433e9 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html @@ -15,9 +15,9 @@
  • {{ checkoutDirectories.testCheckoutDirectory }}
  • - @for (auxiliaryRepositoryCheckoutDirectory of auxiliaryRepositoryCheckoutDirectories; track auxiliaryRepositoryCheckoutDirectory) { + @for (auxiliaryRepository of auxiliaryRepositories; track auxiliaryRepository) {
  • - {{ auxiliaryRepositoryCheckoutDirectory }} + {{ ROOT_DIRECTORY_PATH }}{{ auxiliaryRepository.checkoutDirectory }}
  • } diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts index 8eb6d9a15e2d..63ac41c2e87d 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts @@ -1,5 +1,6 @@ import { Component, Input } from '@angular/core'; import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/build-plan-checkout-directories-dto'; +import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; @Component({ selector: 'jhi-programming-exercise-build-plan-checkout-directories', @@ -8,5 +9,7 @@ import { BuildPlanCheckoutDirectoriesDTO } from 'app/entities/build-plan-checkou }) export class ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent { @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; - @Input() auxiliaryRepositoryCheckoutDirectories: string[]; + @Input() auxiliaryRepositories: AuxiliaryRepository[]; + + ROOT_DIRECTORY_PATH: string = '/'; } diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 3b08547bfd3c..4821f2171a9e 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -1,20 +1,19 @@ -import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; -import { ProgrammingExerciseCreationConfig } from 'app/exercises/programming/manage/update/programming-exercise-creation-config'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; import { MockComponent } from 'ng-mocks'; import { Subscription, of } from 'rxjs'; import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; import { SimpleChanges } from '@angular/core'; -import { ProgrammingExerciseBuildPlanDetailsComponent } from 'app/exercises/programming/manage/update/programming-exercise-build-plan-details.component'; +import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; +import { ProgrammingExerciseBuildDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-details.component'; -describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { - let component: ProgrammingExercisePlansAndRepositoriesPreviewComponent; - let fixture: ComponentFixture; +describe('ProgrammingExerciseBuildDetailsComponent', () => { + let component: ProgrammingExerciseBuildDetailsComponent; + let fixture: ComponentFixture; let programmingExerciseService: ProgrammingExerciseService; const CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN = '#checkout-directory-preview-submission-build-plan'; @@ -45,16 +44,16 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ProgrammingExercisePlansAndRepositoriesPreviewComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanDetailsComponent], + declarations: [ProgrammingExerciseBuildDetailsComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], }) .compileComponents() .then(() => { - fixture = TestBed.createComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent); + fixture = TestBed.createComponent(ProgrammingExerciseBuildDetailsComponent); component = fixture.componentInstance; programmingExerciseService = TestBed.inject(ProgrammingExerciseService); - component.programmingExerciseCreationConfig = { selectedProgrammingLanguage: ProgrammingLanguage.C } as ProgrammingExerciseCreationConfig; + component.programmingLanguage = ProgrammingLanguage.C; component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; component.isLocal = true; @@ -143,9 +142,9 @@ describe('ProgrammingExercisePlansAndRepositoriesPreviewComponent', () => { jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); component.ngOnChanges({ - programmingExerciseCreationConfig: { - previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, - currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, + programmingLanguage: { + previousValue: ProgrammingLanguage.JAVA, + currentValue: ProgrammingLanguage.OCAML, }, } as unknown as SimpleChanges); From 65742c002983a295d3ba4ed868e065902a24b8bf Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 08:56:11 +0200 Subject: [PATCH 086/117] Rename main component --- .../shared/build-details/build-details.module.ts | 6 +++--- ...e-repository-and-build-plan-details.component.html} | 0 ...ise-repository-and-build-plan-details.component.ts} | 4 ++-- ...se-plans-and-repositories-preview.component.spec.ts | 10 +++++----- 4 files changed, 10 insertions(+), 10 deletions(-) rename src/main/webapp/app/exercises/programming/shared/build-details/{programming-exercise-build-details.component.html => programming-exercise-repository-and-build-plan-details.component.html} (100%) rename src/main/webapp/app/exercises/programming/shared/build-details/{programming-exercise-build-details.component.ts => programming-exercise-repository-and-build-plan-details.component.ts} (91%) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts b/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts index 24d045e0a306..2aac795d74a3 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts @@ -1,12 +1,12 @@ import { NgModule } from '@angular/core'; -import { ProgrammingExerciseBuildDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-details.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; @NgModule({ imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], - declarations: [ProgrammingExerciseBuildDetailsComponent, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], - exports: [ProgrammingExerciseBuildDetailsComponent], + declarations: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], + exports: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent], }) export class ArtemisProgrammingExerciseBuildDetailsModule {} diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html similarity index 100% rename from src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.html rename to src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts similarity index 91% rename from src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts rename to src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 163fd40b2312..56972dc50f51 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -7,10 +7,10 @@ import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-build-details', - templateUrl: './programming-exercise-build-details.component.html', + templateUrl: './programming-exercise-repository-and-build-plan-details.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], }) -export class ProgrammingExerciseBuildDetailsComponent implements OnInit, OnChanges, OnDestroy { +export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implements OnInit, OnChanges, OnDestroy { @Input() programmingExercise: ProgrammingExercise; @Input() programmingLanguage: ProgrammingLanguage; @Input() isLocal: boolean; diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 4821f2171a9e..9daf88a37b4a 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -9,11 +9,11 @@ import { Subscription, of } from 'rxjs'; import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary-repository-model'; import { SimpleChanges } from '@angular/core'; import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; -import { ProgrammingExerciseBuildDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-details.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; describe('ProgrammingExerciseBuildDetailsComponent', () => { - let component: ProgrammingExerciseBuildDetailsComponent; - let fixture: ComponentFixture; + let component: ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent; + let fixture: ComponentFixture; let programmingExerciseService: ProgrammingExerciseService; const CHECKOUT_DIRECTORY_PREVIEW_SUBMISSION_BUILD_PLAN = '#checkout-directory-preview-submission-build-plan'; @@ -44,12 +44,12 @@ describe('ProgrammingExerciseBuildDetailsComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ProgrammingExerciseBuildDetailsComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], + declarations: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], }) .compileComponents() .then(() => { - fixture = TestBed.createComponent(ProgrammingExerciseBuildDetailsComponent); + fixture = TestBed.createComponent(ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent); component = fixture.componentInstance; programmingExerciseService = TestBed.inject(ProgrammingExerciseService); From 7a7f634e5f6ce7fffb3f62b9ba3db1ebc4552b9b Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:25:34 +0200 Subject: [PATCH 087/117] Display checkout directories on details page --- .../detail-overview-list.component.html | 15 +++++++++------ .../app/detail-overview-list/detail.model.ts | 3 ++- .../app/detail-overview-list/detail.module.ts | 2 ++ .../programming-exercise-detail.component.ts | 9 +++++++++ .../update/programming-exercise-update.module.ts | 4 +--- ...rogramming-exercise-information.component.html | 2 +- ...repository-and-build-plan-details.component.ts | 8 ++++++-- src/main/webapp/i18n/de/programmingExercise.json | 1 + src/main/webapp/i18n/en/programmingExercise.json | 1 + 9 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 7db9f8807b9e..2760158e8716 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -76,12 +76,6 @@

    {{ section } - @if (isLocalVC && detail.data.isAtLeastEditor) { -
    - : - {{ detail.data.checkoutDirectory }} -
    - } } @else { } @@ -292,6 +286,15 @@

    {{ section } } + @case (DetailType.ProgrammingCheckoutDirectories) { +
    + +
    + } } } } diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index 8cf8fcb6aced..d34611f84d0d 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -1,5 +1,5 @@ import { GradingCriterion } from 'app/exercises/shared/structured-grading-criterion/grading-criterion.model'; -import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; +import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { ProgrammingExerciseInstructorRepositoryType } from 'app/exercises/programming/manage/services/programming-exercise.service'; @@ -142,6 +142,7 @@ interface ProgrammingCheckoutDirectoriesDetail extends DetailBase { type: DetailType.ProgrammingCheckoutDirectories; data: { exercise: ProgrammingExercise; + programmingLanguage?: ProgrammingLanguage; isLocal: boolean; }; } diff --git a/src/main/webapp/app/detail-overview-list/detail.module.ts b/src/main/webapp/app/detail-overview-list/detail.module.ts index b849ae5e67e4..dccfd2b5d976 100644 --- a/src/main/webapp/app/detail-overview-list/detail.module.ts +++ b/src/main/webapp/app/detail-overview-list/detail.module.ts @@ -12,6 +12,7 @@ import { ArtemisProgrammingExerciseLifecycleModule } from 'app/exercises/program import { AssessmentInstructionsModule } from 'app/assessment/assessment-instructions/assessment-instructions.module'; import { IrisModule } from 'app/iris/iris.module'; import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/modeling-editor.module'; +import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/programming/shared/build-details/build-details.module'; @NgModule({ imports: [ @@ -27,6 +28,7 @@ import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/model AssessmentInstructionsModule, IrisModule, ArtemisModelingEditorModule, + ArtemisProgrammingExerciseBuildDetailsModule, ], declarations: [DetailOverviewListComponent], exports: [DetailOverviewListComponent], diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 7ef343bc5d1a..7280e8082180 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -408,6 +408,15 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { showOpenLink: !this.localVCEnabled, }, }, + this.localCIEnabled && { + type: DetailType.ProgrammingCheckoutDirectories, + title: 'artemisApp.programmingExercise.buildPlanDetails', + data: { + exercise: exercise, + programmingLanguage: exercise.programmingLanguage, + isLocal: true, + }, + }, !this.localCIEnabled && { type: DetailType.Link, title: 'artemisApp.programmingExercise.templateBuildPlanId', diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts index 166dec0f9b9c..15f722a63e7c 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core'; import { ProgrammingExerciseUpdateComponent } from 'app/exercises/programming/manage/update/programming-exercise-update.component'; import { ArtemisSharedModule } from 'app/shared/shared.module'; import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component'; import { ArtemisTeamConfigFormGroupModule } from 'app/exercises/shared/team-config-form-group/team-config-form-group.module'; import { ArtemisDifficultyPickerModule } from 'app/exercises/shared/difficulty-picker/difficulty-picker.module'; import { ArtemisPresentationScoreModule } from 'app/exercises/shared/presentation-score/presentation-score.module'; @@ -67,10 +66,9 @@ import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/prog ProgrammingExerciseLanguageComponent, ProgrammingExerciseGradingComponent, ProgrammingExerciseProblemComponent, - ProgrammingExercisePlansAndRepositoriesPreviewComponent, AddAuxiliaryRepositoryButtonComponent, RemoveAuxiliaryRepositoryButtonComponent, ], - exports: [ProgrammingExerciseUpdateComponent, ProgrammingExercisePlansAndRepositoriesPreviewComponent], + exports: [ProgrammingExerciseUpdateComponent], }) export class ArtemisProgrammingExerciseUpdateModule {} diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 83285c5b50f6..66d8b7fd46f5 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -55,7 +55,7 @@ } - { diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index d42b7ef898e6..21c4d61b1eb5 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -434,6 +434,7 @@ "title": "Dein Repository ist gesperrt.", "tooltip": "Dein Repository ist gesperrt, weil die Einreichungsfrist abgelaufen ist oder du das Einreichungslimit erreicht hast. Du kannst weiterhin deinen Code einsehen, aber keine Änderungen vornehmen." }, + "buildPlanCheckoutDirectories": "Build-Plan Checkout-Verzeichnisse", "preview": { "label": "Vorschau", "tooltip": "Für jede Programmieraufgabe, werden verschieden Repositories und Build-Pläne erstellt. Links befinden sich deren generierte Namen basierend auf dem Kurznamen der Aufgabe", diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 338f9efbf831..e45acea9deee 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -434,6 +434,7 @@ "title": "Your repository is locked.", "tooltip": "You are outside of the participation timeframe or you reached your submission limit, your repository is locked. You may still read the code but you may not make any changes to it." }, + "buildPlanCheckoutDirectories": "Build plan checkout directories", "preview": { "label": "Preview", "tooltip": "For every programming exercise, repositories and build plans will be generated. Here, you can find their generated names based on the short name of the exercise (and course)", From 162df5367fa15f7fe2c56487a25d74c9d79cfc4d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:27:51 +0200 Subject: [PATCH 088/117] Fixing headline --- .../programming/manage/programming-exercise-detail.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 7280e8082180..2dfeaac568eb 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -410,7 +410,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { }, this.localCIEnabled && { type: DetailType.ProgrammingCheckoutDirectories, - title: 'artemisApp.programmingExercise.buildPlanDetails', + title: 'artemisApp.programmingExercise.buildPlanCheckoutDirectories', data: { exercise: exercise, programmingLanguage: exercise.programmingLanguage, From ef67e6540191d261fba54c865d24652779f21a03 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:30:13 +0200 Subject: [PATCH 089/117] Display checkout directory for aux repo only once in overview --- .../detail-overview-list/detail-overview-list.component.html | 5 +---- src/main/webapp/i18n/de/programmingExercise.json | 1 - src/main/webapp/i18n/en/programmingExercise.json | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 2760158e8716..1b0c4eccdd8f 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -102,10 +102,7 @@

    {{ section }
    - @if (auxiliaryRepository.checkoutDirectory) { - : - {{ auxiliaryRepository.checkoutDirectory }} - } @else { + @if (!auxiliaryRepository.checkoutDirectory) { } diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 21c4d61b1eb5..42ca6cda0ecf 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -447,7 +447,6 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "Der Build-Plan der Vorlage. Lässt alle Tests über die Vorlage der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests fehlschlagen müssen", "solutionBuildPlanTooltip": "Der Build-Plan der Lösung der Aufgabe. Lässt alle Tests über die Lösung der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests erfolgreich sein müssen", - "checkoutDirectoryDuringBuildExecution": "Checkout-Verzeichnis während der Build-Ausführung", "submissionBuildPlan": "Abgabe Build-Plan", "solutionBuildPlan": "Lösungs Build-Plan" }, diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index e45acea9deee..555a0138827c 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -447,7 +447,6 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "The build plan of the template. Runs all tests on the exercise template. Used as a reference in which all tests must fail", "solutionBuildPlanTooltip": "The build plan of the solution. Runs all tests on the exercise solution. Used as a reference in which all tests must succeed", - "checkoutDirectoryDuringBuildExecution": "Checkout Directory during build execution", "submissionBuildPlan": "Submission build plan", "solutionBuildPlan": "Solution build plan" }, From 1e84a776f9ff69bff119fdc87717cedf29f04fc8 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:36:23 +0200 Subject: [PATCH 090/117] Fixing imports for client tests --- .../programming-exercise-update.component.spec.ts | 4 ++-- .../programming-exercise-information.component.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-update.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-update.component.spec.ts index 756832768cd3..f33778c9ca50 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-update.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-update.component.spec.ts @@ -42,7 +42,6 @@ import { IncludedInOverallScorePickerComponent } from 'app/exercises/shared/incl import { CategorySelectorComponent } from 'app/shared/category-selector/category-selector.component'; import { AddAuxiliaryRepositoryButtonComponent } from 'app/exercises/programming/manage/update/add-auxiliary-repository-button.component'; import { TranslateDirective } from 'app/shared/language/translate.directive'; -import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component'; import { TableEditableFieldComponent } from 'app/shared/table/table-editable-field.component'; import { RemoveKeysPipe } from 'app/shared/pipes/remove-keys.pipe'; import { SubmissionPolicyUpdateComponent } from 'app/exercises/shared/submission-policy/submission-policy-update.component'; @@ -68,6 +67,7 @@ import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary import { AlertService, AlertType } from 'app/core/util/alert.service'; import { FormStatusBarComponent } from 'app/forms/form-status-bar/form-status-bar.component'; import { FormFooterComponent } from 'app/forms/form-footer/form-footer.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; describe('ProgrammingExerciseUpdateComponent', () => { const courseId = 1; @@ -96,7 +96,7 @@ describe('ProgrammingExerciseUpdateComponent', () => { SelectControlValueAccessor, NumberValueAccessor, MockComponent(HelpIconComponent), - MockComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent), + MockComponent(ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent), MockComponent(TableEditableFieldComponent), MockComponent(RemoveAuxiliaryRepositoryButtonComponent), MockComponent(CategorySelectorComponent), diff --git a/src/test/javascript/spec/component/programming-exercise/update-components/programming-exercise-information.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/update-components/programming-exercise-information.component.spec.ts index c59bd4db78fb..30259859d720 100644 --- a/src/test/javascript/spec/component/programming-exercise/update-components/programming-exercise-information.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/update-components/programming-exercise-information.component.spec.ts @@ -8,13 +8,13 @@ import { DefaultValueAccessor, NgModel } from '@angular/forms'; import { RemoveKeysPipe } from 'app/shared/pipes/remove-keys.pipe'; import { ProgrammingExercise } from 'app/entities/programming-exercise.model'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; -import { ProgrammingExercisePlansAndRepositoriesPreviewComponent } from 'app/exercises/programming/manage/update/programming-exercise-plans-and-repositories-preview.component'; import { CategorySelectorComponent } from 'app/shared/category-selector/category-selector.component'; import { AddAuxiliaryRepositoryButtonComponent } from 'app/exercises/programming/manage/update/add-auxiliary-repository-button.component'; import { programmingExerciseCreationConfigMock } from './programming-exercise-creation-config-mock'; import { ExerciseTitleChannelNameComponent } from 'app/exercises/shared/exercise-title-channel-name/exercise-title-channel-name.component'; import { TableEditableFieldComponent } from 'app/shared/table/table-editable-field.component'; import { QueryList } from '@angular/core'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; describe('ProgrammingExerciseInformationComponent', () => { let fixture: ComponentFixture; @@ -29,7 +29,7 @@ describe('ProgrammingExerciseInformationComponent', () => { NgModel, MockComponent(HelpIconComponent), MockComponent(ExerciseTitleChannelNameComponent), - MockComponent(ProgrammingExercisePlansAndRepositoriesPreviewComponent), + MockComponent(ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent), MockComponent(CategorySelectorComponent), MockComponent(AddAuxiliaryRepositoryButtonComponent), MockPipe(ArtemisTranslatePipe), From 789babd12730dfb9682345a5068544455f7eff9d Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:39:36 +0200 Subject: [PATCH 091/117] Adjust translation --- .../programming/manage/programming-exercise-detail.component.ts | 2 +- src/main/webapp/i18n/de/programmingExercise.json | 2 +- src/main/webapp/i18n/en/programmingExercise.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 2dfeaac568eb..ebe943d2330c 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -410,7 +410,7 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { }, this.localCIEnabled && { type: DetailType.ProgrammingCheckoutDirectories, - title: 'artemisApp.programmingExercise.buildPlanCheckoutDirectories', + title: 'artemisApp.programmingExercise.checkoutDirectories', data: { exercise: exercise, programmingLanguage: exercise.programmingLanguage, diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 42ca6cda0ecf..e63abe605742 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -434,7 +434,7 @@ "title": "Dein Repository ist gesperrt.", "tooltip": "Dein Repository ist gesperrt, weil die Einreichungsfrist abgelaufen ist oder du das Einreichungslimit erreicht hast. Du kannst weiterhin deinen Code einsehen, aber keine Änderungen vornehmen." }, - "buildPlanCheckoutDirectories": "Build-Plan Checkout-Verzeichnisse", + "checkoutDirectories": "Checkout-Verzeichnisse", "preview": { "label": "Vorschau", "tooltip": "Für jede Programmieraufgabe, werden verschieden Repositories und Build-Pläne erstellt. Links befinden sich deren generierte Namen basierend auf dem Kurznamen der Aufgabe", diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 555a0138827c..b3190e6ceb9f 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -434,7 +434,7 @@ "title": "Your repository is locked.", "tooltip": "You are outside of the participation timeframe or you reached your submission limit, your repository is locked. You may still read the code but you may not make any changes to it." }, - "buildPlanCheckoutDirectories": "Build plan checkout directories", + "checkoutDirectories": "Checkout directories", "preview": { "label": "Preview", "tooltip": "For every programming exercise, repositories and build plans will be generated. Here, you can find their generated names based on the short name of the exercise (and course)", From 2ceb3319dc61dff3ef3b2dc979bb8fd9e6dac162 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 09:45:40 +0200 Subject: [PATCH 092/117] Fixing whitespaces in repository names --- ...rcise-repository-and-build-plan-details.component.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index 2f03b8810d3f..1fece3e82879 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -8,18 +8,18 @@
    • - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -exercise + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-exercise
    • - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -solution + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-solution
    • - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }} -tests + {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-tests
    • @if (programmingExercise?.auxiliaryRepositories?.length) { @@ -28,7 +28,7 @@
    • - {{ courseShortName?.toLowerCase() }}{{ programmingExercise!.shortName?.toLowerCase() }} -{{ auxiliaryRepository.name?.toLowerCase() }} + {{ courseShortName?.toLowerCase() }}{{ programmingExercise!.shortName?.toLowerCase() }}-{{ auxiliaryRepository.name?.toLowerCase() }}
    • From cedcc65533a1a22bec80c23375c9d15021b4ff54 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 10:03:29 +0200 Subject: [PATCH 093/117] Apply suggestion, import with "type" for type only imports --- ...ng-exercise-repository-and-build-plan-details.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 61e11cc8b438..993b1d6365f6 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -1,9 +1,9 @@ import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; import { getCourseFromExercise } from 'app/entities/exercise.model'; -import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; +import type { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { Subscription } from 'rxjs'; -import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; +import type { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-repository-and-build-plan-details', From 25f1c74cbfc76a772118ae2f5390d28ef3695ae3 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 10:06:53 +0200 Subject: [PATCH 094/117] Apply Self-review --- .../connectors/ci/ContinuousIntegrationService.java | 10 +--------- .../webapp/app/detail-overview-list/detail.model.ts | 7 ------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index 32cfb407b581..b23185195ca7 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -235,19 +235,11 @@ public String forProgrammingLanguage(ProgrammingLanguage language) { }, SOLUTION { - /** - * @param language for which the checkout directory should be retrieved - * @return checkoutDirectory for the solution repository for the build execution of the template and student submissions - * @throws IllegalArgumentException if the solution is not checked out within the build process for the template or student submission - *

      - * Note: if the solution is not checked out during the submission build plan, it will be checked out - * in the assignment respective repository during the solution build - */ @Override public String forProgrammingLanguage(ProgrammingLanguage language) { return switch (language) { case HASKELL, OCAML -> "solution"; - default -> throw new IllegalArgumentException("The solution repository is not checked out during the template or student submission for " + language); + default -> throw new IllegalArgumentException("The solution repository is not checked out during the template/submission build plan for " + language); }; } } diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index d34611f84d0d..d6e004f364ea 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -83,10 +83,6 @@ interface ProgrammingIrisEnabledDetail extends DetailBase { data: { exercise?: ProgrammingExercise; course?: Course; disabled: boolean; subSettingsType: IrisSubSettingsType }; } -/** - * {@link ProgrammingRepositoryButtonsDetail.data.checkoutDirectory} is only needed for localCI, as otherwise the information - * about the checkout directories will be present in the build plans (for the base repositories exercise, solution, tests) - */ interface ProgrammingRepositoryButtonsDetail extends DetailBase { type: DetailType.ProgrammingRepositoryButtons; data: { @@ -94,9 +90,6 @@ interface ProgrammingRepositoryButtonsDetail extends DetailBase { participation?: TemplateProgrammingExerciseParticipation | SolutionProgrammingExerciseParticipation; showOpenLink?: boolean; type: ProgrammingExerciseInstructorRepositoryType; - checkoutDirectory?: string; - isCheckoutDirectoryForSubmissionAndTemplateBuild?: boolean; - isAtLeastEditor?: boolean; }; } From 4dfc532295151da5073226ec0ddceed18f3f554a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 12:07:10 +0200 Subject: [PATCH 095/117] Address review comments from Patrik --- ...amming-exercise-information.component.html | 6 +----- ...tory-and-build-plan-details.component.html | 20 +++++++------------ ...sitory-and-build-plan-details.component.ts | 14 ++++++++----- ...and-repositories-preview.component.spec.ts | 2 +- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 66d8b7fd46f5..1bd5706f339f 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -49,11 +49,7 @@

      - @if (isLocal) { - - } @else { - - } +
      • - - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-exercise - + {{ courseShortName }}{{ programmingExercise?.shortName }}-exercise
      • - - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-solution - + {{ courseShortName }}{{ programmingExercise?.shortName }}-solution
      • - {{ courseShortName?.toLowerCase() }}{{ programmingExercise?.shortName?.toLowerCase() }}-tests + {{ courseShortName }}{{ programmingExercise?.shortName }}-tests
      • @if (programmingExercise?.auxiliaryRepositories?.length) { @@ -27,8 +23,8 @@ @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) {
      • - - {{ courseShortName?.toLowerCase() }}{{ programmingExercise!.shortName?.toLowerCase() }}-{{ auxiliaryRepository.name?.toLowerCase() }} + + {{ courseShortName }}{{ programmingExercise!.shortName }}-{{ auxiliaryRepository.name }}
      • @@ -46,13 +42,11 @@
        • - {{ courseShortName?.toUpperCase() }}{{ programmingExercise?.shortName?.toUpperCase() }} -BASE + {{ courseShortName }}{{ programmingExercise?.shortName }}-BASE
        • - - {{ courseShortName?.toUpperCase() }}{{ programmingExercise?.shortName?.toUpperCase() }} -SOLUTION - + {{ courseShortName }}{{ programmingExercise?.shortName }}-SOLUTION
        diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 993b1d6365f6..d5d5ceacdc08 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -17,7 +17,7 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement constructor(private programmingExerciseService: ProgrammingExerciseService) {} - programmingExerciseServiceSubscription: Subscription; + checkoutDirectorySubscription?: Subscription; courseShortName?: string; checkoutDirectories?: CheckoutDirectoriesDto; @@ -28,14 +28,18 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement return; } - this.programmingExerciseServiceSubscription = this.programmingExerciseService + if (this.checkoutDirectorySubscription) { + this.checkoutDirectorySubscription.unsubscribe(); + } + + this.checkoutDirectorySubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage) .subscribe((checkoutDirectories) => { this.checkoutDirectories = checkoutDirectories; }); } - private updateShortName() { + private updateCourseShortName() { if (!this.programmingExercise) { return; } @@ -43,7 +47,7 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement } ngOnInit() { - this.updateShortName(); + this.updateCourseShortName(); if (this.isLocal) { this.updateCheckoutDirectories(); @@ -57,6 +61,6 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement } ngOnDestroy() { - this.programmingExerciseServiceSubscription?.unsubscribe(); + this.checkoutDirectorySubscription?.unsubscribe(); } } diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 9daf88a37b4a..5a4e603ecf7f 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -131,7 +131,7 @@ describe('ProgrammingExerciseBuildDetailsComponent', () => { it('should unsubscribe from programmingExerciseServiceSubscription on destroy', () => { const subscription = new Subscription(); jest.spyOn(subscription, 'unsubscribe'); - component.programmingExerciseServiceSubscription = subscription; + component.checkoutDirectorySubscription = subscription; component.ngOnDestroy(); From 5405f486ba91e288331d7d78f858c156390f9450 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 13:11:46 +0200 Subject: [PATCH 096/117] Make Coderabbit happy --- src/main/webapp/app/detail-overview-list/detail.model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/detail-overview-list/detail.model.ts b/src/main/webapp/app/detail-overview-list/detail.model.ts index d6e004f364ea..9c95158e0307 100644 --- a/src/main/webapp/app/detail-overview-list/detail.model.ts +++ b/src/main/webapp/app/detail-overview-list/detail.model.ts @@ -1,5 +1,5 @@ import { GradingCriterion } from 'app/exercises/shared/structured-grading-criterion/grading-criterion.model'; -import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; +import type { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { TemplateProgrammingExerciseParticipation } from 'app/entities/participation/template-programming-exercise-participation.model'; import { SolutionProgrammingExerciseParticipation } from 'app/entities/participation/solution-programming-exercise-participation.model'; import { ProgrammingExerciseInstructorRepositoryType } from 'app/exercises/programming/manage/services/programming-exercise.service'; From 273d09c2028cacc3d42fb072080b8ad1e7f3c80a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Fri, 24 May 2024 17:16:34 +0200 Subject: [PATCH 097/117] Address review comments --- .../programming-exercise-detail.component.ts | 17 +++++++++-------- ...sitory-and-build-plan-details.component.html | 2 ++ .../webapp/i18n/de/programmingExercise.json | 2 +- .../webapp/i18n/en/programmingExercise.json | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index ebe943d2330c..09379466a54d 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -408,15 +408,16 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { showOpenLink: !this.localVCEnabled, }, }, - this.localCIEnabled && { - type: DetailType.ProgrammingCheckoutDirectories, - title: 'artemisApp.programmingExercise.checkoutDirectories', - data: { - exercise: exercise, - programmingLanguage: exercise.programmingLanguage, - isLocal: true, + exercise.isAtLeastEditor && + this.localCIEnabled && { + type: DetailType.ProgrammingCheckoutDirectories, + title: 'artemisApp.programmingExercise.checkoutDirectories', + data: { + exercise: exercise, + programmingLanguage: exercise.programmingLanguage, + isLocal: true, + }, }, - }, !this.localCIEnabled && { type: DetailType.Link, title: 'artemisApp.programmingExercise.templateBuildPlanId', diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index cea07c8763d8..113f584a433d 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -55,6 +55,7 @@
        +
        +
        Date: Fri, 24 May 2024 17:54:17 +0200 Subject: [PATCH 098/117] Clarify translations --- src/main/webapp/i18n/de/programmingExercise.json | 2 +- src/main/webapp/i18n/en/programmingExercise.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 6403b04a498d..4df98e2a652e 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -445,7 +445,7 @@ "solutionRepoTooltip": "Das Repository, welches die Lösung der Aufgabe beinhaltet", "testRepoTooltip": "Das Repository, welches alle Tests beinhaltet", "auxiliaryRepoTooltip": "{{description}}", - "templateBuildPlanTooltip": "Der Build-Plan der Vorlage. Lässt alle Tests über die Vorlage der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests fehlschlagen müssen. Für Abgaben von Studierenden wird ein analoger Build Plan verwendet.", + "templateBuildPlanTooltip": "Der Build-Plan der Vorlage und Abgaben von Studierenden. Lässt alle Tests über die Vorlage/Studierenden-Abgabe, der Aufgabe laufen. Die Vorlage dient als Kontrollreferenz, für welche alle Tests fehlschlagen müssen.", "solutionBuildPlanTooltip": "Der Build-Plan der Lösung der Aufgabe. Lässt alle Tests über die Lösung der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests erfolgreich sein müssen", "submissionBuildPlan": "Abgabe Build-Plan", "solutionBuildPlan": "Lösungs Build-Plan" diff --git a/src/main/webapp/i18n/en/programmingExercise.json b/src/main/webapp/i18n/en/programmingExercise.json index 470eaf91fc88..8fa4e5e20ed4 100644 --- a/src/main/webapp/i18n/en/programmingExercise.json +++ b/src/main/webapp/i18n/en/programmingExercise.json @@ -445,8 +445,8 @@ "solutionRepoTooltip": "The repository which contains the solution to the exercise", "testRepoTooltip": "The repository which contains all tests", "auxiliaryRepoTooltip": "{{description}}", - "templateBuildPlanTooltip": "The build plan of the template. Runs all tests on the exercise template. Used as a reference in which all tests must fail. An analogous build plan is used for student submissions.", - "solutionBuildPlanTooltip": "The build plan of the solution. Runs all tests on the exercise solution. Used as a reference in which all tests must succeed", + "templateBuildPlanTooltip": "The build plan of the template and student submissions. Runs all tests on the exercise template / student submission. The build for the exercise template is used as reference in which all tests must fail.", + "solutionBuildPlanTooltip": "The build plan of the solution. Runs all tests on the exercise solution. Used as a reference in which all tests must succeed.", "submissionBuildPlan": "Submission build plan", "solutionBuildPlan": "Solution build plan" }, From 2293a7553f139d0678eb8a82fdc431ae34c53daf Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sat, 25 May 2024 15:20:43 +0200 Subject: [PATCH 099/117] Addressing review feedback --- ...d-plan-checkout-directories.component.html | 6 +-- ...tory-and-build-plan-details.component.html | 49 ++++++++++++++----- ...sitory-and-build-plan-details.component.ts | 40 +++++++-------- .../webapp/i18n/de/programmingExercise.json | 4 +- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html index 1c91fa2433e9..7a3f17bff69f 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html @@ -1,10 +1,10 @@ @if (checkoutDirectories) {
          -
        • +
        • {{ checkoutDirectories.exerciseCheckoutDirectory }}
        • -
        • +
        • @for (directory of checkoutDirectories.solutionCheckoutDirectories; track directory; let index = $index) { {{ directory }} @if (index < checkoutDirectories.solutionCheckoutDirectories!.length - 1) { @@ -12,7 +12,7 @@ } }
        • -
        • +
        • {{ checkoutDirectories.testCheckoutDirectory }}
        • @for (auxiliaryRepository of auxiliaryRepositories; track auxiliaryRepository) { diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index 113f584a433d..b4b8d57ce96a 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -6,18 +6,43 @@

          -
        • - {{ courseShortName }}{{ programmingExercise?.shortName }}-exercise - -
        • -
        • - {{ courseShortName }}{{ programmingExercise?.shortName }}-solution - -
        • -
        • - {{ courseShortName }}{{ programmingExercise?.shortName }}-tests - -
        • + +
        • + + {{ courseShortName }}{{ programmingExercise?.shortName }}{{ trailingRepoSlug }} + + +
        • +
          + + + + + @if (programmingExercise?.auxiliaryRepositories?.length) {
          @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) { diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index d5d5ceacdc08..f9e8d275da31 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -23,14 +23,30 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement checkoutDirectories?: CheckoutDirectoriesDto; auxiliaryRepositoryCheckoutDirectories: string[] = []; + ngOnInit() { + this.updateCourseShortName(); + + if (this.isLocal) { + this.updateCheckoutDirectories(); + } + } + + ngOnChanges(changes: SimpleChanges) { + if (this.isLocal && changes.programmingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { + this.updateCheckoutDirectories(); + } + } + + ngOnDestroy() { + this.checkoutDirectorySubscription?.unsubscribe(); + } + private updateCheckoutDirectories() { if (!this.programmingLanguage) { return; } - if (this.checkoutDirectorySubscription) { - this.checkoutDirectorySubscription.unsubscribe(); - } + this.checkoutDirectorySubscription?.unsubscribe(); // might be defined from previous method execution this.checkoutDirectorySubscription = this.programmingExerciseService .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage) @@ -45,22 +61,4 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement } this.courseShortName = getCourseFromExercise(this.programmingExercise)?.shortName; } - - ngOnInit() { - this.updateCourseShortName(); - - if (this.isLocal) { - this.updateCheckoutDirectories(); - } - } - - ngOnChanges(changes: SimpleChanges) { - if (this.isLocal && changes.programmingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { - this.updateCheckoutDirectories(); - } - } - - ngOnDestroy() { - this.checkoutDirectorySubscription?.unsubscribe(); - } } diff --git a/src/main/webapp/i18n/de/programmingExercise.json b/src/main/webapp/i18n/de/programmingExercise.json index 4df98e2a652e..0d471f7a9ad5 100644 --- a/src/main/webapp/i18n/de/programmingExercise.json +++ b/src/main/webapp/i18n/de/programmingExercise.json @@ -447,8 +447,8 @@ "auxiliaryRepoTooltip": "{{description}}", "templateBuildPlanTooltip": "Der Build-Plan der Vorlage und Abgaben von Studierenden. Lässt alle Tests über die Vorlage/Studierenden-Abgabe, der Aufgabe laufen. Die Vorlage dient als Kontrollreferenz, für welche alle Tests fehlschlagen müssen.", "solutionBuildPlanTooltip": "Der Build-Plan der Lösung der Aufgabe. Lässt alle Tests über die Lösung der Aufgabe laufen. Dient als Kontrollreferenz, für welche alle Tests erfolgreich sein müssen", - "submissionBuildPlan": "Abgabe Build-Plan", - "solutionBuildPlan": "Lösungs Build-Plan" + "submissionBuildPlan": "Abgabe-Build-Plan", + "solutionBuildPlan": "Lösungs-Build-Plan" }, "orion": { "openEditor": "Editor Öffnen" From 516cb009e06a82601fec1cadc97e1bb9a6debf24 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 26 May 2024 23:08:22 +0200 Subject: [PATCH 100/117] Fixing typo in ocaml build script --- src/main/resources/templates/ocaml/test/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/ocaml/test/run.sh b/src/main/resources/templates/ocaml/test/run.sh index 6b831445f61f..7e43c62e03d6 100755 --- a/src/main/resources/templates/ocaml/test/run.sh +++ b/src/main/resources/templates/ocaml/test/run.sh @@ -69,8 +69,8 @@ if ! timeout -s SIGTERM $BUILD_TIMEOUT checker/checker.exe; then echo "Unable to build submission, please ensure that your code builds and matches the provided interface" >&2 exit 0 fi -# build the sudent submission -# don't reference the tests or solution, so that we can show the build output to the sudent and not leak test / solution code +# build the student submission +# don't reference the tests or solution, so that we can show the build output to the student and not leak test / solution code if ! timeout -s SIGTERM $BUILD_TIMEOUT dune build --force assignment; then echo "Unable to build submission, please ensure that your code builds and matches the provided interface" >&2 exit 0 From f24027936651a4d6d85dd6c98d4b8dd2a3b776c5 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Sun, 26 May 2024 23:09:35 +0200 Subject: [PATCH 101/117] Fixing typo in ocaml build script --- src/main/resources/templates/ocaml/test/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/templates/ocaml/test/run.sh b/src/main/resources/templates/ocaml/test/run.sh index 7e43c62e03d6..fe73a2830c98 100755 --- a/src/main/resources/templates/ocaml/test/run.sh +++ b/src/main/resources/templates/ocaml/test/run.sh @@ -52,7 +52,7 @@ cp_code solution echo 'include Assignment' > solution/solution.ml cp_code assignment -# select if tests are run by generated source code as studen toplevel code may run before the tests and be able to spoof a runtime signal +# select if tests are run by generated source code as student toplevel code may run before the tests and be able to spoof a runtime signal echo "let runHidden = $RUN_HIDDEN" > test/runHidden.ml # shellcheck disable=SC2046 From e1d6c0aab3c0ae99189c6ae5a6c3b25178fb774a Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Mon, 27 May 2024 12:51:03 +0200 Subject: [PATCH 102/117] Use template more often --- ...tory-and-build-plan-details.component.html | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index b4b8d57ce96a..3c3bd23c57df 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -6,39 +6,33 @@

            - -
          • - - {{ courseShortName }}{{ programmingExercise?.shortName }}{{ trailingRepoSlug }} - - -
          • -
            - @@ -46,13 +40,16 @@ @if (programmingExercise?.auxiliaryRepositories?.length) {
            @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) { -
            -
          • - - {{ courseShortName }}{{ programmingExercise!.shortName }}-{{ auxiliaryRepository.name }} - -
          • -
            + }
            } @@ -66,9 +63,19 @@

        +
      • - {{ courseShortName }}{{ programmingExercise?.shortName }}-BASE + {{ courseShortName }}{{ programmingExercise?.shortName }}-BASE
      • {{ courseShortName }}{{ programmingExercise?.shortName }}-SOLUTION @@ -99,3 +106,10 @@
    } + + +
  • + {{ courseShortName }}{{ programmingExercise?.shortName }}{{ trailingRepoSlug }} + +
  • +
    From 0e1e3fdbec93fd2c862b163f5fad38b9099fc691 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 18:26:09 +0200 Subject: [PATCH 103/117] Considering checkmark for checkoutSolutionRepository --- .../ci/ContinuousIntegrationService.java | 2 +- .../connectors/gitlabci/GitLabCIService.java | 2 +- .../connectors/jenkins/JenkinsService.java | 2 +- .../connectors/localci/LocalCIService.java | 21 +++++++++++-------- .../ProgrammingExerciseResource.java | 5 +++-- .../detail-overview-list.component.html | 1 + .../programming-exercise-detail.component.ts | 13 ------------ .../services/programming-exercise.service.ts | 3 ++- ...amming-exercise-information.component.html | 1 + ...sitory-and-build-plan-details.component.ts | 8 +++++-- .../artemis/localvcci/LocalCIServiceTest.java | 21 ++++++++++++++++--- 11 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index b23185195ca7..c45d50ff416b 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -264,5 +264,5 @@ interface CustomizableCheckoutPath { * @return the paths of the checkout directories for the default repositories (exercise, solution, tests) for the * template and submission build plan */ - CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage); + CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution); } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index 66152552c1a4..7a0c184a9dee 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -326,7 +326,7 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { } @Override - public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index c595d8086bea..f2693f69da83 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -257,7 +257,7 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th } @Override - public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index 9dcc84f9ee3a..e8451266ceb3 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -223,14 +223,14 @@ private String getCleanPlanName(String name) { } @Override - public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage) { - BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories = getSubmissionBuildPlanCheckoutDirectories(programmingLanguage); + public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { + BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories = getSubmissionBuildPlanCheckoutDirectories(programmingLanguage, checkoutSolution); BuildPlanCheckoutDirectoriesDTO solutionBuildPlanCheckoutDirectories = getSolutionBuildPlanCheckoutDirectories(submissionBuildPlanCheckoutDirectories); return new CheckoutDirectoriesDTO(submissionBuildPlanCheckoutDirectories, solutionBuildPlanCheckoutDirectories); } - private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectories(ProgrammingLanguage programmingLanguage) { + private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { String exerciseCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.ASSIGNMENT.forProgrammingLanguage(programmingLanguage); String testCheckoutDirectory = ContinuousIntegrationService.RepositoryCheckoutPath.TEST.forProgrammingLanguage(programmingLanguage); @@ -238,12 +238,15 @@ private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectorie testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); String[] solutionCheckoutDirectories = null; - try { - String solutionCheckoutDirectoryPath = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - solutionCheckoutDirectories = new String[] { startPathWithRootDirectory(solutionCheckoutDirectoryPath) }; - } - catch (IllegalArgumentException exception) { - // not checked out during template & submission build + + if (checkoutSolution) { + try { + String solutionCheckoutDirectoryPath = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); + solutionCheckoutDirectories = new String[] { startPathWithRootDirectory(solutionCheckoutDirectoryPath) }; + } + catch (IllegalArgumentException exception) { + // not checked out during template & submission build + } } return new BuildPlanCheckoutDirectoriesDTO(exerciseCheckoutDirectory, solutionCheckoutDirectories, testCheckoutDirectory); diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 985ab7367002..61cbb7fb0182 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -888,10 +888,11 @@ public ResponseEntity getBuildLogStatistics(@PathVariable @GetMapping("programming-exercises/repository-checkout-directories") @EnforceAtLeastEditor @FeatureToggle(Feature.ProgrammingExercises) - public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage) { + public ResponseEntity getRepositoryCheckoutDirectories(@RequestParam(value = "programmingLanguage") ProgrammingLanguage programmingLanguage, + @RequestParam(value = "checkoutSolution", defaultValue = "true") boolean checkoutSolution) { log.debug("REST request to get checkout directories for programming language: {}", programmingLanguage); - CheckoutDirectoriesDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow().getCheckoutDirectories(programmingLanguage); + CheckoutDirectoriesDTO repositoriesCheckoutDirectoryDTO = continuousIntegrationService.orElseThrow().getCheckoutDirectories(programmingLanguage, checkoutSolution); return ResponseEntity.ok(repositoriesCheckoutDirectoryDTO); } } diff --git a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html index 1b0c4eccdd8f..dbabc394771a 100644 --- a/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html +++ b/src/main/webapp/app/detail-overview-list/detail-overview-list.component.html @@ -289,6 +289,7 @@

    {{ section [programmingExercise]="detail.data.exercise" [programmingLanguage]="detail.data.programmingLanguage" [isLocal]="detail.data.isLocal" + [checkoutSolutionRepository]="detail.data.exercise.checkoutSolutionRepository" /> } diff --git a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts index 09379466a54d..86791687e2f5 100644 --- a/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts +++ b/src/main/webapp/app/exercises/programming/manage/programming-exercise-detail.component.ts @@ -56,7 +56,6 @@ import { IrisSubSettingsType } from 'app/entities/iris/settings/iris-sub-setting import { Detail } from 'app/detail-overview-list/detail.model'; import { Competency } from 'app/entities/competency.model'; import { AeolusService } from 'app/exercises/programming/shared/service/aeolus.service'; -import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; @Component({ selector: 'jhi-programming-exercise-detail', @@ -103,9 +102,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { plagiarismCheckSupported = false; // default value - checkoutDirectories?: CheckoutDirectoriesDto; - - private checkoutDirectoriesSubscription: Subscription; private activatedRouteSubscription: Subscription; private templateAndSolutionParticipationSubscription: Subscription; private profileInfoSubscription: Subscription; @@ -250,14 +246,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { this.exerciseDetailSections = this.getExerciseDetails(); }); - if (programmingExercise.isAtLeastEditor && this.programmingExercise.programmingLanguage) { - this.checkoutDirectoriesSubscription = this.programmingExerciseService - .getCheckoutDirectoriesForProgrammingLanguage(this.programmingExercise.programmingLanguage) - .subscribe((checkoutDirectories) => { - this.checkoutDirectories = checkoutDirectories; - }); - } - this.exerciseStatisticsSubscription = this.statisticsService.getExerciseStatistics(exerciseId!).subscribe((statistics: ExerciseManagementStatisticsDto) => { this.doughnutStats = statistics; }); @@ -266,7 +254,6 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.dialogErrorSource.unsubscribe(); - this.checkoutDirectoriesSubscription?.unsubscribe(); this.activatedRouteSubscription?.unsubscribe(); this.templateAndSolutionParticipationSubscription?.unsubscribe(); this.profileInfoSubscription?.unsubscribe(); diff --git a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts index 3f4fa2ad000c..e5710a37db11 100644 --- a/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts +++ b/src/main/webapp/app/exercises/programming/manage/services/programming-exercise.service.ts @@ -675,10 +675,11 @@ export class ProgrammingExerciseService { .pipe(map((res: EntityResponseType) => this.processProgrammingExerciseEntityResponse(res))); } - getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage): Observable { + getCheckoutDirectoriesForProgrammingLanguage(programmingLanguage: ProgrammingLanguage, checkoutSolution: boolean): Observable { return this.http.get(`${this.resourceUrl}/repository-checkout-directories`, { params: { programmingLanguage, + checkoutSolution: checkoutSolution, }, }); } diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 1bd5706f339f..648a2bb59fd8 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -55,6 +55,7 @@ [programmingExercise]="programmingExercise" [programmingLanguage]="programmingExerciseCreationConfig.selectedProgrammingLanguage" [isLocal]="isLocal" + [checkoutSolutionRepository]="programmingExerciseCreationConfig.checkoutSolutionRepositoryAllowed" /> @if (!programmingExerciseCreationConfig.isImportFromExistingExercise && programmingExerciseCreationConfig.auxiliaryRepositoriesSupported) {
    diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index f9e8d275da31..518edfe8a7f4 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -14,6 +14,7 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement @Input() programmingExercise: ProgrammingExercise; @Input() programmingLanguage?: ProgrammingLanguage; @Input() isLocal: boolean; + @Input() checkoutSolutionRepository?: boolean = true; constructor(private programmingExerciseService: ProgrammingExerciseService) {} @@ -32,7 +33,9 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement } ngOnChanges(changes: SimpleChanges) { - if (this.isLocal && changes.programmingLanguage && changes.programmingLanguage.currentValue !== changes.programmingLanguage.previousValue) { + const isProgrammingLanguageUpdated = changes.programmingLanguage?.currentValue !== changes.programmingLanguage.previousValue; + const isCheckoutSolutionRepositoryUpdated = changes.checkoutSolutionRepository?.currentValue !== changes.checkoutSolutionRepository.previousValue; + if (this.isLocal && (isProgrammingLanguageUpdated || isCheckoutSolutionRepositoryUpdated)) { this.updateCheckoutDirectories(); } } @@ -48,8 +51,9 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement this.checkoutDirectorySubscription?.unsubscribe(); // might be defined from previous method execution + const CHECKOUT_SOLUTION_REPOSITORY_DEFAULT = true; this.checkoutDirectorySubscription = this.programmingExerciseService - .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage) + .getCheckoutDirectoriesForProgrammingLanguage(this.programmingLanguage, this.checkoutSolutionRepository ?? CHECKOUT_SOLUTION_REPOSITORY_DEFAULT) .subscribe((checkoutDirectories) => { this.checkoutDirectories = checkoutDirectories; }); diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index c494f719fb95..663a9036a3c0 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -178,7 +178,7 @@ class GetCheckoutDirectoriesTests { @Test void getCheckoutDirectoriesForJava() { - CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.JAVA); + CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.JAVA, true); // Verify submission build plan checkout directories assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); @@ -193,7 +193,7 @@ void getCheckoutDirectoriesForJava() { @Test void getCheckoutDirectoriesForOcaml() { - CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML); + CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML, true); // Verify submission build plan checkout directories assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); @@ -201,9 +201,24 @@ void getCheckoutDirectoriesForOcaml() { assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); // Verify solution build plan checkout directories - assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isNull(); assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment", "/solution" }); assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); } + + @Test + void getCheckoutDirectoriesForOcamlWithoutCheckingOutSolution() { + CheckoutDirectoriesDTO checkoutDirectories = continuousIntegrationService.getCheckoutDirectories(ProgrammingLanguage.OCAML, false); + + // Verify submission build plan checkout directories + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); + + // Verify solution build plan checkout directories + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isNull(); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); + } } } From e7c5bb25210f2ca3dc2823cded72a3a6fa3de36e Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 18:34:55 +0200 Subject: [PATCH 104/117] Fixing reactivity of option not to checkout the solution repository --- .../programming-exercise-information.component.html | 2 +- ...ng-exercise-repository-and-build-plan-details.component.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html index 648a2bb59fd8..e370449b38b4 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html +++ b/src/main/webapp/app/exercises/programming/manage/update/update-components/programming-exercise-information.component.html @@ -55,7 +55,7 @@ [programmingExercise]="programmingExercise" [programmingLanguage]="programmingExerciseCreationConfig.selectedProgrammingLanguage" [isLocal]="isLocal" - [checkoutSolutionRepository]="programmingExerciseCreationConfig.checkoutSolutionRepositoryAllowed" + [checkoutSolutionRepository]="programmingExercise.checkoutSolutionRepository" /> @if (!programmingExerciseCreationConfig.isImportFromExistingExercise && programmingExerciseCreationConfig.auxiliaryRepositoriesSupported) {
    diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 518edfe8a7f4..66ff9fb77f94 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -33,8 +33,8 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement } ngOnChanges(changes: SimpleChanges) { - const isProgrammingLanguageUpdated = changes.programmingLanguage?.currentValue !== changes.programmingLanguage.previousValue; - const isCheckoutSolutionRepositoryUpdated = changes.checkoutSolutionRepository?.currentValue !== changes.checkoutSolutionRepository.previousValue; + const isProgrammingLanguageUpdated = changes.programmingLanguage?.currentValue !== changes.programmingLanguage?.previousValue; + const isCheckoutSolutionRepositoryUpdated = changes.checkoutSolutionRepository?.currentValue !== changes.checkoutSolutionRepository?.previousValue; if (this.isLocal && (isProgrammingLanguageUpdated || isCheckoutSolutionRepositoryUpdated)) { this.updateCheckoutDirectories(); } From 5fc33409fc2b01a3884d6fb716d7dfd8cf655c56 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 18:43:37 +0200 Subject: [PATCH 105/117] Adding javadoc --- .../service/connectors/ci/ContinuousIntegrationService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java index c45d50ff416b..35876ac08e9a 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/ci/ContinuousIntegrationService.java @@ -261,6 +261,7 @@ interface CustomizableCheckoutPath { * Get the checkout directories for the template and submission build plan for a given programming language. * * @param programmingLanguage for which the checkout directories should be retrieved + * @param checkoutSolution whether the checkout solution repository shall be checked out during the template and submission build plan * @return the paths of the checkout directories for the default repositories (exercise, solution, tests) for the * template and submission build plan */ From 2064f0e95cc599adec853e191084a888a4017379 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:11:26 +0200 Subject: [PATCH 106/117] Adjust checkout directory dto, only one possible checkout for solution --- .../connectors/localci/LocalCIService.java | 14 ++++------- .../buildagent/BuildJobExecutionService.java | 16 ++++++------- .../dto/BuildPlanCheckoutDirectoriesDTO.java | 2 +- .../build-plan-checkout-directories-dto.ts | 2 +- ...d-plan-checkout-directories.component.html | 9 ++----- ...ExerciseLocalVCLocalCIIntegrationTest.java | 4 ++-- .../artemis/localvcci/LocalCIServiceTest.java | 12 +++++----- ...and-repositories-preview.component.spec.ts | 24 ++++--------------- 8 files changed, 29 insertions(+), 54 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java index ff8134ea0e1f..4c2dde4578b2 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/LocalCIService.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.Optional; -import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; @@ -240,19 +239,19 @@ private BuildPlanCheckoutDirectoriesDTO getSubmissionBuildPlanCheckoutDirectorie exerciseCheckoutDirectory = startPathWithRootDirectory(exerciseCheckoutDirectory); testCheckoutDirectory = startPathWithRootDirectory(testCheckoutDirectory); - String[] solutionCheckoutDirectories = null; + String solutionCheckoutDirectory = null; if (checkoutSolution) { try { String solutionCheckoutDirectoryPath = ContinuousIntegrationService.RepositoryCheckoutPath.SOLUTION.forProgrammingLanguage(programmingLanguage); - solutionCheckoutDirectories = new String[] { startPathWithRootDirectory(solutionCheckoutDirectoryPath) }; + solutionCheckoutDirectory = startPathWithRootDirectory(solutionCheckoutDirectoryPath); } catch (IllegalArgumentException exception) { // not checked out during template & submission build } } - return new BuildPlanCheckoutDirectoriesDTO(exerciseCheckoutDirectory, solutionCheckoutDirectories, testCheckoutDirectory); + return new BuildPlanCheckoutDirectoriesDTO(exerciseCheckoutDirectory, solutionCheckoutDirectory, testCheckoutDirectory); } private String startPathWithRootDirectory(String checkoutDirectoryPath) { @@ -265,12 +264,9 @@ private String startPathWithRootDirectory(String checkoutDirectoryPath) { } private BuildPlanCheckoutDirectoriesDTO getSolutionBuildPlanCheckoutDirectories(BuildPlanCheckoutDirectoriesDTO submissionBuildPlanCheckoutDirectories) { - String[] solutionCheckoutDirectories = new String[] { submissionBuildPlanCheckoutDirectories.exerciseCheckoutDirectory() }; - if (submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories() != null && submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories().length > 0) { - solutionCheckoutDirectories = ArrayUtils.addAll(solutionCheckoutDirectories, submissionBuildPlanCheckoutDirectories.solutionCheckoutDirectories()); - } + String solutionCheckoutDirectory = submissionBuildPlanCheckoutDirectories.exerciseCheckoutDirectory(); String testCheckoutDirectory = submissionBuildPlanCheckoutDirectories.testCheckoutDirectory(); - return new BuildPlanCheckoutDirectoriesDTO(null, solutionCheckoutDirectories, testCheckoutDirectory); + return new BuildPlanCheckoutDirectoriesDTO(null, solutionCheckoutDirectory, testCheckoutDirectory); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java index 38305201afa3..1baff1ff3f06 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java @@ -101,14 +101,14 @@ public BuildResult runBuildJob(BuildJobQueueItem buildJob, String containerName) buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); // Check if the Docker image is available. If not, pull it. - try { - buildAgentDockerService.pullDockerImage(buildJob, buildLogsMap); - } - catch (LocalCIException e) { - msg = "Could not pull Docker image " + buildJob.buildConfig().dockerImage(); - buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); - throw new LocalCIException(msg, e); - } + // try { + // buildAgentDockerService.pullDockerImage(buildJob, buildLogsMap); + // } + // catch (LocalCIException e) { + // msg = "Could not pull Docker image " + buildJob.buildConfig().dockerImage(); + // buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); + // throw new LocalCIException(msg, e); + // } boolean isPushToTestOrAuxRepository = buildJob.repositoryInfo().triggeredByPushTo() == RepositoryType.TESTS || buildJob.repositoryInfo().triggeredByPushTo() == RepositoryType.AUXILIARY; diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java index 983238158e26..f83aaae3ed2f 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/dto/BuildPlanCheckoutDirectoriesDTO.java @@ -3,6 +3,6 @@ import com.fasterxml.jackson.annotation.JsonInclude; @JsonInclude(JsonInclude.Include.NON_EMPTY) -public record BuildPlanCheckoutDirectoriesDTO(String exerciseCheckoutDirectory, String[] solutionCheckoutDirectories, String testCheckoutDirectory) { +public record BuildPlanCheckoutDirectoriesDTO(String exerciseCheckoutDirectory, String solutionCheckoutDirectory, String testCheckoutDirectory) { } diff --git a/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts b/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts index 7d684ca68b33..73d8d1dec2a2 100644 --- a/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts +++ b/src/main/webapp/app/entities/build-plan-checkout-directories-dto.ts @@ -1,5 +1,5 @@ export class BuildPlanCheckoutDirectoriesDTO { exerciseCheckoutDirectory?: string; - solutionCheckoutDirectories?: string[]; + solutionCheckoutDirectory?: string; testCheckoutDirectory: string; } diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html index 7a3f17bff69f..1f1a5fb736c4 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.html @@ -4,13 +4,8 @@
  • {{ checkoutDirectories.exerciseCheckoutDirectory }}
  • -
  • - @for (directory of checkoutDirectories.solutionCheckoutDirectories; track directory; let index = $index) { - {{ directory }} - @if (index < checkoutDirectories.solutionCheckoutDirectories!.length - 1) { - , - } - } +
  • + {{ checkoutDirectories.solutionCheckoutDirectory }}
  • {{ checkoutDirectories.testCheckoutDirectory }} diff --git a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java index 1b8666476144..71d2206c52c4 100644 --- a/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java +++ b/src/test/java/de/tum/in/www1/artemis/exercise/programming/ProgrammingExerciseLocalVCLocalCIIntegrationTest.java @@ -275,12 +275,12 @@ void testWithValidProgrammingLanguage() throws Exception { CheckoutDirectoriesDTO.class); assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isNull(); assertThat(checkoutDirectoryDTO.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); // Verify solution build plan checkout directories assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); - assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectoryDTO.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); } diff --git a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java index 902f9efc712e..01ed24d0a60f 100644 --- a/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java +++ b/src/test/java/de/tum/in/www1/artemis/localvcci/LocalCIServiceTest.java @@ -182,12 +182,12 @@ void getCheckoutDirectoriesForJava() { // Verify submission build plan checkout directories assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isNull(); assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); // Verify solution build plan checkout directories assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo(null); - assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/"); } @@ -197,12 +197,12 @@ void getCheckoutDirectoriesForOcaml() { // Verify submission build plan checkout directories assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/solution" }); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isEqualTo("/solution"); assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); // Verify solution build plan checkout directories assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isNull(); - assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment", "/solution" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); } @@ -212,12 +212,12 @@ void getCheckoutDirectoriesForOcamlWithoutCheckingOutSolution() { // Verify submission build plan checkout directories assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isEqualTo("/assignment"); - assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isNull(); + assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isNull(); assertThat(checkoutDirectories.submissionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); // Verify solution build plan checkout directories assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().exerciseCheckoutDirectory()).isNull(); - assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectories()).isEqualTo(new String[] { "/assignment" }); + assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().solutionCheckoutDirectory()).isEqualTo("/assignment"); assertThat(checkoutDirectories.solutionBuildPlanCheckoutDirectories().testCheckoutDirectory()).isEqualTo("/tests"); } } diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts index 5a4e603ecf7f..2c727b3d23cd 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts @@ -25,7 +25,7 @@ describe('ProgrammingExerciseBuildDetailsComponent', () => { testCheckoutDirectory: '', }, solutionBuildPlanCheckoutDirectories: { - solutionCheckoutDirectories: ['/assignment'], + solutionCheckoutDirectory: '/assignment', testCheckoutDirectory: '', }, }; @@ -33,11 +33,11 @@ describe('ProgrammingExerciseBuildDetailsComponent', () => { const OCAML_CHECKOUT_DIRECTORIES: CheckoutDirectoriesDto = { submissionBuildPlanCheckoutDirectories: { exerciseCheckoutDirectory: '/assignment', - solutionCheckoutDirectories: ['/solution'], + solutionCheckoutDirectory: '/solution', testCheckoutDirectory: 'tests', }, solutionBuildPlanCheckoutDirectories: { - solutionCheckoutDirectories: ['/assignment', '/solution'], + solutionCheckoutDirectory: '/assignment', testCheckoutDirectory: 'tests', }, }; @@ -150,23 +150,7 @@ describe('ProgrammingExerciseBuildDetailsComponent', () => { // assertion to check if ngOnChanges was executed properly and updated the checkout directories expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); - expect(component.checkoutDirectories?.solutionBuildPlanCheckoutDirectories?.solutionCheckoutDirectories).toEqual(['/assignment', '/solution']); // was ['/assignment'] before with JAVA as programming language - }); - - it('should comma separate the solution directories', () => { - component.ngOnChanges({ - programmingExerciseCreationConfig: { - previousValue: { selectedProgrammingLanguage: ProgrammingLanguage.JAVA }, - currentValue: { selectedProgrammingLanguage: ProgrammingLanguage.OCAML }, - }, - } as unknown as SimpleChanges); - - fixture.detectChanges(); - - const OCAML_SOLUTION_CHECKOUT_DIRECTORY_REGEX = RegExp('.*\\/assignment, *\\/solution.*'); - const solutionPreviewElement = fixture.debugElement.nativeElement.querySelector(CHECKOUT_DIRECTORY_PREVIEW_SOLUTION_BUILD_PLAN); - expect(solutionPreviewElement).toBeTruthy(); - expect(OCAML_SOLUTION_CHECKOUT_DIRECTORY_REGEX.test(solutionPreviewElement.textContent)).toBeTrue(); + expect(component.checkoutDirectories?.submissionBuildPlanCheckoutDirectories?.solutionCheckoutDirectory).toBe('/solution'); // was null before with JAVA as programming language }); it('should update auxiliary repository directories on changes', () => { From e9f36703c0f93b75d6d06be5d7a35c80aa75c01e Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:33:10 +0200 Subject: [PATCH 107/117] Convert component to standalone component --- .../webapp/app/detail-overview-list/detail.module.ts | 6 ++++-- .../update/programming-exercise-update.module.ts | 6 ++++-- .../shared/build-details/build-details.module.ts | 12 ------------ ...cise-build-plan-checkout-directories.component.ts | 1 + ...se-repository-and-build-plan-details.component.ts | 5 +++++ 5 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts diff --git a/src/main/webapp/app/detail-overview-list/detail.module.ts b/src/main/webapp/app/detail-overview-list/detail.module.ts index dccfd2b5d976..217146a1fd88 100644 --- a/src/main/webapp/app/detail-overview-list/detail.module.ts +++ b/src/main/webapp/app/detail-overview-list/detail.module.ts @@ -12,7 +12,8 @@ import { ArtemisProgrammingExerciseLifecycleModule } from 'app/exercises/program import { AssessmentInstructionsModule } from 'app/assessment/assessment-instructions/assessment-instructions.module'; import { IrisModule } from 'app/iris/iris.module'; import { ArtemisModelingEditorModule } from 'app/exercises/modeling/shared/modeling-editor.module'; -import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/programming/shared/build-details/build-details.module'; +import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; @NgModule({ imports: [ @@ -28,7 +29,8 @@ import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/prog AssessmentInstructionsModule, IrisModule, ArtemisModelingEditorModule, - ArtemisProgrammingExerciseBuildDetailsModule, + ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent, + ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, ], declarations: [DetailOverviewListComponent], exports: [DetailOverviewListComponent], diff --git a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts index 15f722a63e7c..d055eb081a39 100644 --- a/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts +++ b/src/main/webapp/app/exercises/programming/manage/update/programming-exercise-update.module.ts @@ -30,7 +30,8 @@ import { AceEditorModule } from 'app/shared/markdown-editor/ace-editor/ace-edito import { ProgrammingExerciseCustomBuildPlanComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-custom-build-plan.component'; import { ProgrammingExerciseDockerImageComponent } from 'app/exercises/programming/manage/update/update-components/custom-build-plans/programming-exercise-docker-image/programming-exercise-docker-image.component'; import { FormsModule } from 'app/forms/forms.module'; -import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/programming/shared/build-details/build-details.module'; +import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; +import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; @NgModule({ imports: [ @@ -54,7 +55,8 @@ import { ArtemisProgrammingExerciseBuildDetailsModule } from 'app/exercises/prog ExerciseUpdatePlagiarismModule, AceEditorModule, FormsModule, - ArtemisProgrammingExerciseBuildDetailsModule, + ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent, + ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, ], declarations: [ ProgrammingExerciseUpdateComponent, diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts b/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts deleted file mode 100644 index 2aac795d74a3..000000000000 --- a/src/main/webapp/app/exercises/programming/shared/build-details/build-details.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { NgModule } from '@angular/core'; -import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; -import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; -import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; -import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; - -@NgModule({ - imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], - declarations: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], - exports: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent], -}) -export class ArtemisProgrammingExerciseBuildDetailsModule {} diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts index 63ac41c2e87d..b11a2a67fa5c 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts @@ -6,6 +6,7 @@ import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary selector: 'jhi-programming-exercise-build-plan-checkout-directories', templateUrl: './programming-exercise-build-plan-checkout-directories.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], + standalone: true, }) export class ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent { @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 66ff9fb77f94..0174374faeb1 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -4,11 +4,16 @@ import type { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/prog import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; import { Subscription } from 'rxjs'; import type { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; +import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; @Component({ selector: 'jhi-programming-exercise-repository-and-build-plan-details', templateUrl: './programming-exercise-repository-and-build-plan-details.component.html', styleUrls: ['../../manage/programming-exercise-form.scss'], + standalone: true, + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule, ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], }) export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implements OnInit, OnChanges, OnDestroy { @Input() programmingExercise: ProgrammingExercise; From 8a433a61e18c63f5a9770c4e16ad4bc15f044032 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:38:53 +0200 Subject: [PATCH 108/117] Use template for build plans aswell --- ...tory-and-build-plan-details.component.html | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index 3c3bd23c57df..2389aa8332aa 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -67,20 +67,22 @@ *ngTemplateOutlet=" repositoryBadge; context: { - helpIconText: 'artemisApp.programmingExercise.preview.testRepoTooltip', + helpIconText: 'artemisApp.programmingExercise.preview.templateBuildPlanTooltip', trailingRepoSlug: '-BASE', customBootstrapClasses: 'bg-primary text-uppercase' } " /> -
  • - - {{ courseShortName }}{{ programmingExercise?.shortName }}-BASE -
  • -
  • - {{ courseShortName }}{{ programmingExercise?.shortName }}-SOLUTION - -
  • +
    } @else if (checkoutDirectories) { From ba91d611ecbefd652474f65e032fb3c6158b5f3b Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:47:20 +0200 Subject: [PATCH 109/117] Undo change for local testing --- .../buildagent/BuildJobExecutionService.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java index 1baff1ff3f06..38305201afa3 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/localci/buildagent/BuildJobExecutionService.java @@ -101,14 +101,14 @@ public BuildResult runBuildJob(BuildJobQueueItem buildJob, String containerName) buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); // Check if the Docker image is available. If not, pull it. - // try { - // buildAgentDockerService.pullDockerImage(buildJob, buildLogsMap); - // } - // catch (LocalCIException e) { - // msg = "Could not pull Docker image " + buildJob.buildConfig().dockerImage(); - // buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); - // throw new LocalCIException(msg, e); - // } + try { + buildAgentDockerService.pullDockerImage(buildJob, buildLogsMap); + } + catch (LocalCIException e) { + msg = "Could not pull Docker image " + buildJob.buildConfig().dockerImage(); + buildLogsMap.appendBuildLogEntry(buildJob.id(), msg); + throw new LocalCIException(msg, e); + } boolean isPushToTestOrAuxRepository = buildJob.repositoryInfo().triggeredByPushTo() == RepositoryType.TESTS || buildJob.repositoryInfo().triggeredByPushTo() == RepositoryType.AUXILIARY; From 1693cc30b90bf5ee41ecf4bbfb38504b8f93c864 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:47:45 +0200 Subject: [PATCH 110/117] Refator reused template method --- ...tory-and-build-plan-details.component.html | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index 2389aa8332aa..a2c102e12504 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -12,7 +12,8 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.templateRepoTooltip', trailingRepoSlug: '-exercise', - customBootstrapClasses: 'bg-primary text-lowercase' + isBuildPlan: false, + isAuxRepo: false } " /> @@ -22,7 +23,8 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.solutionRepoTooltip', trailingRepoSlug: '-solution', - customBootstrapClasses: 'bg-primary text-lowercase' + isBuildPlan: false, + isAuxRepo: false } " /> @@ -32,7 +34,8 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.testRepoTooltip', trailingRepoSlug: '-tests', - customBootstrapClasses: 'bg-primary text-lowercase' + isBuildPlan: false, + isAuxRepo: false } " /> @@ -44,9 +47,9 @@ *ngTemplateOutlet=" repositoryBadge; context: { - helpIconText: 'artemisApp.programmingExercise.preview.testRepoTooltip', trailingRepoSlug: '-' + auxiliaryRepository.name, - customBootstrapClasses: 'bg-success text-lowercase' + isBuildPlan: false, + isAuxRepo: true } " /> @@ -69,7 +72,8 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.templateBuildPlanTooltip', trailingRepoSlug: '-BASE', - customBootstrapClasses: 'bg-primary text-uppercase' + isBuildPlan: true, + isAuxRepo: false } " /> @@ -79,7 +83,8 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.solutionBuildPlanTooltip', trailingRepoSlug: '-SOLUTION', - customBootstrapClasses: 'bg-primary text-uppercase' + isBuildPlan: true, + isAuxRepo: false } " /> @@ -109,9 +114,13 @@ }
    - +
  • - {{ courseShortName }}{{ programmingExercise?.shortName }}{{ trailingRepoSlug }} - + + {{ courseShortName }}{{ programmingExercise?.shortName }}{{ trailingRepoSlug }} + + @if (helpIconText) { + + }
  • From bea607c4191015ec1b024ba022df32c568e56a1c Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:50:30 +0200 Subject: [PATCH 111/117] Simplify usage of template --- ...tory-and-build-plan-details.component.html | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index a2c102e12504..7ea458537256 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -11,9 +11,7 @@ repositoryBadge; context: { helpIconText: 'artemisApp.programmingExercise.preview.templateRepoTooltip', - trailingRepoSlug: '-exercise', - isBuildPlan: false, - isAuxRepo: false + trailingRepoSlug: '-exercise' } " /> @@ -22,9 +20,7 @@ repositoryBadge; context: { helpIconText: 'artemisApp.programmingExercise.preview.solutionRepoTooltip', - trailingRepoSlug: '-solution', - isBuildPlan: false, - isAuxRepo: false + trailingRepoSlug: '-solution' } " /> @@ -33,28 +29,23 @@ repositoryBadge; context: { helpIconText: 'artemisApp.programmingExercise.preview.testRepoTooltip', - trailingRepoSlug: '-tests', - isBuildPlan: false, - isAuxRepo: false + trailingRepoSlug: '-tests' } " /> @if (programmingExercise?.auxiliaryRepositories?.length) { -
    - @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) { - - } -
    + @for (auxiliaryRepository of programmingExercise!.auxiliaryRepositories; track auxiliaryRepository) { + + } } @@ -72,8 +63,7 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.templateBuildPlanTooltip', trailingRepoSlug: '-BASE', - isBuildPlan: true, - isAuxRepo: false + isBuildPlan: true } " /> @@ -83,8 +73,7 @@ context: { helpIconText: 'artemisApp.programmingExercise.preview.solutionBuildPlanTooltip', trailingRepoSlug: '-SOLUTION', - isBuildPlan: true, - isAuxRepo: false + isBuildPlan: true } " /> From 9387f8d881b560967681bcceaf4b6768813d0312 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 21:54:22 +0200 Subject: [PATCH 112/117] Make coderabbit happy --- ...amming-exercise-build-plan-checkout-directories.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts index b11a2a67fa5c..4bcffecaa5af 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component.ts @@ -12,5 +12,5 @@ export class ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent { @Input() checkoutDirectories?: BuildPlanCheckoutDirectoriesDTO; @Input() auxiliaryRepositories: AuxiliaryRepository[]; - ROOT_DIRECTORY_PATH: string = '/'; + ROOT_DIRECTORY_PATH = '/'; } From dd43e5e8a854258d74ffa1bc51b61a66bf90d192 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Tue, 28 May 2024 22:11:17 +0200 Subject: [PATCH 113/117] Remove margin left --- ...ng-exercise-repository-and-build-plan-details.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html index 7ea458537256..53b0300ab054 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.html @@ -1,4 +1,4 @@ -
    +
    From f7613ceee6fa5d1eae679671a9e12cab3429be22 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 29 May 2024 14:28:44 +0200 Subject: [PATCH 114/117] Address Patrik's review --- ...xercise-repository-and-build-plan-details.component.spec.ts} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/test/javascript/spec/component/programming-exercise/{programming-exercise-plans-and-repositories-preview.component.spec.ts => programming-exercise-repository-and-build-plan-details.component.spec.ts} (99%) diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts similarity index 99% rename from src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts rename to src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts index 2c727b3d23cd..320263681375 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-plans-and-repositories-preview.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts @@ -11,7 +11,7 @@ import { SimpleChanges } from '@angular/core'; import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; -describe('ProgrammingExerciseBuildDetailsComponent', () => { +describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { let component: ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent; let fixture: ComponentFixture; let programmingExerciseService: ProgrammingExerciseService; From cb580d04bd66593db0ebb9d0c9327b93d424520c Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 29 May 2024 14:30:37 +0200 Subject: [PATCH 115/117] Address Patrik's review --- ...mming-exercise-repository-and-build-plan-details.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts index 0174374faeb1..30021b146f48 100644 --- a/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts +++ b/src/main/webapp/app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component.ts @@ -27,7 +27,6 @@ export class ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent implement courseShortName?: string; checkoutDirectories?: CheckoutDirectoriesDto; - auxiliaryRepositoryCheckoutDirectories: string[] = []; ngOnInit() { this.updateCourseShortName(); From 63aaf6038115d4fd7666c1d767b8840e656d8d77 Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 29 May 2024 14:34:36 +0200 Subject: [PATCH 116/117] Address Patrik's review --- .../ProgrammingExerciseResource.java | 3 + ...y-and-build-plan-details.component.spec.ts | 62 ++++++++++++++++--- .../mock-programming-exercise.service.ts | 2 +- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java index 61cbb7fb0182..a3013e07ae10 100644 --- a/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java +++ b/src/main/java/de/tum/in/www1/artemis/web/rest/programming/ProgrammingExerciseResource.java @@ -882,6 +882,9 @@ public ResponseEntity getBuildLogStatistics(@PathVariable /** * GET programming-exercises/repository-checkout-directories * + * @param programmingLanguage for which the checkout directories should be retrieved + * @param checkoutSolution whether the checkout solution repository shall be checked out during the template and submission build plan, + * if not supplied set to true as default * @return a DTO containing the checkout directories for the exercise, solution, and tests repository * for the requested programming language for the submission and solution build. */ diff --git a/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts b/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts index 320263681375..ccc542ea3ec5 100644 --- a/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts +++ b/src/test/javascript/spec/component/programming-exercise/programming-exercise-repository-and-build-plan-details.component.spec.ts @@ -1,6 +1,5 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ProgrammingExerciseService } from 'app/exercises/programming/manage/services/programming-exercise.service'; -import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; import { CheckoutDirectoriesDto } from 'app/entities/checkout-directories-dto'; import { ProgrammingExercise, ProgrammingLanguage } from 'app/entities/programming-exercise.model'; import { HelpIconComponent } from 'app/shared/components/help-icon.component'; @@ -10,6 +9,11 @@ import { AuxiliaryRepository } from 'app/entities/programming-exercise-auxiliary import { SimpleChanges } from '@angular/core'; import { ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-build-plan-checkout-directories.component'; import { ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent } from 'app/exercises/programming/shared/build-details/programming-exercise-repository-and-build-plan-details.component'; +import { ArtemisSharedComponentModule } from 'app/shared/components/shared-component.module'; +import { ArtemisSharedCommonModule } from 'app/shared/shared-common.module'; +import { MockTranslateService } from '../../helpers/mocks/service/mock-translate.service'; +import { TranslateService } from '@ngx-translate/core'; +import { MockProgrammingExerciseService } from '../../helpers/mocks/service/mock-programming-exercise.service'; describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { let component: ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent; @@ -42,10 +46,25 @@ describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { }, }; + const OCAML_CHECKOUT_DIRECTORIES_WITHOUT_SOLUTION_CHECKOUT: CheckoutDirectoriesDto = { + submissionBuildPlanCheckoutDirectories: { + exerciseCheckoutDirectory: '/assignment', + testCheckoutDirectory: 'tests', + }, + solutionBuildPlanCheckoutDirectories: { + solutionCheckoutDirectory: '/assignment', + testCheckoutDirectory: 'tests', + }, + }; + beforeEach(() => { TestBed.configureTestingModule({ declarations: [ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent, MockComponent(HelpIconComponent), ProgrammingExerciseBuildPlanCheckoutDirectoriesComponent], - providers: [{ provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }], + imports: [ArtemisSharedComponentModule, ArtemisSharedCommonModule], + providers: [ + { provide: ProgrammingExerciseService, useClass: MockProgrammingExerciseService }, + { provide: TranslateService, useClass: MockTranslateService }, + ], }) .compileComponents() .then(() => { @@ -57,13 +76,19 @@ describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { component.programmingExercise = { id: 1, shortName: 'shortName' } as ProgrammingExercise; component.isLocal = true; - jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockImplementation((programmingLanguage: ProgrammingLanguage) => { - if (programmingLanguage === ProgrammingLanguage.JAVA) { - return of(JAVA_CHECKOUT_DIRECTORIES); - } + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage').mockImplementation( + (programmingLanguage: ProgrammingLanguage, checkoutSolution: boolean) => { + if (programmingLanguage === ProgrammingLanguage.JAVA) { + return of(JAVA_CHECKOUT_DIRECTORIES); + } - return of(OCAML_CHECKOUT_DIRECTORIES); - }); + if (programmingLanguage === ProgrammingLanguage.OCAML && !checkoutSolution) { + return of(OCAML_CHECKOUT_DIRECTORIES_WITHOUT_SOLUTION_CHECKOUT); + } + + return of(OCAML_CHECKOUT_DIRECTORIES); + }, + ); }); }); @@ -141,6 +166,7 @@ describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { it('should update checkout directories when selectedProgrammingLanguage changes', () => { jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); + component.programmingLanguage = ProgrammingLanguage.OCAML; component.ngOnChanges({ programmingLanguage: { previousValue: ProgrammingLanguage.JAVA, @@ -149,10 +175,28 @@ describe('ProgrammingExerciseRepositoryAndBuildPlanDetailsComponent', () => { } as unknown as SimpleChanges); // assertion to check if ngOnChanges was executed properly and updated the checkout directories - expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalled(); + expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalledWith(ProgrammingLanguage.OCAML, true); expect(component.checkoutDirectories?.submissionBuildPlanCheckoutDirectories?.solutionCheckoutDirectory).toBe('/solution'); // was null before with JAVA as programming language }); + it('should update checkout directories when checkoutSolution flag changes', () => { + jest.spyOn(programmingExerciseService, 'getCheckoutDirectoriesForProgrammingLanguage'); + + component.programmingLanguage = ProgrammingLanguage.OCAML; + component.checkoutSolutionRepository = false; + component.ngOnChanges({ + checkoutSolutionRepository: { + previousValue: true, + currentValue: false, + }, + } as unknown as SimpleChanges); + + // assertion to check if ngOnChanges was executed properly and updated the checkout directories + expect(programmingExerciseService.getCheckoutDirectoriesForProgrammingLanguage).toHaveBeenCalledWith(ProgrammingLanguage.OCAML, false); + // solution checkout directory was /solution before with OCaml as programming language and solution checkout allowed + expect(component.checkoutDirectories?.submissionBuildPlanCheckoutDirectories?.solutionCheckoutDirectory).toBeUndefined(); + }); + it('should update auxiliary repository directories on changes', () => { fixture.detectChanges(); diff --git a/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts b/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts index 471ad340d827..d897194809fd 100644 --- a/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts +++ b/src/test/javascript/spec/helpers/mocks/service/mock-programming-exercise.service.ts @@ -27,5 +27,5 @@ export class MockProgrammingExerciseService { generateStructureOracle = (exerciseId: number) => of({}); unlockAllRepositories = (exerciseId: number) => of({}); getDiffReportForCommits = (exerciseId: number, participationId: number, olderCommitHash: string, newerCommitHash: string, repositoryType: string) => of({}); - getCheckoutDirectoriesForProgrammingLanguage = (programmingLanguage: ProgrammingLanguage) => of(); + getCheckoutDirectoriesForProgrammingLanguage = (programmingLanguage: ProgrammingLanguage, checkoutSolution: boolean) => of(); } From ba3a6351819a95b4ef5a5d9740ad2e128863d19c Mon Sep 17 00:00:00 2001 From: Florian Glombik Date: Wed, 29 May 2024 16:50:39 +0200 Subject: [PATCH 117/117] Adress feedback from Aniruddh --- .../artemis/service/connectors/gitlabci/GitLabCIService.java | 2 +- .../www1/artemis/service/connectors/jenkins/JenkinsService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java index 7a0c184a9dee..f338a26e910f 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/gitlabci/GitLabCIService.java @@ -327,6 +327,6 @@ public Optional getWebHookUrl(String projectKey, String buildPlanId) { @Override public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { - throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for the checkout directories."); + throw new UnsupportedOperationException("Method not implemented, consult the build plans in GitLab for more information on the checkout directories."); } } diff --git a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java index 7ee8bc512f6d..5f251df9de94 100644 --- a/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java +++ b/src/main/java/de/tum/in/www1/artemis/service/connectors/jenkins/JenkinsService.java @@ -257,6 +257,6 @@ public void createProjectForExercise(ProgrammingExercise programmingExercise) th @Override public CheckoutDirectoriesDTO getCheckoutDirectories(ProgrammingLanguage programmingLanguage, boolean checkoutSolution) { - throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for the checkout directories."); + throw new UnsupportedOperationException("Method not implemented, consult the build plans in Jenkins for more information on the checkout directories."); } }