Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Programming exercises: Add online IDE settings #8965

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
7a1ee41
Add Theia spring profile and configuration file
iyannsch May 28, 2024
3ff2d16
Add InfoContributor for sharing Theia information with client
iyannsch May 28, 2024
ab1cfca
Add button to open online iDE in exercise details for students
iyannsch May 28, 2024
5b54ac1
Switch from href usage to explicit Theia start function
iyannsch May 29, 2024
11e6396
Add german translation
iyannsch May 29, 2024
215d840
Clean up theia portal logic and add future work
iyannsch May 29, 2024
87d9c35
Prevent missing theia config files from crashing Artemis
iyannsch May 29, 2024
96988cb
Remove default values for theiaPortalURL
iyannsch May 30, 2024
ab37268
Add theiaPortalURL to profile test suite
iyannsch May 30, 2024
44896b3
Fix hard-coded client-side test
iyannsch Jun 4, 2024
e4af6f0
Add server-side test to cover TheiaInfoContributor
iyannsch Jun 6, 2024
dbbfa1c
Add server-side test to cover TheiaInfoContributor
iyannsch Jun 6, 2024
236011d
Add tests for checking the visibility of the Theia start button
iyannsch Jun 6, 2024
296fd2f
Combined test suite for client tests
iyannsch Jun 6, 2024
74666c5
Merge remote-tracking branch 'origin/develop' into feature/programmin…
iyannsch Jun 24, 2024
bdb00e1
Use exemplary values in configuration
iyannsch Jun 24, 2024
4eb4919
Remove future work comments
iyannsch Jun 24, 2024
8e5fb20
Fix order of execution in IntelliJ theia profile
iyannsch Jun 24, 2024
6edc158
Merge branch 'feature/programming-exercises/add-online-ide-button-to-…
iyannsch Jun 26, 2024
1b80c87
Not-working TheiaConfiguration
iyannsch Jun 27, 2024
ec36309
fix autowiring of TheiaConfiguration in Test
b-fein Jun 27, 2024
c855543
Add Server-Side endpoints for providing available Theia images
iyannsch Jun 27, 2024
86f88c8
Add Server-Side endpoints for providing available Theia images
iyannsch Jun 27, 2024
277bb1a
Refactor for Server-Side Tests
iyannsch Jun 27, 2024
6d66718
Refactor for Server-Side Tests
iyannsch Jun 27, 2024
4dd891d
Add Online-IDE Selection for exercise creation
iyannsch Jun 28, 2024
78d5d64
Add Theia Configuration to DB
iyannsch Jul 1, 2024
62de8b7
Make IDE selection almost work for both creation and modification
iyannsch Jul 1, 2024
0aba231
Ensure consistent TheiaImage Saving
iyannsch Jul 2, 2024
64b29f5
Show Status of Online IDE Settings in exercise details
iyannsch Jul 3, 2024
46f2772
Stop online IDE settings from appearing in exam programming exercises
iyannsch Jul 3, 2024
2af8afc
Add online IDE status to exercise overview
iyannsch Jul 3, 2024
56983ab
Add client test for exercise-update component
iyannsch Jul 3, 2024
88f3ea9
Add client test for programming-exercise component
iyannsch Jul 3, 2024
390bd94
Enforce Instructor for getting Theia Image Configuration
iyannsch Jul 3, 2024
d49baa5
Incorporate typing feedback
iyannsch Jul 4, 2024
a4016d5
Change Boolean type to boolean in ProgrammingExercise changes
iyannsch Jul 4, 2024
3126462
Change access modifier and access according to feedback
iyannsch Jul 4, 2024
a2e08d1
Clear-cut test with NullpointerException
iyannsch Jul 4, 2024
fc20712
Make TheiaUpdateComponent standalone
iyannsch Jul 5, 2024
732da05
Add default value of allowOnlineIde for existing DB entries
iyannsch Jul 9, 2024
af3a386
Revert Standalone Module to fix unknown-pipe error
iyannsch Jul 9, 2024
fa88ec2
Use typed ProgrammingLanguage for TheiaImage endpoint
iyannsch Jul 9, 2024
02e8b24
Add ResponseEntity to server endpoint as demanded by tests
iyannsch Jul 9, 2024
1fd7d10
Merge develop into branch
iyannsch Jul 9, 2024
910aa58
Add client tests for theia and language component
iyannsch Jul 10, 2024
a5622b0
Fix boolean type
iyannsch Jul 10, 2024
3fe0c04
Improve tests and code style according to @b-fein
iyannsch Jul 10, 2024
728c517
Fix german translation typo
iyannsch Jul 10, 2024
152f561
Change old translation pipe to new and implement @JohannesWt feedback
iyannsch Jul 11, 2024
94c0487
Fix group-cell test and translation injection
iyannsch Jul 11, 2024
5809979
Add check to only show start button when Theia is enabled and configu…
iyannsch Jul 17, 2024
169b514
Add tests for new start button properties
iyannsch Jul 17, 2024
856825a
Merge Code button etc from develop
iyannsch Jul 19, 2024
f2cc698
Merge develop into branch
iyannsch Aug 6, 2024
b515ef8
Make update theia component standalone
iyannsch Aug 8, 2024
792b30b
Fix imports for standalone component
iyannsch Aug 8, 2024
851bc8f
Merge branch 'refs/heads/develop' into feature/programming-exercises/…
iyannsch Aug 12, 2024
4ffaf96
Merge migration changes from #8897
iyannsch Aug 12, 2024
69a3c12
Fix tests
iyannsch Aug 12, 2024
e49688d
Hide checkbox for allowing online Ide when THEIA profile is not active
iyannsch Aug 12, 2024
c495cd1
Fix tests
iyannsch Aug 12, 2024
873bcf7
Fix forced non-null operator
iyannsch Aug 12, 2024
30fcb28
Add better error message when theia profile is not activated
iyannsch Aug 26, 2024
4a2b91e
Move label to language component and remove Autowired
iyannsch Aug 26, 2024
9361786
Merge branch 'refs/heads/develop' into feature/programming-exercises/…
iyannsch Aug 26, 2024
c45298a
Sanitize participation modes properly in the server
iyannsch Aug 26, 2024
6eedb5e
Fix profileInfo mismatching contents
iyannsch Aug 26, 2024
2434459
Try to fix bamboo error of not finding activeProfiles in programming-…
iyannsch Aug 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/main/java/de/tum/in/www1/artemis/ArtemisApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@
import org.springframework.core.env.Environment;

