diff --git a/backend/packages/Upgrade/.env.docker.local.example b/backend/packages/Upgrade/.env.docker.local.example index 0ac7b3e52..2ceabef31 100644 --- a/backend/packages/Upgrade/.env.docker.local.example +++ b/backend/packages/Upgrade/.env.docker.local.example @@ -78,7 +78,7 @@ EMAIL_BUCKET="s3_bucket" # Mooclets # -MOOCLETS_ENABLED = true/false +MOOCLETS_ENABLED = false MOOCLETS_HOST_URL = mooclet_host_url MOOCLETS_API_ROUTE = /engine/api/v1 MOOCLETS_API_TOKEN = some_token diff --git a/backend/packages/Upgrade/src/api/controllers/ExperimentController.ts b/backend/packages/Upgrade/src/api/controllers/ExperimentController.ts index 8011cdfac..dea8c7a4e 100644 --- a/backend/packages/Upgrade/src/api/controllers/ExperimentController.ts +++ b/backend/packages/Upgrade/src/api/controllers/ExperimentController.ts @@ -29,6 +29,7 @@ import { MoocletExperimentService } from '../services/MoocletExperimentService'; import { env } from '../../env'; import { NotFoundException } from '@nestjs/common/exceptions'; import { ExperimentIdValidator } from '../DTO/ExperimentDTO'; +import { SUPPORTED_MOOCLET_ALGORITHMS } from 'upgrade_types'; interface ExperimentPaginationInfo extends PaginationResponse { nodes: Experiment[]; @@ -828,11 +829,24 @@ export class ExperimentController { */ @Get('/single/:id') @OnUndefined(ExperimentNotFoundError) - public one( + public async one( @Params({ validate: true }) { id }: ExperimentIdValidator, @Req() request: AppRequest ): Promise { - return this.experimentService.getSingleExperiment(id, request.logger); + const experiment = await this.experimentService.getSingleExperiment(id, request.logger); + + if (SUPPORTED_MOOCLET_ALGORITHMS.includes(experiment.assignmentAlgorithm)) { + if (!env.mooclets?.enabled) { + throw new BadRequestError( + 'MoocletPolicyParameters are present in the experiment but Mooclet is not enabled in the environment' + ); + } else { + const policyParametersResponse = await this.moocletExperimentService.getPolicyParametersByExperimentId(id); + experiment.moocletPolicyParameters = policyParametersResponse.parameters; + } + } + + return experiment; } /** diff --git a/backend/packages/Upgrade/src/api/services/MoocletDataService.ts b/backend/packages/Upgrade/src/api/services/MoocletDataService.ts index c4d8ff7b3..5676f6b9f 100644 --- a/backend/packages/Upgrade/src/api/services/MoocletDataService.ts +++ b/backend/packages/Upgrade/src/api/services/MoocletDataService.ts @@ -128,6 +128,19 @@ export class MoocletDataService { return response; } + public async getPolicyParameters(policyParametersId: number): Promise { + const endpoint = `/policyparameters/${policyParametersId}`; + const requestParams: MoocletProxyRequestParams = { + method: 'GET', + url: this.apiUrl + endpoint, + apiToken: this.apiToken, + }; + + const response = await this.fetchExternalMoocletsData(requestParams); + + return response; + } + public async deletePolicyParameters(policyParametersId: number): Promise { const endpoint = `/policyparameters/${policyParametersId}`; const requestParams: MoocletProxyRequestParams = { diff --git a/backend/packages/Upgrade/src/api/services/MoocletExperimentService.ts b/backend/packages/Upgrade/src/api/services/MoocletExperimentService.ts index 82eccace2..02cd90518 100644 --- a/backend/packages/Upgrade/src/api/services/MoocletExperimentService.ts +++ b/backend/packages/Upgrade/src/api/services/MoocletExperimentService.ts @@ -47,7 +47,7 @@ import { ConditionValidator, ExperimentDTO } from '../DTO/ExperimentDTO'; import { UserDTO } from '../DTO/UserDTO'; import { Experiment } from '../models/Experiment'; import { UpgradeLogger } from '../../lib/logger/UpgradeLogger'; -import { ASSIGNMENT_ALGORITHM, MOOCLET_POLICY_SCHEMA_MAP, MoocletPolicyParametersDTO } from 'upgrade_types'; +import { ASSIGNMENT_ALGORITHM, MoocletPolicyParametersDTO, SUPPORTED_MOOCLET_ALGORITHMS } from 'upgrade_types'; import { ExperimentCondition } from '../models/ExperimentCondition'; export interface SyncCreateParams { @@ -409,6 +409,17 @@ export class MoocletExperimentService extends ExperimentService { } } + public async getPolicyParametersByExperimentId( + experimentId: string + ): Promise { + try { + const moocletExperimentRef = await this.getMoocletExperimentRefByUpgradeExperimentId(experimentId); + return await this.moocletDataService.getPolicyParameters(moocletExperimentRef.policyParametersId); + } catch (err) { + throw new Error(`Failed to get Mooclet policy parameters: ${err}`); + } + } + private async createMooclet(newMoocletRequest: MoocletRequestBody): Promise { try { return await this.moocletDataService.postNewMooclet(newMoocletRequest); @@ -551,6 +562,6 @@ export class MoocletExperimentService extends ExperimentService { } public isMoocletExperiment(assignmentAlgorithm: ASSIGNMENT_ALGORITHM): boolean { - return Object.keys(MOOCLET_POLICY_SCHEMA_MAP).includes(assignmentAlgorithm); + return SUPPORTED_MOOCLET_ALGORITHMS.includes(assignmentAlgorithm); } } diff --git a/frontend/projects/upgrade/src/app/core/experiment-design-stepper/experiment-design-stepper.service.ts b/frontend/projects/upgrade/src/app/core/experiment-design-stepper/experiment-design-stepper.service.ts index 1b6d06d03..fc789249d 100644 --- a/frontend/projects/upgrade/src/app/core/experiment-design-stepper/experiment-design-stepper.service.ts +++ b/frontend/projects/upgrade/src/app/core/experiment-design-stepper/experiment-design-stepper.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { AppState } from '../core.state'; -import { ASSIGNMENT_ALGORITHM, ASSIGNMENT_UNIT, MOOCLET_POLICY_SCHEMA_MAP } from 'upgrade_types'; +import { ASSIGNMENT_ALGORITHM, ASSIGNMENT_UNIT, SUPPORTED_MOOCLET_ALGORITHMS } from 'upgrade_types'; import { ExperimentDecisionPoint, ExperimentCondition, @@ -87,7 +87,7 @@ export class ExperimentDesignStepperService { currentAssignmentAlgorithm$ = new BehaviorSubject(ASSIGNMENT_ALGORITHM.RANDOM); isMoocletExperimentDesign$ = this.currentAssignmentAlgorithm$.pipe( map((algorithm) => { - return environment.moocletToggle && Object.keys(MOOCLET_POLICY_SCHEMA_MAP).includes(algorithm); + return environment.moocletToggle && SUPPORTED_MOOCLET_ALGORITHMS.includes(algorithm); }) ); diff --git a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.ts b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.ts index fa34cfe6d..df57395ab 100644 --- a/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.ts +++ b/frontend/projects/upgrade/src/app/features/dashboard/home/components/experiment-overview/experiment-overview.component.ts @@ -19,6 +19,7 @@ import { EXPERIMENT_STATE, EXPERIMENT_TYPE, MOOCLET_POLICY_SCHEMA_MAP, + SUPPORTED_MOOCLET_ALGORITHMS, } from 'upgrade_types'; import { NewExperimentDialogEvents, @@ -106,7 +107,7 @@ export class ExperimentOverviewComponent implements OnInit, OnDestroy { this.unitOfAssignments.push({ value: ASSIGNMENT_UNIT.WITHIN_SUBJECTS }); } if (this.environment.moocletToggle) { - const supportedMoocletAlgorithms = Object.keys(MOOCLET_POLICY_SCHEMA_MAP) as ASSIGNMENT_ALGORITHM[]; + const supportedMoocletAlgorithms = SUPPORTED_MOOCLET_ALGORITHMS as ASSIGNMENT_ALGORITHM[]; supportedMoocletAlgorithms.forEach((algorithmName) => { this.assignmentAlgorithms.push({ value: algorithmName }); }); diff --git a/types/src/Mooclet/index.ts b/types/src/Mooclet/index.ts index 30ecea835..e8404589c 100644 --- a/types/src/Mooclet/index.ts +++ b/types/src/Mooclet/index.ts @@ -11,8 +11,11 @@ const MOOCLET_POLICY_SCHEMA_MAP = { [ASSIGNMENT_ALGORITHM.MOOCLET_TS_CONFIGURABLE]: MoocletTSConfigurablePolicyParametersDTO, }; +const SUPPORTED_MOOCLET_ALGORITHMS = Object.keys(MOOCLET_POLICY_SCHEMA_MAP); + export { MOOCLET_POLICY_SCHEMA_MAP, + SUPPORTED_MOOCLET_ALGORITHMS, Prior, CurrentPosteriors, MoocletPolicyParametersDTO, diff --git a/types/src/index.ts b/types/src/index.ts index 23be26d59..2838b2435 100644 --- a/types/src/index.ts +++ b/types/src/index.ts @@ -81,4 +81,5 @@ export { MoocletPolicyParametersDTO, MoocletTSConfigurablePolicyParametersDTO, MOOCLET_POLICY_SCHEMA_MAP, + SUPPORTED_MOOCLET_ALGORITHMS, } from './Mooclet';