import de.tum.in.www1.artemis.config.ProgrammingLanguageConfiguration;
import de.tum.in.www1.artemis.config.TheiaConfiguration;
import tech.jhipster.config.DefaultProfileUtil;
import tech.jhipster.config.JHipsterConstants;

@SpringBootApplication
@EnableConfigurationProperties({ LiquibaseProperties.class, ProgrammingLanguageConfiguration.class })
@EnableConfigurationProperties({ LiquibaseProperties.class, ProgrammingLanguageConfiguration.class, TheiaConfiguration.class })
public class ArtemisApp {

private static final Logger log = LoggerFactory.getLogger(ArtemisApp.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package de.tum.in.www1.artemis.config;

import static de.tum.in.www1.artemis.config.Constants.PROFILE_THEIA;
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage;

@Profile(PROFILE_THEIA)
@Configuration
@ConfigurationProperties(prefix = "theia")
public class TheiaConfiguration {

private Map<ProgrammingLanguage, Map<String, String>> images;
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

public void setImages(final Map<ProgrammingLanguage, Map<String, String>> images) {
this.images = images;
}
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

/**
* Get the images for all languages
*
* @return a map of language -> [flavor/name -> image-link]
*/
public Map<ProgrammingLanguage, Map<String, String>> getImagesForAllLanguages() {
return images;
}

/**
* Get the images for a specific language
*
* @param language the language for which the images should be retrieved
* @return a map of flavor/name -> image-link
*/
public Map<String, String> getImagesForLanguage(ProgrammingLanguage language) {
return images.get(language);
}
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

}
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,9 @@ public String toString() {
public void validateProgrammingSettings() {

// Check if a participation mode was selected
if (!Boolean.TRUE.equals(isAllowOnlineEditor()) && !Boolean.TRUE.equals(isAllowOfflineIde())) {
throw new BadRequestAlertException("You need to allow at least one participation mode, the online editor or the offline IDE", "Exercise", "noParticipationModeAllowed");
if (!Boolean.TRUE.equals(isAllowOnlineEditor()) && !Boolean.TRUE.equals(isAllowOfflineIde()) && !isAllowOnlineIde()) {
throw new BadRequestAlertException("You need to allow at least one participation mode, the online editor, the offline IDE, or the online IDE", "Exercise",
"noParticipationModeAllowed");
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
}

// Check if Xcode has no online code editor enabled
Expand All @@ -745,6 +746,11 @@ public void validateProgrammingSettings() {
if (getProgrammingLanguage() == null) {
throw new BadRequestAlertException("No programming language was specified", "Exercise", "programmingLanguageNotSet");
}

// Check if theia image was selected if the online IDE is enabled
if (isAllowOnlineIde() && buildConfig.getTheiaImage() == null) {
throw new BadRequestAlertException("The Theia image must be selected if the online IDE is enabled", "Exercise", "theiaImageNotSet");
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.tum.in.www1.artemis.web.rest.programming;

import static de.tum.in.www1.artemis.config.Constants.PROFILE_CORE;
import static de.tum.in.www1.artemis.config.Constants.PROFILE_THEIA;

import java.io.IOException;
import java.net.URI;
Expand All @@ -18,6 +19,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
Expand Down Expand Up @@ -89,6 +91,7 @@
import de.tum.in.www1.artemis.web.rest.errors.EntityNotFoundException;
import de.tum.in.www1.artemis.web.rest.util.HeaderUtil;
import de.tum.in.www1.artemis.web.websocket.dto.ProgrammingExerciseTestCaseStateDTO;
import io.jsonwebtoken.lang.Arrays;

/**
* REST controller for managing ProgrammingExercise.
Expand Down Expand Up @@ -151,6 +154,8 @@ public class ProgrammingExerciseResource {

private final Optional<AthenaModuleService> athenaModuleService;

private final Environment environment;

public ProgrammingExerciseResource(ProgrammingExerciseRepository programmingExerciseRepository, ProgrammingExerciseTestCaseRepository programmingExerciseTestCaseRepository,
UserRepository userRepository, AuthorizationCheckService authCheckService, CourseService courseService,
Optional<ContinuousIntegrationService> continuousIntegrationService, Optional<VersionControlService> versionControlService, ExerciseService exerciseService,
Expand All @@ -160,7 +165,8 @@ public ProgrammingExerciseResource(ProgrammingExerciseRepository programmingExer
GradingCriterionRepository gradingCriterionRepository, CourseRepository courseRepository, GitService gitService, AuxiliaryRepositoryService auxiliaryRepositoryService,
SolutionProgrammingExerciseParticipationRepository solutionProgrammingExerciseParticipationRepository,
TemplateProgrammingExerciseParticipationRepository templateProgrammingExerciseParticipationRepository,
BuildLogStatisticsEntryRepository buildLogStatisticsEntryRepository, ChannelRepository channelRepository, Optional<AthenaModuleService> athenaModuleService) {
BuildLogStatisticsEntryRepository buildLogStatisticsEntryRepository, ChannelRepository channelRepository, Optional<AthenaModuleService> athenaModuleService,
Environment environment) {
this.programmingExerciseTaskService = programmingExerciseTaskService;
this.programmingExerciseRepository = programmingExerciseRepository;
this.programmingExerciseTestCaseRepository = programmingExerciseTestCaseRepository;
Expand All @@ -184,6 +190,7 @@ public ProgrammingExerciseResource(ProgrammingExerciseRepository programmingExer
this.buildLogStatisticsEntryRepository = buildLogStatisticsEntryRepository;
this.channelRepository = channelRepository;
this.athenaModuleService = athenaModuleService;
this.environment = environment;
}

/**
Expand Down Expand Up @@ -303,9 +310,26 @@ public ResponseEntity<ProgrammingExercise> updateProgrammingExercise(@RequestBod
updatedProgrammingExercise.getBuildConfig().isTestwiseCoverageEnabled())) {
throw new BadRequestAlertException("Testwise coverage enabled flag must not be changed", ENTITY_NAME, "testwiseCoverageCannotChange");
}
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
if (!Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOnlineEditor()) && !Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOfflineIde())) {
return ResponseEntity.badRequest().headers(HeaderUtil.createAlert(applicationName,
"You need to allow at least one participation mode, the online editor or the offline IDE", "noParticipationModeAllowed")).body(null);
// Check if theia Profile is enabled
if (Arrays.asList(this.environment.getActiveProfiles()).contains(PROFILE_THEIA)) {
// Require 1 / 3 participation modes to be enabled
if (!Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOnlineEditor()) && !Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOfflineIde())
&& !updatedProgrammingExercise.isAllowOnlineIde()) {
throw new BadRequestAlertException("You need to allow at least one participation mode, the online editor, the offline IDE, or the online IDE", ENTITY_NAME,
"noParticipationModeAllowed");
}
}
else {
// Require 1 / 2 participation modes to be enabled
if (!Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOnlineEditor()) && !Boolean.TRUE.equals(updatedProgrammingExercise.isAllowOfflineIde())) {
throw new BadRequestAlertException("You need to allow at least one participation mode, the online editor or the offline IDE", ENTITY_NAME,
"noParticipationModeAllowed");
}
}
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

// Verify that a theia image is provided when the online IDE is enabled
if (updatedProgrammingExercise.isAllowOnlineIde() && updatedProgrammingExercise.getBuildConfig().getTheiaImage() == null) {
throw new BadRequestAlertException("You need to provide a Theia image when the online IDE is enabled", ENTITY_NAME, "noTheiaImageProvided");
b-fein marked this conversation as resolved.
Show resolved Hide resolved
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
}
// Forbid changing the course the exercise belongs to.
if (!Objects.equals(programmingExerciseBeforeUpdate.getCourseViaExerciseGroupOrCourseMember().getId(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.tum.in.www1.artemis.web.rest.theia;

import static de.tum.in.www1.artemis.config.Constants.PROFILE_THEIA;
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

import java.util.Map;

import org.springframework.context.annotation.Profile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import de.tum.in.www1.artemis.config.TheiaConfiguration;
import de.tum.in.www1.artemis.domain.enumeration.ProgrammingLanguage;
import de.tum.in.www1.artemis.security.annotations.EnforceAtLeastInstructor;

@Profile(PROFILE_THEIA)
@RestController
@RequestMapping("api/theia/")
public class TheiaConfigurationResource {

private final TheiaConfiguration theiaConfiguration;

public TheiaConfigurationResource(TheiaConfiguration theiaConfiguration) {
this.theiaConfiguration = theiaConfiguration;
}

/**
* GET /api/theia/images?language=<language>: Get the images for a specific language
*
* @param language the language for which the images should be retrieved
* @return a map of flavor/name -> image-link
*/
@GetMapping("images")
@EnforceAtLeastInstructor
public ResponseEntity<Map<String, String>> getImagesForLanguage(@RequestParam("language") ProgrammingLanguage language) {
return ResponseEntity.ok(this.theiaConfiguration.getImagesForLanguage(language));
}

}
11 changes: 10 additions & 1 deletion src/main/resources/config/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,13 @@ eureka:

# Theia configuration
theia:
portal-url: https://theia-test.k8s.ase.cit.tum.de
portal-url: https://theia-test.k8s.ase.cit.tum.de

images:
java:
Java-17: "ghcr.io/ls1intum/theia/java-17:latest"
Java-Test: "ghcr.io/ls1intum/theia/java-test:latest"
Java-Test2: "ghcr.io/ls1intum/theia/java-test:2"
c:
C: "ghcr.io/ls1intum/theia/c:latest"

13 changes: 12 additions & 1 deletion src/main/resources/config/application-theia.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
theia:
portal-url: https://your-theia-instance.com
portal-url: https://your-theia-instance.com

# Theia IDE images available for the different programming languages
images:
# Upper level key is the language category (must match the language key in the programming-exercise configuration)
java:
# Lower level key can be multiple flavors of the image, e.g. version, tag, or additional dependencies
Java-17: "my-registry/my-image:my-tag"
# Add more flavors here (e.g. Java-11, Java-8, etc.)
# Add more languages here (e.g. c, python, etc.)
c:
C: "my-registry/my-image:my-tag"
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions src/main/webapp/app/entities/programming-exercise.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export class ProgrammingExerciseBuildConfig {
public dockerFlags?: string;
public windfile?: WindFile;
public testwiseCoverageEnabled?: boolean;
public theiaImage?: string;
iyannsch marked this conversation as resolved.
Show resolved Hide resolved

constructor() {
this.checkoutSolutionRepository = false; // default value
Expand Down Expand Up @@ -113,6 +114,7 @@ export class ProgrammingExercise extends Exercise {
*/
public maxStaticCodeAnalysisPenalty?: number;
public allowOfflineIde?: boolean;
public allowOnlineIde?: boolean;
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
public programmingLanguage?: ProgrammingLanguage;
public packageName?: string;
public showTestNamesToStudents?: boolean;
Expand Down Expand Up @@ -147,6 +149,7 @@ export class ProgrammingExercise extends Exercise {
this.templateParticipation = new TemplateProgrammingExerciseParticipation();
this.solutionParticipation = new SolutionProgrammingExerciseParticipation();
this.allowOnlineEditor = false; // default value
this.allowOnlineIde = false; // default value
this.staticCodeAnalysisEnabled = false; // default value
this.allowOfflineIde = true; // default value
this.programmingLanguage = ProgrammingLanguage.JAVA; // default value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,13 @@
@if (displayEditorModus) {
<div>
<div class="d-flex justify-content-between">
{{ 'artemisApp.programmingExercise.offlineIde' | artemisTranslate }}
: {{ programmingExercise.allowOfflineIde || false }}
<span jhiTranslate="'artemisApp.programmingExercise.offlineIde'">: {{ programmingExercise.allowOfflineIde || false }}</span>
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div class="d-flex justify-content-between">
{{ 'artemisApp.programmingExercise.onlineEditor' | artemisTranslate }}
: {{ programmingExercise.allowOnlineEditor || false }}
<span jhiTranslate="'artemisApp.programmingExercise.onlineEditor'">: {{ programmingExercise.allowOnlineEditor || false }}</span>
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
</div>
<div class="d-flex justify-content-between">
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
<span jhiTranslate="'artemisApp.programmingExercise.onlineIde'">: {{ programmingExercise.allowOnlineIde || false }}</span>
iyannsch marked this conversation as resolved.
Show resolved Hide resolved
</div>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,17 @@ export class ProgrammingExerciseDetailComponent implements OnInit, OnDestroy {
{
type: DetailType.Boolean,
title: 'artemisApp.programmingExercise.allowOfflineIde.title',
data: { boolean: exercise.allowOfflineIde },
data: { boolean: exercise.allowOfflineIde ?? false },
},
{
type: DetailType.Boolean,
title: 'artemisApp.programmingExercise.allowOnlineEditor.title',
data: { boolean: exercise.allowOnlineEditor },
data: { boolean: exercise.allowOnlineEditor ?? false },
},
{
type: DetailType.Boolean,
title: 'artemisApp.programmingExercise.allowOnlineIde.title',
data: { boolean: exercise.allowOnlineIde ?? false },
},
],
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,16 @@
}
<td class="d-md-table-cell">
<div class="d-flex justify-content-between">
{{ 'artemisApp.programmingExercise.offlineIde' | artemisTranslate }}:
{{ programmingExercise.allowOfflineIde ? ('artemisApp.exercise.yes' | artemisTranslate) : ('artemisApp.exercise.no' | artemisTranslate) }}
<span [jhiTranslate]="'artemisApp.programmingExercise.offlineIde'"></span>:
<span [jhiTranslate]="programmingExercise.allowOfflineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
<div class="d-flex justify-content-between">
{{ 'artemisApp.programmingExercise.onlineEditor' | artemisTranslate }}:
{{ programmingExercise.allowOnlineEditor ? ('artemisApp.exercise.yes' | artemisTranslate) : ('artemisApp.exercise.no' | artemisTranslate) }}
<span [jhiTranslate]="'artemisApp.programmingExercise.onlineEditor'"></span>:
<span [jhiTranslate]="programmingExercise.allowOnlineEditor ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
<div class="d-flex justify-content-between">
<span [jhiTranslate]="'artemisApp.programmingExercise.onlineIde'"></span>:
<span [jhiTranslate]="programmingExercise.allowOnlineIde ? 'artemisApp.exercise.yes' : 'artemisApp.exercise.no'"></span>
</div>
</td>
@if (course.presentationScore !== 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type ProgrammingExerciseCreationConfig = {
hasUnsavedChanges: boolean;
rerenderSubject: Observable<void>;
validIdeSelection: () => boolean | undefined;
validOnlineIdeSelection: () => boolean | undefined;
inProductionEnvironment: boolean;
recreateBuildPlans: boolean;
onRecreateBuildPlanOrUpdateTemplateChange: () => void;
Expand Down
Loading
Loading