commons-assessment 12.0.39-dev.3 → 12.0.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -768,6 +768,8 @@
768
768
  var _a;
769
769
  this.http = http;
770
770
  this.assetsBaseUrl = (_a = document === null || document === void 0 ? void 0 : document.baseURI) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, '');
771
+ // cache the static config JSON so multiple taker instances on one page fetch it only once
772
+ this.configCache = {};
771
773
  }
772
774
  AssessmentTakerService.prototype.getHeaders = function () {
773
775
  return new i1$1.HttpHeaders().set('X-Library-Source', 'commons-assessment');
@@ -791,7 +793,17 @@
791
793
  return param;
792
794
  };
793
795
  AssessmentTakerService.prototype.getConfigJSON = function (fileName) {
794
- return this.http.get(this.assetsBaseUrl + "/assets/commons-assessment/" + fileName + ".json");
796
+ var _this = this;
797
+ if (!this.configCache[fileName]) {
798
+ this.configCache[fileName] = this.http
799
+ .get(this.assetsBaseUrl + "/assets/commons-assessment/" + fileName + ".json")
800
+ .pipe(
801
+ // drop the cache entry on error so a later render can retry the fetch
802
+ operators.catchError(function (err) { delete _this.configCache[fileName]; return rxjs.throwError(err); }),
803
+ // share one request across all subscribers and replay the loaded config to later ones
804
+ operators.shareReplay(1));
805
+ }
806
+ return this.configCache[fileName];
795
807
  };
796
808
  AssessmentTakerService.prototype.getAssessmentContextById = function (params) {
797
809
  return this.http.get(assessmentTakerController.getAssessmentContextById + this.createParams(params), { headers: this.getHeaders() });
@@ -1457,6 +1469,7 @@
1457
1469
  var _this = this;
1458
1470
  var _a;
1459
1471
  this.cameraError = '';
1472
+ this.cameraReady = false; // show the "starting camera" state until the (re)started stream is ready
1460
1473
  (_a = navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia({ video: { facingMode: 'user' }, audio: false }).then(function (stream) {
1461
1474
  var _a;
1462
1475
  _this.stream = stream;
@@ -1490,6 +1503,10 @@
1490
1503
  this.capturedUrl = '';
1491
1504
  this.capturedBase64 = '';
1492
1505
  this.startError = '';
1506
+ // the stream is stopped before a session-start attempt; restart it so recapture works after a failure
1507
+ if (!this.stream) {
1508
+ this.startCamera();
1509
+ }
1493
1510
  };
1494
1511
  /** Enabled only once a photo is captured (when required); runs the session-start action. */
1495
1512
  ProctoringConsentComponent.prototype.proceed = function () {
@@ -1511,6 +1528,13 @@
1511
1528
  _this.starting = false;
1512
1529
  _this.startError = (typeof err === 'string' ? err : err === null || err === void 0 ? void 0 : err.message)
1513
1530
  || _this.labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSION_ERROR'];
1531
+ if ((err === null || err === void 0 ? void 0 : err.retakePhoto) && _this.requireCapture) {
1532
+ // the captured photo was rejected — return to the camera so the candidate can recapture
1533
+ _this.captured = false;
1534
+ _this.capturedUrl = '';
1535
+ _this.capturedBase64 = '';
1536
+ _this.startCamera();
1537
+ }
1514
1538
  }
1515
1539
  });
1516
1540
  };
@@ -3156,10 +3180,15 @@
3156
3180
  })
3157
3181
  : rxjs.of(void 0);
3158
3182
  }), operators.catchError(function (err) {
3183
+ var _a;
3159
3184
  if ((err === null || err === void 0 ? void 0 : err.code) === 'camera_denied') {
3160
3185
  // surfaced inside the intro gate so the candidate can allow the camera and retry
3161
3186
  return rxjs.throwError({ message: _this.labelConfig['COMMONS_ASSESSMENT.PROCTORING.CAMERA_DENIED'] });
3162
3187
  }
3188
+ // backend rejected the reference photo (e.g. no clear face) — prompt the candidate to retake it
3189
+ if (((_a = err === null || err === void 0 ? void 0 : err.error) === null || _a === void 0 ? void 0 : _a.errorCode) === 'ERR_PROCTORING_PROVIDER_CLIENT') {
3190
+ return rxjs.throwError({ message: _this.labelConfig['COMMONS_ASSESSMENT.PROCTORING.REFERENCE_IMAGE_REJECTED'], retakePhoto: true });
3191
+ }
3163
3192
  _this.snackbarMessage.emit({ message: _this.labelConfig['COMMONS_ASSESSMENT.TOAST.ERROR_DEFAULT'], type: 'error' });
3164
3193
  return rxjs.throwError({ message: _this.labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSION_ERROR'] });
3165
3194
  }));
@@ -3820,7 +3849,7 @@
3820
3849
  return AssessmentTakerComponent;
3821
3850
  }());
3822
3851
  AssessmentTakerComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: AssessmentTakerComponent, deps: [{ token: AssessmentTakerService }, { token: i1__namespace$2.FormBuilder }, { token: ResponseBuilderService }, { token: i2__namespace.DomSanitizer }, { token: i1__namespace.MatDialog }, { token: i0__namespace.ChangeDetectorRef }, { token: ProctoringService }], target: i0__namespace.ɵɵFactoryTarget.Component });
3823
- AssessmentTakerComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: AssessmentTakerComponent, selector: "lib-assessment-taker", inputs: { labelConfig: "labelConfig", imageConfig: "imageConfig", showFooter: "showFooter", assessmentId: "assessmentId", assessmentInstanceId: "assessmentInstanceId", assesseeData: "assesseeData", assessorData: "assessorData", disabled: "disabled", previewMode: "previewMode", verticalView: "verticalView", enableMarks: "enableMarks", hideSectionTabs: "hideSectionTabs", assessmentContext: "assessmentContext", assesseeResponse: "assesseeResponse", markAsCompleted: "markAsCompleted", sectionWiseScore: "sectionWiseScore", showOverallRemarks: "showOverallRemarks", showCorrectAnswers: "showCorrectAnswers", resumeTimerAcrossVisits: "resumeTimerAcrossVisits", warnOnLeaveDuringProctoring: "warnOnLeaveDuringProctoring", proctorLinkLoader: "proctorLinkLoader" }, outputs: { snackbarMessage: "snackbarMessage", submitAssessment: "submitAssessment", stepChanged: "stepChanged", consentToProceed: "consentToProceed" }, host: { listeners: { "window:resize": "onResize()", "window:beforeunload": "onBeforeUnload($event)", "window:popstate": "onPopState()" } }, ngImport: i0__namespace, template: "<div *ngIf=\"configsLoaded && !showLoader; else loader\" class=\"col-12 h-100\">\r\n <div class=\"col-12 h-100 pt-2 pb-4\" [class.height-without-footer]=\"showFooter\">\r\n <div *ngIf=\"previewMode && isProctoringEnabled && (assesseeResponse?.id || assesseeData?.id)\" class=\"d-flex justify-content-end mb-3\">\r\n <button type=\"button\" (click)=\"openProctoringResult()\"\r\n class=\"assessment-zoom-animation assessment-button-padding assessment-border-radius-two assessment-btn-primary-transparent assessment-text-semibold-13 d-flex align-items-center gap-2\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.PROCTORING']\" width=\"16\" height=\"16\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/proctoring.svg')\" />\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.VIEW_REPORT'] }}\r\n </button>\r\n </div>\r\n <!-- Full-screen intro gate \u2014 questions stay hidden until proceed -->\r\n <lib-proctoring-consent *ngIf=\"introActive\" [labelConfig]=\"labelConfig\"\r\n [proctoringEnabled]=\"isProctoringEnabled\" [requireCapture]=\"requireReferenceCapture\"\r\n [sectionCount]=\"totalSectionCount\" [questionCount]=\"totalQuestionCount\"\r\n [durationSeconds]=\"assessmentDurationSeconds\"\r\n [confirmAction]=\"startSessionAction\" (proceeded)=\"onIntroProceeded()\">\r\n </lib-proctoring-consent>\r\n\r\n <div *ngIf=\"assessmentContext?.assessmentInstanceDTO?.duration && !previewMode && !introActive && (!disabled || timeExpired)\"\r\n class=\"d-flex align-items-center gap-md-3 gap-2 px-3 py-2 assessment-border-radius-two mb-4 timer-container assessment-bg-palette-FEF1E8\">\r\n <p class=\"assessment-text-semibold-18 assessment-text-grey-ten mb-0\">{{displayTime}}</p>\r\n <p class=\"assessment-text-grey-ten assessment-text-medium-12 mb-0\">\r\n {{ timeExpired\r\n ? labelConfig['COMMONS_ASSESSMENT.LABEL.TIMER_EXPIRED']\r\n : labelConfig['COMMONS_ASSESSMENT.LABEL.TIMER_AUTO_SUBMIT'] }}</p>\r\n </div>\r\n <ng-container *ngIf=\"assessmentQuestionPaperData?.questionPaperSectionList?.length && !introActive\">\r\n <mat-tab-group *ngIf=\"!verticalView\" animationDuration=\"0ms\" class=\"assessment-mat-custom-tabs\"\r\n [ngClass]=\"{'assessment-hide-tabs': hideSectionTabs}\" [(selectedIndex)]=\"selectedTabIndex\">\r\n <mat-tab\r\n *ngFor=\"let section of assessmentQuestionPaperData.questionPaperSectionList | orderBy; let i = index; trackBy: trackBySectionId\"\r\n [disabled]=\"shouldDisableTab(i)\">\r\n <ng-template mat-tab-label>\r\n <span class=\"assessment-text-semibold-16\"\r\n [ngClass]=\"sectionErrors[i] ? 'assessment-text-danger' : ''\">{{section.qpsName?.[0]?.text}}</span>\r\n </ng-template>\r\n <div class=\"mt-4\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sectionContent; context: { section: section, i: i }\"></ng-container>\r\n </div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <mat-accordion *ngIf=\"verticalView\" multi=\"true\" class=\"d-flex flex-column gap-4\">\r\n <mat-expansion-panel\r\n *ngFor=\"let section of assessmentQuestionPaperData.questionPaperSectionList | orderBy; let i = index; trackBy: trackBySectionId\"\r\n [expanded]=\"expandedState[i] !== false\" (opened)=\"expandedState[i] = true\"\r\n (closed)=\"expandedState[i] = false\"\r\n class=\"assessment-border-radius-two shadow-none m-0 assessment-panel bg-transparent\">\r\n <mat-expansion-panel-header class=\"assessment-bg-grey-two h-auto assessment-panel-header\">\r\n <div class=\"d-flex align-items-center justify-content-between gap-2 col-12 pe-3\">\r\n <span class=\"assessment-text-semibold-16\"\r\n [ngClass]=\"sectionErrors[i] ? 'assessment-text-danger' : ''\">\r\n {{section.qpsName?.[0]?.text}}</span>\r\n\r\n <ng-container *ngIf=\"sectionWiseScore?.[section?.id] as sectionScore\">\r\n <div *ngIf=\"(sectionScore?.totalMarks ?? 0) > 0\"\r\n class=\"d-flex align-items-center gap-2 assessment-text-primary-four\">\r\n <span *ngIf=\"(sectionScore?.skillScores?.length ?? 0) > 0\"\r\n class=\"assessment-text-medium-11 assessment-text-grey-ten px-2 py-1 assessment-border-radius-two skill-chip cursor-pointer\"\r\n (click)=\"$event.stopPropagation(); openSkillAllocationDialog(sectionScore?.skillScores)\">\r\n {{sectionScore?.skillScores?.length}}\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.SKILLS']}}\r\n </span>\r\n <span class=\"white-space-nowrap assessment-text-semibold-13\">\r\n <span class=\"assessment-text-medium-15 me-1\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.SCORE']}}:</span>\r\n {{sectionScore.obtainedMarks || 0}}/{{sectionScore.totalMarks}}\r\n </span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </mat-expansion-panel-header>\r\n <div class=\"mt-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sectionContent; context: { section: section, i: i }\"></ng-container>\r\n </div>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n </ng-container>\r\n\r\n <div *ngIf=\"!assessmentQuestionPaperData?.questionPaperSectionList?.length\"\r\n class=\"h-100 d-flex flex-column align-items-center justify-content-center gap-3\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.NO_QUESTIONS']\" class=\"col-sm-auto col-6\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/no-questions.svg')\" />\r\n <div class=\"text-center\">\r\n <p class=\"mb-1 assessment-text-medium-18\">{{labelConfig['COMMONS_ASSESSMENT.LABEL.NO_QUESTIONS']}}</p>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showOverallRemarks && assessmentQuestionPaperData?.questionPaperSectionList?.length\" class=\"mt-3\">\r\n <p class=\"assessment-text-medium-15 mb-2\">{{labelConfig['COMMONS_ASSESSMENT.LABEL.OVERALL_REMARKS']}}</p>\r\n <textarea\r\n class=\"col-12 assessment-text-regular-13 assessment-input-border-one assessment-border-radius-two assessment-input-padding outline-0 assessment-bg-grey-one\"\r\n rows=\"3\" [formControl]=\"overallNotesCtrl\"\r\n [placeholder]=\"labelConfig['COMMONS_ASSESSMENT.PLACEHOLDER.REMARKS']\"></textarea>\r\n </div>\r\n </div>\r\n <div *ngIf=\"showFooter && !introActive\"\r\n class=\"bg-white p-3 position-sticky bottom-0 d-flex align-items-center justify-content-end border-top gap-3 z-index-1\">\r\n <button\r\n class=\"assessment-zoom-animation assessment-border-radius-two assessment-button-padding-large assessment-btn-primary-transparent assessment-text-semibold-13\"\r\n (click)=\"goBack()\" *ngIf=\"selectedTabIndex > 0 && !verticalView\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.GO_BACK']}}</button>\r\n <button [disabled]=\"isSubmitting || (disabled && !enableMarks && !showOverallRemarks) || isCheckingLink\" (click)=\"verticalView ? goNext(true) : goNext()\"\r\n class=\"assessment-zoom-animation assessment-border-radius-two assessment-button-padding-large assessment-btn-primary assessment-text-semibold-13 position-relative\">\r\n <span [ngClass]=\"{'opacity-0': isSubmitting}\">\r\n {{ (verticalView || selectedTabIndex === sectionFormGroups.length - 1) ?\r\n labelConfig['COMMONS_ASSESSMENT.LABEL.SUBMIT'] : labelConfig['COMMONS_ASSESSMENT.LABEL.NEXT'] }}\r\n </span>\r\n <mat-spinner *ngIf=\"isSubmitting\" [diameter]=\"20\"\r\n class=\"position-absolute top-50 start-50 translate-middle assessment-spinner-white\"></mat-spinner>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loader>\r\n <div class=\"h-100 col-12 d-flex align-items-center justify-content-center py-5\">\r\n <mat-spinner diameter=\"60\" class=\"assessment-spinner-primary\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Recursive Template for Questions & Child Questions -->\r\n<ng-template #questionTemplate let-questionId=\"questionId\" let-isMandatory=\"isMandatory\" let-groupIndex=\"groupIndex\"\r\n let-parentOptionId=\"parentOptionId\" let-parentQuestionId=\"parentQuestionId\" let-sequence=\"sequence\">\r\n <div *ngIf=\"sectionFormGroups[groupIndex].formGroup as formGroup\" [formGroup]=\"formGroup\"\r\n [id]=\"'question-container-' + questionId\">\r\n <div class=\"assessment-border-radius-two assessment-bg-white\"\r\n [ngClass]=\"{'p-3 assessment-card-border': !parentOptionId}\" *ngIf=\"questionBank[questionId] as question\">\r\n <div class=\"d-flex flex-md-row flex-column gap-2 align-items-start\">\r\n <div class=\"flex-grow-1 d-flex align-items-start gap-1\">\r\n <span class=\"assessment-text-medium-15 text-nowrap d-md-block d-none\"\r\n *ngIf=\"sequence\">{{sequence}}.</span>\r\n <div class=\"flex-grow-1\">\r\n <div class=\"d-flex gap-2 align-items-start col-12\">\r\n <div class=\"flex-grow-1\">\r\n <p class=\"assessment-text-medium-15 mb-0 d-flex gap-1\">\r\n <span>\r\n <span [innerHtml]=\"question.questionText?.[0]?.text\"></span>\r\n <span *ngIf=\"isMandatory\"\r\n class=\"assessment-text-regular-11 assessment-text-grey-eight\">\r\n ({{labelConfig['COMMONS_ASSESSMENT.LABEL.MANDATORY']}})</span>\r\n </span>\r\n </p>\r\n <div class=\"mt-3 col-12\" *ngIf=\"question?.mediaUrl?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"VideoTemplate; context:{videoUrl:question?.mediaUrl}\"></ng-container>\r\n </div>\r\n </div>\r\n <ng-container *ngIf=\"question.hintText?.length && !previewMode\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.INFO']\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/info.svg')\"\r\n cdkOverlayOrigin #trigger=\"cdkOverlayOrigin\"\r\n (mouseenter)=\"tooltipState[question.id!] = true\"\r\n (mouseleave)=\"tooltipState[question.id!] = false\" class=\"cursor-pointer\" />\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"tooltipState[question.id!] || false\"\r\n [cdkConnectedOverlayPositions]=\"[{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8, offsetY: 0 }, { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8, offsetY: 0 }]\">\r\n <div class=\"assessment-bg-grey-two assessment-tooltip-border p-3 assessment-border-radius-two assessment-box-shadow-tooltip question-info assessment-text-regular-13\"\r\n (mouseenter)=\"tooltipState[question.id!] = true\"\r\n (mouseleave)=\"tooltipState[question.id!] = false\"\r\n [innerHTML]=\"question.hintText\">\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"previewMode && !isMobile\" class=\"mt-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"isMobile\" class=\"col-12 mt-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n\r\n <!-- Assessor Marks Logic -->\r\n <div class=\"assessment-marks-field\"\r\n *ngIf=\"enableMarks && shouldShowMarksDropdown(question) && formGroup.get(question.id + '_marks') as marksControl\">\r\n <label class=\"assessment-text-medium-12 assessment-text-grey-ten\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.MARKS']}}(Max: {{question.weight}})</label>\r\n <input (keydown)=\"preventNegativeInput($event)\"\r\n (input)=\"checkMaxVal($event, marksControl, question?.weight)\"\r\n class=\"col-12 assessment-input-border-one assessment-border-radius-two px-2 py-1 outline-0 assessment-bg-grey-one assessment-text-medium-12\"\r\n [formControlName]=\"question.id + '_marks'\" type=\"number\" min=\"0\"\r\n (wheel)=\"$event.preventDefault()\">\r\n </div>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"!previewMode && !isMobile\" class=\"mt-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n\r\n <!-- Child Questions and Remarks Rendering Logic based on checked form state -->\r\n <ng-container *ngIf=\"question.defaultOptionsList?.length\">\r\n <ng-container *ngFor=\"let option of question.defaultOptionsList; trackBy: trackByOptionId\">\r\n\r\n <ng-container *ngIf=\"isOptionSelected(formGroup, question, option.options?.id)\">\r\n\r\n <!-- REMARKS FIELD -->\r\n <div class=\"mt-3\"\r\n *ngIf=\"option.remarksRequired && formGroup.get(question.id + '_remarks_' + option.id) as remarksControl\">\r\n <p class=\"assessment-text-regular-15 mb-2\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.REMARKS']}}</p>\r\n <textarea *ngIf=\"!previewMode\" formControlName=\"{{question.id}}_remarks_{{option.id}}\"\r\n rows=\"2\" [placeholder]=\"labelConfig['COMMONS_ASSESSMENT.PLACEHOLDER.REMARKS']\"\r\n [ngClass]=\"remarksControl.invalid && remarksControl.touched ? 'assessment-input-border-invalid' : ''\"\r\n class=\"col-12 assessment-text-regular-13 assessment-input-border-one assessment-border-radius-two assessment-input-padding outline-0 assessment-bg-grey-one\"></textarea>\r\n <ng-container *ngIf=\"previewMode\">\r\n <span class=\"assessment-text-regular-13 assessment-text-grey-nine\">\r\n {{ remarksControl.value }}</span>\r\n </ng-container>\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"remarksControl.invalid && remarksControl.touched\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.FIELD_REQUIRED']}}\r\n </div>\r\n </div>\r\n\r\n <!-- CHILD QUESTIONS RECURSION -->\r\n <div class=\"col-12 mt-4 d-flex flex-column gap-3\" *ngIf=\"option.childQuestionList?.length\">\r\n <ng-container *ngFor=\"let childId of option.childQuestionList; let childIndex = index; trackBy: trackByChildId\">\r\n <ng-container *ngTemplateOutlet=\"questionTemplate; context: {\r\n questionId: childId,\r\n isMandatory: questionBank[childId]?.isMandatory,\r\n groupIndex: groupIndex,\r\n parentOptionId: option.id,\r\n parentQuestionId: question.id,\r\n sequence: sequence + '.' + (childIndex + 1)\r\n }\">\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- answer field template -->\r\n<ng-template #answerField let-question=\"question\" let-previewMode=\"previewMode\" let-isMandatory=\"isMandatory\"\r\n let-groupIndex=\"groupIndex\" let-parentOptionId=\"parentOptionId\" let-parentQuestionId=\"parentQuestionId\">\r\n <div *ngIf=\"sectionFormGroups[groupIndex].formGroup\" [formGroup]=\"sectionFormGroups[groupIndex].formGroup\"\r\n class=\"col-12\">\r\n <ng-container [ngSwitch]=\"question.questionType?.code\">\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_SHORT'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_LONG'\">\r\n <lib-question-type-long [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-long>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_RICH_TEXT'\">\r\n <lib-question-type-editor [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [previewMode]=\"previewMode\"\r\n [labelConfig]=\"labelConfig\"></lib-question-type-editor>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.OBJECTIVE'\">\r\n <lib-question-type-objective [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [showCorrectAnswers]=\"showCorrectAnswers\" [imageConfig]=\"imageConfig\"\r\n [answerObj]=\"getQuestionAnswerObj(question.id!, parentOptionId, parentQuestionId)\"></lib-question-type-objective>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.MULTI_SELECT'\">\r\n <lib-question-type-multiselect [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [showCorrectAnswers]=\"showCorrectAnswers\" [imageConfig]=\"imageConfig\"\r\n [answerObj]=\"getQuestionAnswerObj(question.id!, parentOptionId, parentQuestionId)\"></lib-question-type-multiselect>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.PREFERENCE'\">\r\n <lib-question-type-preference [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\"></lib-question-type-preference>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.NUMBER'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.EMAIL'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.CONTACT_NUMBER'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.URL'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.FILE_UPLOAD'\">\r\n <lib-question-type-file-upload [question]=\"question\" [assessmentInstanceId]=\"assessmentInstanceId\"\r\n [formControlName]=\"question.id!\" [required]=\"isMandatory\" [labelConfig]=\"labelConfig\"\r\n [imageConfig]=\"imageConfig\" (snackbarMessage)=\"snackbarMessage.emit($event)\"></lib-question-type-file-upload>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.DATE_PICKER'\">\r\n <lib-question-type-date-picker [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [previewMode]=\"previewMode\"\r\n [labelConfig]=\"labelConfig\"></lib-question-type-date-picker>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Error Messages and Character Count Container -->\r\n <ng-container\r\n *ngIf=\"!previewMode && sectionFormGroups[groupIndex].formGroup.get(question.id?.toString() || '') as control\">\r\n <div class=\"d-flex justify-content-between align-items-start mt-1\">\r\n <span>\r\n <div class=\"assessment-text-regular-12 assessment-text-danger\"\r\n *ngIf=\"control.touched && control.errors?.['required']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.REQUIRED_RESPONSE']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['pattern']\">\r\n {{question?.validationMessage || labelConfig['COMMONS_ASSESSMENT.ERROR.INVALID_FORMAT']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['privateGdriveLink']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.PRIVATE_DRIVE_LINK']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['minlength']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MIN_CHARS']?.replace('{{length}}',\r\n control.errors?.['minlength'].requiredLength + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxlength']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_CHARS']?.replace('{{length}}',\r\n control.errors?.['maxlength'].requiredLength + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['minOptions']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MIN_OPTIONS']?.replace('{{count}}',\r\n control.errors?.['minOptions'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxOptions']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_OPTIONS']?.replace('{{count}}',\r\n control.errors?.['maxOptions'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxFiles']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_FILES']?.replace('{{count}}',\r\n control.errors?.['maxFiles'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxFileSize']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_FILE_SIZE']?.replace('{{size}}',\r\n control.errors?.['maxFileSize'].requiredSize + '')}}\r\n </div>\r\n </span>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-grey-seven white-space-nowrap ms-2\"\r\n *ngIf=\"getMaxCharCount(question) > 0\">\r\n {{ getRemainingChars(question, control) }}\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.CHARACTER']}}{{getRemainingChars(question, control) !==\r\n 1\r\n ? 's' : ''}} {{labelConfig['COMMONS_ASSESSMENT.LABEL.REMAINING']}}\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Reusable Section Form Template -->\r\n<ng-template #sectionContent let-section=\"section\" let-i=\"i\">\r\n <form class=\"w-100\" *ngIf=\"sectionFormGroups[i].formGroup\" [formGroup]=\"sectionFormGroups[i].formGroup\"\r\n [name]=\"'sectionfrm-' + i\" novalidate>\r\n <div class=\"d-flex justify-content-between align-items-center mb-4\"\r\n *ngIf=\"!previewMode && (section?.qpsDesc?.[0]?.text || section?.mediaUrl)\">\r\n <span class=\"assessment-text-semibold-14 assessment-text-grey-ten\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.TOTAL_QUESTIONS']}}: {{ section?.totalQuestions || 0 }}\r\n </span>\r\n <button (click)=\"openInstructionsDialog(section)\"\r\n class=\"assessment-zoom-animation assessment-button-padding assessment-text-medium-13 assessment-btn-primary-transparent\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.VIEW_INSTRUCTIONS']}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"col-12 d-flex flex-column gap-3\">\r\n <ng-container *ngFor=\"let sq of section.sectionQuestionsList | orderBy; let j = index; trackBy: trackBySectionQuestion\">\r\n <ng-container *ngTemplateOutlet=\"questionTemplate; context: {\r\n questionId: sq.questionId,\r\n isMandatory: questionBank[sq.questionId]?.isMandatory,\r\n groupIndex: i,\r\n parentOptionId: null,\r\n parentQuestionId: null,\r\n sequence: j + 1\r\n }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </form>\r\n</ng-template>\r\n\r\n<!-- video preview -->\r\n<ng-template let-videoUrl=\"videoUrl\" #VideoTemplate>\r\n <div class=\"assessment-border-radius-two overflow-hidden col-md-10 col-12\">\r\n <video *ngIf=\"videoUrl?.includes('.mp4') else youtubeVideo\" width=\"400\" controls class=\"mw-100 d-block mx-auto\">\r\n <source [src]=\"videoUrl\" type=\"video/mp4\">\r\n </video>\r\n <ng-template #youtubeVideo>\r\n <div class=\"youtube-video position-relative h-100\">\r\n <iframe [src]=\"addYoutubeIframeSrc(videoUrl)\" title=\"YouTube video player\" frameborder=\"0\"\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\r\n allowfullscreen class=\"position-absolute top-0 start-0 w-100 h-100 d-block\">\r\n </iframe>\r\n </div>\r\n </ng-template>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";.assessment-text-grey-ten{color:var(--assessment-grey-ten)!important}.assessment-bg-grey-ten{background-color:var(--assessment-grey-ten)!important}.assessment-text-grey-nine{color:var(--assessment-grey-nine)!important}.assessment-bg-grey-nine{background-color:var(--assessment-grey-nine)!important}.assessment-text-grey-eight{color:var(--assessment-grey-eight)!important}.assessment-bg-grey-eight{background-color:var(--assessment-grey-eight)!important}.assessment-text-grey-seven{color:var(--assessment-grey-seven)!important}.assessment-bg-grey-seven{background-color:var(--assessment-grey-seven)!important}.assessment-text-grey-six{color:var(--assessment-grey-six)!important}.assessment-bg-grey-six{background-color:var(--assessment-grey-six)!important}.assessment-text-grey-five{color:var(--assessment-grey-five)!important}.assessment-bg-grey-five{background-color:var(--assessment-grey-five)!important}.assessment-text-grey-four{color:var(--assessment-grey-four)!important}.assessment-bg-grey-four{background-color:var(--assessment-grey-four)!important}.assessment-text-grey-three{color:var(--assessment-grey-three)!important}.assessment-bg-grey-three{background-color:var(--assessment-grey-three)!important}.assessment-text-grey-two{color:var(--assessment-grey-two)!important}.assessment-bg-grey-two{background-color:var(--assessment-grey-two)!important}.assessment-text-grey-one{color:var(--assessment-grey-one)!important}.assessment-bg-grey-one{background-color:var(--assessment-grey-one)!important}.assessment-text-white{color:var(--assessment-white)!important}.assessment-bg-white{background-color:var(--assessment-white)!important}.assessment-text-black{color:var(--assessment-black)!important}.assessment-bg-black{background-color:var(--assessment-black)!important}.assessment-text-danger{color:var(--assessment-danger)!important}.assessment-bg-danger{background-color:var(--assessment-danger)!important}.assessment-text-danger-bg{color:var(--assessment-danger-bg)!important}.assessment-bg-danger-bg{background-color:var(--assessment-danger-bg)!important}.assessment-text-success{color:var(--assessment-success)!important}.assessment-bg-success{background-color:var(--assessment-success)!important}.assessment-text-success-bg{color:var(--assessment-success-bg)!important}.assessment-bg-success-bg{background-color:var(--assessment-success-bg)!important}.assessment-text-warning{color:var(--assessment-warning)!important}.assessment-bg-warning{background-color:var(--assessment-warning)!important}.assessment-text-warning-bg{color:var(--assessment-warning-bg)!important}.assessment-bg-warning-bg{background-color:var(--assessment-warning-bg)!important}.assessment-text-primary-one{color:var(--assessment-primary-one)!important}.assessment-bg-primary-one{background-color:var(--assessment-primary-one)!important}.assessment-text-primary-four{color:var(--assessment-primary-four)!important}.assessment-bg-primary-four{background-color:var(--assessment-primary-four)!important}.assessment-text-palette-EDF3FD{color:var(--assessment-palette-EDF3FD)!important}.assessment-bg-palette-EDF3FD{background-color:var(--assessment-palette-EDF3FD)!important}.assessment-text-palette-C8DAF9{color:var(--assessment-palette-C8DAF9)!important}.assessment-bg-palette-C8DAF9{background-color:var(--assessment-palette-C8DAF9)!important}.assessment-text-palette-ADC9F6{color:var(--assessment-palette-ADC9F6)!important}.assessment-bg-palette-ADC9F6{background-color:var(--assessment-palette-ADC9F6)!important}.assessment-text-palette-FEF9F1{color:var(--assessment-palette-FEF9F1)!important}.assessment-bg-palette-FEF9F1{background-color:var(--assessment-palette-FEF9F1)!important}.assessment-text-palette-F9DAA6{color:var(--assessment-palette-F9DAA6)!important}.assessment-bg-palette-F9DAA6{background-color:var(--assessment-palette-F9DAA6)!important}.assessment-text-palette-E8F7F0{color:var(--assessment-palette-E8F7F0)!important}.assessment-bg-palette-E8F7F0{background-color:var(--assessment-palette-E8F7F0)!important}.assessment-text-palette-B7E7CF{color:var(--assessment-palette-B7E7CF)!important}.assessment-bg-palette-B7E7CF{background-color:var(--assessment-palette-B7E7CF)!important}.assessment-text-palette-FEF1E8{color:var(--assessment-palette-FEF1E8)!important}.assessment-bg-palette-FEF1E8{background-color:var(--assessment-palette-FEF1E8)!important}.assessment-text-palette-FAD2B9{color:var(--assessment-palette-FAD2B9)!important}.assessment-bg-palette-FAD2B9{background-color:var(--assessment-palette-FAD2B9)!important}.assessment-box-shadow-one{box-shadow:var(--assessment-box-shadow-one)!important}.assessment-border-radius-one{border-radius:var(--assessment-border-radius-one)!important}.assessment-border-radius-two{border-radius:var(--assessment-border-radius-two)!important}.assessment-border-radius-three{border-radius:var(--assessment-border-radius-three)!important}.assessment-border-radius-four{border-radius:var(--assessment-border-radius-four)!important}.assessment-border-radius-five{border-radius:var(--assessment-border-radius-five)!important}.assessment-border-radius-six{border-radius:var(--assessment-border-radius-six)!important}.assessment-input-border-one{border:var(--assessment-input-border-one)!important}.assessment-input-border-invalid{border:var(--assessment-input-border-invalid)!important}.assessment-input-focus-border{border:var(--assessment-input-focus-border)!important}.assessment-border-two{border:var(--assessment-border-two)!important}.assessment-card-border{border:var(--assessment-card-border)!important}.assessment-tooltip-border{border:var(--assessment-tooltip-border)!important}.assessment-box-shadow-tooltip{box-shadow:var(--assessment-box-shadow-tooltip)!important}.assessment-input-focus-box-shadow{box-shadow:var(--assessment-input-focus-box-shadow)!important}.assessment-button-padding{padding:var(--assessment-button-padding)!important}.assessment-button-padding-large{padding:var(--assessment-button-padding-large)!important}.assessment-input-padding{padding:var(--assessment-input-padding)!important}.assessment-text-font-family{color:var(--assessment-font-family)!important}.assessment-bg-font-family{background-color:var(--assessment-font-family)!important}.assessment-text-regular-12{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-semibold-12{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-medium-11{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.48rem + .25vw);line-height:calc(.8rem + .25vw)}.assessment-text-medium-10{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.42rem + .2vw);line-height:calc(.72rem + .2vw)}.assessment-text-regular-11{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.48rem + .25vw);line-height:calc(.8rem + .25vw)}.assessment-text-medium-12{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-regular-13{font-weight:400;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-semibold-13{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-medium-13{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-medium-14{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.7rem + .2vw)!important;line-height:calc(1.2rem + .2vw)!important}.assessment-text-semibold-14{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.7rem + .2vw);line-height:calc(1.2rem + .2vw)}.assessment-text-regular-15{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.85rem + .1vw);line-height:calc(1.4rem + .1vw)}.assessment-text-medium-15{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.85rem + .1vw);line-height:calc(1.25rem + .1vw)}.assessment-text-semibold-15{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.85rem + .1vw);line-height:calc(1.25rem + .1vw)}.assessment-text-semibold-16{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.77rem + .25vw);line-height:calc(1.25rem + .2vw)}.assessment-text-medium-16{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.77rem + .25vw);line-height:calc(1.25rem + .2vw)}.assessment-text-medium-18{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(1rem + .125vw)!important;line-height:calc(1.5rem + .1vw)!important}.assessment-text-semibold-18{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(1rem + .125vw)!important;line-height:calc(1.5rem + .1vw)!important}@media (min-height: 100vw) and (orientation: portrait){.assessment-text-medium-18,.assessment-text-semibold-18{font-size:calc(1rem + .1vh)!important;line-height:calc(1.6rem + .1vh)!important}.assessment-text-medium-16,.assessment-text-semibold-16{font-size:calc(.9rem + .2vh)!important;line-height:calc(1.4rem + .2vh)!important}.assessment-text-regular-15,.assessment-text-semibold-15{font-size:calc(.8rem + .2vh);line-height:calc(1.27rem + .2vh)}.assessment-text-medium-15{font-size:calc(.82rem + .2vh);line-height:calc(1.27rem + .2vh)}.assessment-text-medium-12,.assessment-text-regular-12,.assessment-text-semibold-12{font-size:calc(.5rem + .4vh);line-height:calc(.8rem + .4vh)}.assessment-text-medium-14,.assessment-text-semibold-14{font-size:calc(.8rem + .1vh)!important;line-height:calc(1.2rem + .2vh)!important}.assessment-text-regular-13,.assessment-text-medium-13,.assessment-text-semibold-13{font-size:calc(.7rem + .2vh)!important;line-height:calc(1rem + .3vh)!important}.assessment-text-regular-11,.assessment-text-medium-11{font-size:calc(.5rem + .2vh)!important;line-height:calc(.8rem + .2vh)!important}.assessment-text-medium-10{font-size:calc(.45rem + .2vh)!important;line-height:calc(.72rem + .2vh)!important}}.assessment-btn-primary{background-color:var(--assessment-primary-one);color:var(--assessment-white);border:.064rem solid var(--assessment-primary-one);border-radius:var(--assessment-border-radius-two)}.assessment-btn-primary-transparent{background-color:var(--assessment-white);color:var(--assessment-primary-one);border-radius:var(--assessment-border-radius-two);border:.064rem solid var(--assessment-primary-one)}.assessment-zoom-animation{transition:transform .2s ease;transform:translateZ(0);text-rendering:optimizeLegibility}.assessment-zoom-animation:hover{transform:scale(1.03)}.assessment-zoom-animation:active{transform:scale(1)}.assessment-zoom-animation:disabled{transform:none!important}.change-direction{transform:rotate(180deg);transition:.3s ease-out}.change-direction-reverse{transform:rotate(0);transition:.3s ease-out}.outline-0{outline:none}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.action-icon{width:1.2rem}.mat-menu-item,.mat-mdc-menu-item{height:inherit;min-height:unset;--mat-menu-item-label-text-font: var(--assessment-font-family) !important;--mat-menu-item-label-text-size: 14px !important;--mat-menu-item-label-text-weight: 600 !important;--mat-menu-item-label-text-line-height: inherit !important}.skill-chip{width:-moz-fit-content;width:fit-content;background:var(--assessment-palette-EDF3FD);border:.064rem solid var(--assessment-palette-C8DAF9)}.assessment-form-check-input-primary-one{min-height:unset}.assessment-form-check-input-primary-one .form-check-input{width:1rem;height:1rem}.assessment-form-check-input-primary-one .form-check-input:checked{background-color:var(--assessment-primary-one);color:var(--assessment-primary-one)}.assessment-form-check-input-primary-one .form-check-input:disabled{opacity:.8}.form-check-input:checked{background-color:var(--assessment-primary-one);border-color:var(--assessment-primary-one)}.form-check-input:focus{border-color:var(--assessment-primary-one);box-shadow:none}.height-without-footer{height:calc(100% - 4.4rem)!important}.z-index-1{z-index:1}.question-info{min-width:15rem;max-width:40vw}@media screen and (max-width: 768px){.question-info{max-width:75vw}}.assessment-marks-field{min-width:6.5rem;width:6.5rem}.youtube-video{aspect-ratio:16/9}.assessment-panel-header{padding-top:.7rem;padding-bottom:.7rem}.timer-container{border:.064rem solid var(--assessment-palette-FAD2B9)}\n"], components: [{ type: ProctoringConsentComponent, selector: "lib-proctoring-consent", inputs: ["labelConfig", "proctoringEnabled", "requireCapture", "sectionCount", "questionCount", "durationSeconds", "confirmAction"], outputs: ["proceeded"] }, { type: i8__namespace.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple"], exportAs: ["matTabGroup"] }, { type: i8__namespace.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby"], exportAs: ["matTab"] }, { type: i3__namespace.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { type: i3__namespace.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }, { type: i10__namespace.MatSpinner, selector: "mat-spinner", inputs: ["color"] }, { type: QuestionTypeShortComponent, selector: "lib-question-type-short", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeLongComponent, selector: "lib-question-type-long", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeEditorComponent, selector: "lib-question-type-editor", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeObjectiveComponent, selector: "lib-question-type-objective", inputs: ["required", "question", "showCorrectAnswers", "imageConfig", "answerObj"], outputs: ["viewChild"] }, { type: QuestionTypeMultiselectComponent, selector: "lib-question-type-multiselect", inputs: ["required", "question", "showCorrectAnswers", "imageConfig", "answerObj"], outputs: ["viewChild"] }, { type: QuestionTypePreferenceComponent, selector: "lib-question-type-preference", inputs: ["required", "question"], outputs: ["viewChild"] }, { type: QuestionTypeFileUploadComponent, selector: "lib-question-type-file-upload", inputs: ["required", "assessmentInstanceId", "question", "labelConfig", "imageConfig"], outputs: ["snackbarMessage"] }, { type: QuestionTypeDatePickerComponent, selector: "lib-question-type-date-picker", inputs: ["required", "question", "previewMode", "labelConfig"] }], directives: [{ type: i2__namespace$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2__namespace$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2__namespace$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i8__namespace.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { type: i2__namespace$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3__namespace.MatAccordion, selector: "mat-accordion", inputs: ["multi", "displayMode", "togglePosition", "hideToggle"], exportAs: ["matAccordion"] }, { type: i1__namespace$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1__namespace$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1__namespace$2.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i1__namespace$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1__namespace$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i20__namespace.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { type: i20__namespace.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayPositions", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayTransformOriginOn"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { type: i1__namespace$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i1__namespace$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i1__namespace$2.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i2__namespace$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2__namespace$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i1__namespace$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1__namespace$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }], pipes: { "orderBy": OrderByPipe } });
3852
+ AssessmentTakerComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: AssessmentTakerComponent, selector: "lib-assessment-taker", inputs: { labelConfig: "labelConfig", imageConfig: "imageConfig", showFooter: "showFooter", assessmentId: "assessmentId", assessmentInstanceId: "assessmentInstanceId", assesseeData: "assesseeData", assessorData: "assessorData", disabled: "disabled", previewMode: "previewMode", verticalView: "verticalView", enableMarks: "enableMarks", hideSectionTabs: "hideSectionTabs", assessmentContext: "assessmentContext", assesseeResponse: "assesseeResponse", markAsCompleted: "markAsCompleted", sectionWiseScore: "sectionWiseScore", showOverallRemarks: "showOverallRemarks", showCorrectAnswers: "showCorrectAnswers", resumeTimerAcrossVisits: "resumeTimerAcrossVisits", warnOnLeaveDuringProctoring: "warnOnLeaveDuringProctoring", proctorLinkLoader: "proctorLinkLoader" }, outputs: { snackbarMessage: "snackbarMessage", submitAssessment: "submitAssessment", stepChanged: "stepChanged", consentToProceed: "consentToProceed" }, host: { listeners: { "window:resize": "onResize()", "window:beforeunload": "onBeforeUnload($event)", "window:popstate": "onPopState()" } }, ngImport: i0__namespace, template: "<div *ngIf=\"configsLoaded && !showLoader; else loader\" class=\"col-12 h-100\">\r\n <div class=\"col-12 h-100 pt-2 pb-4\" [class.height-without-footer]=\"showFooter\">\r\n <div *ngIf=\"previewMode && isProctoringEnabled && (assesseeResponse?.id || assesseeData?.id)\" class=\"d-flex justify-content-end mb-3\">\r\n <button type=\"button\" (click)=\"openProctoringResult()\"\r\n class=\"assessment-zoom-animation assessment-button-padding assessment-border-radius-two assessment-btn-primary-transparent assessment-text-semibold-13 d-flex align-items-center gap-2\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.PROCTORING']\" width=\"16\" height=\"16\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/proctoring.svg')\" />\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.VIEW_REPORT'] }}\r\n </button>\r\n </div>\r\n <!-- Full-screen intro gate \u2014 questions stay hidden until proceed -->\r\n <lib-proctoring-consent *ngIf=\"introActive\" [labelConfig]=\"labelConfig\"\r\n [proctoringEnabled]=\"isProctoringEnabled\" [requireCapture]=\"requireReferenceCapture\"\r\n [sectionCount]=\"totalSectionCount\" [questionCount]=\"totalQuestionCount\"\r\n [durationSeconds]=\"assessmentDurationSeconds\"\r\n [confirmAction]=\"startSessionAction\" (proceeded)=\"onIntroProceeded()\">\r\n </lib-proctoring-consent>\r\n\r\n <div *ngIf=\"assessmentContext?.assessmentInstanceDTO?.duration && !previewMode && !introActive && (!disabled || timeExpired)\"\r\n class=\"d-flex align-items-center gap-md-3 gap-2 px-3 py-2 assessment-border-radius-two mb-4 timer-container assessment-bg-palette-FEF1E8\">\r\n <p class=\"assessment-text-semibold-18 assessment-text-grey-ten mb-0\">{{displayTime}}</p>\r\n <p class=\"assessment-text-grey-ten assessment-text-medium-12 mb-0\">\r\n {{ timeExpired\r\n ? labelConfig['COMMONS_ASSESSMENT.LABEL.TIMER_EXPIRED']\r\n : labelConfig['COMMONS_ASSESSMENT.LABEL.TIMER_AUTO_SUBMIT'] }}</p>\r\n </div>\r\n <ng-container *ngIf=\"assessmentQuestionPaperData?.questionPaperSectionList?.length && !introActive\">\r\n <mat-tab-group *ngIf=\"!verticalView\" animationDuration=\"0ms\" class=\"assessment-mat-custom-tabs\"\r\n [ngClass]=\"{'assessment-hide-tabs': hideSectionTabs}\" [(selectedIndex)]=\"selectedTabIndex\">\r\n <mat-tab\r\n *ngFor=\"let section of assessmentQuestionPaperData.questionPaperSectionList | orderBy; let i = index; trackBy: trackBySectionId\"\r\n [disabled]=\"shouldDisableTab(i)\">\r\n <ng-template mat-tab-label>\r\n <span class=\"assessment-text-semibold-16\"\r\n [ngClass]=\"sectionErrors[i] ? 'assessment-text-danger' : ''\">{{section.qpsName?.[0]?.text}}</span>\r\n </ng-template>\r\n <div class=\"mt-4\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sectionContent; context: { section: section, i: i }\"></ng-container>\r\n </div>\r\n </mat-tab>\r\n </mat-tab-group>\r\n\r\n <mat-accordion *ngIf=\"verticalView\" multi=\"true\" class=\"d-flex flex-column gap-4\">\r\n <mat-expansion-panel\r\n *ngFor=\"let section of assessmentQuestionPaperData.questionPaperSectionList | orderBy; let i = index; trackBy: trackBySectionId\"\r\n [expanded]=\"expandedState[i] !== false\" (opened)=\"expandedState[i] = true\"\r\n (closed)=\"expandedState[i] = false\"\r\n class=\"assessment-border-radius-two shadow-none m-0 assessment-panel bg-transparent\">\r\n <mat-expansion-panel-header class=\"assessment-bg-grey-two h-auto assessment-panel-header\">\r\n <div class=\"d-flex align-items-center justify-content-between gap-2 col-12 pe-3\">\r\n <span class=\"assessment-text-semibold-16\"\r\n [ngClass]=\"sectionErrors[i] ? 'assessment-text-danger' : ''\">\r\n {{section.qpsName?.[0]?.text}}</span>\r\n\r\n <ng-container *ngIf=\"sectionWiseScore?.[section?.id] as sectionScore\">\r\n <div *ngIf=\"(sectionScore?.totalMarks ?? 0) > 0\"\r\n class=\"d-flex align-items-center gap-2 assessment-text-primary-four\">\r\n <span *ngIf=\"(sectionScore?.skillScores?.length ?? 0) > 0\"\r\n class=\"assessment-text-medium-11 assessment-text-grey-ten px-2 py-1 assessment-border-radius-two skill-chip cursor-pointer\"\r\n (click)=\"$event.stopPropagation(); openSkillAllocationDialog(sectionScore?.skillScores)\">\r\n {{sectionScore?.skillScores?.length}}\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.SKILLS']}}\r\n </span>\r\n <span class=\"white-space-nowrap assessment-text-semibold-13\">\r\n <span class=\"assessment-text-medium-15 me-1\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.SCORE']}}:</span>\r\n {{sectionScore.obtainedMarks || 0}}/{{sectionScore.totalMarks}}\r\n </span>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </mat-expansion-panel-header>\r\n <div class=\"mt-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"sectionContent; context: { section: section, i: i }\"></ng-container>\r\n </div>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n </ng-container>\r\n\r\n <div *ngIf=\"!assessmentQuestionPaperData?.questionPaperSectionList?.length\"\r\n class=\"h-100 d-flex flex-column align-items-center justify-content-center gap-3\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.NO_QUESTIONS']\" class=\"col-sm-auto col-6\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/no-questions.svg')\" />\r\n <div class=\"text-center\">\r\n <p class=\"mb-1 assessment-text-medium-18\">{{labelConfig['COMMONS_ASSESSMENT.LABEL.NO_QUESTIONS']}}</p>\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"showOverallRemarks && assessmentQuestionPaperData?.questionPaperSectionList?.length\" class=\"mt-3\">\r\n <p class=\"assessment-text-medium-15 mb-2\">{{labelConfig['COMMONS_ASSESSMENT.LABEL.OVERALL_REMARKS']}}</p>\r\n <textarea\r\n class=\"col-12 assessment-text-regular-13 assessment-input-border-one assessment-border-radius-two assessment-input-padding outline-0 assessment-bg-grey-one\"\r\n rows=\"3\" [formControl]=\"overallNotesCtrl\"\r\n [placeholder]=\"labelConfig['COMMONS_ASSESSMENT.PLACEHOLDER.REMARKS']\"></textarea>\r\n </div>\r\n </div>\r\n <div *ngIf=\"showFooter && !introActive\"\r\n class=\"bg-white p-3 position-sticky bottom-0 d-flex align-items-center justify-content-end border-top gap-3 z-index-1\">\r\n <button\r\n class=\"assessment-zoom-animation assessment-border-radius-two assessment-button-padding-large assessment-btn-primary-transparent assessment-text-semibold-13\"\r\n (click)=\"goBack()\" *ngIf=\"selectedTabIndex > 0 && !verticalView\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.GO_BACK']}}</button>\r\n <button [disabled]=\"isSubmitting || (disabled && !enableMarks && !showOverallRemarks) || isCheckingLink\" (click)=\"verticalView ? goNext(true) : goNext()\"\r\n class=\"assessment-zoom-animation assessment-border-radius-two assessment-button-padding-large assessment-btn-primary assessment-text-semibold-13 position-relative\">\r\n <span [ngClass]=\"{'opacity-0': isSubmitting}\">\r\n {{ (verticalView || selectedTabIndex === sectionFormGroups.length - 1) ?\r\n labelConfig['COMMONS_ASSESSMENT.LABEL.SUBMIT'] : labelConfig['COMMONS_ASSESSMENT.LABEL.NEXT'] }}\r\n </span>\r\n <mat-spinner *ngIf=\"isSubmitting\" [diameter]=\"20\"\r\n class=\"position-absolute top-50 start-50 translate-middle assessment-spinner-white\"></mat-spinner>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<ng-template #loader>\r\n <div class=\"h-100 col-12 d-flex align-items-center justify-content-center py-5\">\r\n <mat-spinner diameter=\"60\" class=\"assessment-spinner-primary\"></mat-spinner>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Recursive Template for Questions & Child Questions -->\r\n<ng-template #questionTemplate let-questionId=\"questionId\" let-isMandatory=\"isMandatory\" let-groupIndex=\"groupIndex\"\r\n let-parentOptionId=\"parentOptionId\" let-parentQuestionId=\"parentQuestionId\" let-sequence=\"sequence\">\r\n <div *ngIf=\"sectionFormGroups[groupIndex].formGroup as formGroup\" [formGroup]=\"formGroup\"\r\n [id]=\"'question-container-' + questionId\">\r\n <div class=\"assessment-border-radius-two assessment-bg-white\"\r\n [ngClass]=\"{'p-3 assessment-card-border': !parentOptionId}\" *ngIf=\"questionBank[questionId] as question\">\r\n <div class=\"d-flex flex-md-row flex-column gap-2 align-items-start\">\r\n <div class=\"flex-grow-1 d-flex align-items-start gap-1\">\r\n <span class=\"assessment-text-medium-15 text-nowrap d-md-block d-none\"\r\n *ngIf=\"sequence\">{{sequence}}.</span>\r\n <div class=\"flex-grow-1\">\r\n <div class=\"d-flex gap-2 align-items-start col-12\">\r\n <div class=\"flex-grow-1\">\r\n <p class=\"assessment-text-medium-15 mb-0 d-flex gap-1\">\r\n <span>\r\n <span [innerHtml]=\"question.questionText?.[0]?.text\"></span>\r\n <span *ngIf=\"isMandatory\"\r\n class=\"assessment-text-regular-11 assessment-text-grey-eight\">\r\n ({{labelConfig['COMMONS_ASSESSMENT.LABEL.MANDATORY']}})</span>\r\n </span>\r\n </p>\r\n <div class=\"mt-3 col-12\" *ngIf=\"question?.mediaUrl?.length\">\r\n <ng-container\r\n *ngTemplateOutlet=\"VideoTemplate; context:{videoUrl:question?.mediaUrl}\"></ng-container>\r\n </div>\r\n </div>\r\n <ng-container *ngIf=\"question.hintText?.length && !previewMode\">\r\n <img [src]=\"imageConfig['COMMONS_ASSESSMENT.ICON.INFO']\" class=\"info-icon\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/info.svg')\"\r\n cdkOverlayOrigin #trigger=\"cdkOverlayOrigin\"\r\n (mouseenter)=\"tooltipState[question.id!] = true\"\r\n (mouseleave)=\"tooltipState[question.id!] = false\" class=\"cursor-pointer\" />\r\n <ng-template cdkConnectedOverlay [cdkConnectedOverlayOrigin]=\"trigger\"\r\n [cdkConnectedOverlayOpen]=\"tooltipState[question.id!] || false\"\r\n [cdkConnectedOverlayPositions]=\"[{ originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -8, offsetY: 0 }, { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 8, offsetY: 0 }]\">\r\n <div class=\"assessment-bg-grey-two assessment-tooltip-border p-3 assessment-border-radius-two assessment-box-shadow-tooltip question-info assessment-text-regular-13\"\r\n (mouseenter)=\"tooltipState[question.id!] = true\"\r\n (mouseleave)=\"tooltipState[question.id!] = false\"\r\n [innerHTML]=\"question.hintText\">\r\n </div>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"previewMode && !isMobile\" class=\"mt-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"isMobile\" class=\"col-12 mt-2\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n\r\n <!-- Assessor Marks Logic -->\r\n <div class=\"assessment-marks-field\"\r\n *ngIf=\"enableMarks && shouldShowMarksDropdown(question) && formGroup.get(question.id + '_marks') as marksControl\">\r\n <label class=\"assessment-text-medium-12 assessment-text-grey-ten\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.MARKS']}}(Max: {{question.weight}})</label>\r\n <input (keydown)=\"preventNegativeInput($event)\"\r\n (input)=\"checkMaxVal($event, marksControl, question?.weight)\"\r\n class=\"col-12 assessment-input-border-one assessment-border-radius-two px-2 py-1 outline-0 assessment-bg-grey-one assessment-text-medium-12\"\r\n [formControlName]=\"question.id + '_marks'\" type=\"number\" min=\"0\"\r\n (wheel)=\"$event.preventDefault()\">\r\n </div>\r\n </div>\r\n\r\n <!-- answer field -->\r\n <div *ngIf=\"!previewMode && !isMobile\" class=\"mt-3\">\r\n <ng-container\r\n *ngTemplateOutlet=\"answerField; context: {question: question,previewMode: previewMode,isMandatory: isMandatory,groupIndex: groupIndex,parentOptionId: parentOptionId,parentQuestionId: parentQuestionId}\"></ng-container>\r\n </div>\r\n\r\n <!-- Child Questions and Remarks Rendering Logic based on checked form state -->\r\n <ng-container *ngIf=\"question.defaultOptionsList?.length\">\r\n <ng-container *ngFor=\"let option of question.defaultOptionsList; trackBy: trackByOptionId\">\r\n\r\n <ng-container *ngIf=\"isOptionSelected(formGroup, question, option.options?.id)\">\r\n\r\n <!-- REMARKS FIELD -->\r\n <div class=\"mt-3\"\r\n *ngIf=\"option.remarksRequired && formGroup.get(question.id + '_remarks_' + option.id) as remarksControl\">\r\n <p class=\"assessment-text-regular-15 mb-2\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.REMARKS']}}</p>\r\n <textarea *ngIf=\"!previewMode\" formControlName=\"{{question.id}}_remarks_{{option.id}}\"\r\n rows=\"2\" [placeholder]=\"labelConfig['COMMONS_ASSESSMENT.PLACEHOLDER.REMARKS']\"\r\n [ngClass]=\"remarksControl.invalid && remarksControl.touched ? 'assessment-input-border-invalid' : ''\"\r\n class=\"col-12 assessment-text-regular-13 assessment-input-border-one assessment-border-radius-two assessment-input-padding outline-0 assessment-bg-grey-one\"></textarea>\r\n <ng-container *ngIf=\"previewMode\">\r\n <span class=\"assessment-text-regular-13 assessment-text-grey-nine\">\r\n {{ remarksControl.value }}</span>\r\n </ng-container>\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"remarksControl.invalid && remarksControl.touched\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.FIELD_REQUIRED']}}\r\n </div>\r\n </div>\r\n\r\n <!-- CHILD QUESTIONS RECURSION -->\r\n <div class=\"col-12 mt-4 d-flex flex-column gap-3\" *ngIf=\"option.childQuestionList?.length\">\r\n <ng-container *ngFor=\"let childId of option.childQuestionList; let childIndex = index; trackBy: trackByChildId\">\r\n <ng-container *ngTemplateOutlet=\"questionTemplate; context: {\r\n questionId: childId,\r\n isMandatory: questionBank[childId]?.isMandatory,\r\n groupIndex: groupIndex,\r\n parentOptionId: option.id,\r\n parentQuestionId: question.id,\r\n sequence: sequence + '.' + (childIndex + 1)\r\n }\">\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- answer field template -->\r\n<ng-template #answerField let-question=\"question\" let-previewMode=\"previewMode\" let-isMandatory=\"isMandatory\"\r\n let-groupIndex=\"groupIndex\" let-parentOptionId=\"parentOptionId\" let-parentQuestionId=\"parentQuestionId\">\r\n <div *ngIf=\"sectionFormGroups[groupIndex].formGroup\" [formGroup]=\"sectionFormGroups[groupIndex].formGroup\"\r\n class=\"col-12\">\r\n <ng-container [ngSwitch]=\"question.questionType?.code\">\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_SHORT'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_LONG'\">\r\n <lib-question-type-long [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-long>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.SUBJECTIVE_RICH_TEXT'\">\r\n <lib-question-type-editor [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [previewMode]=\"previewMode\"\r\n [labelConfig]=\"labelConfig\"></lib-question-type-editor>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.OBJECTIVE'\">\r\n <lib-question-type-objective [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [showCorrectAnswers]=\"showCorrectAnswers\" [imageConfig]=\"imageConfig\"\r\n [answerObj]=\"getQuestionAnswerObj(question.id!, parentOptionId, parentQuestionId)\"></lib-question-type-objective>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.MULTI_SELECT'\">\r\n <lib-question-type-multiselect [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [showCorrectAnswers]=\"showCorrectAnswers\" [imageConfig]=\"imageConfig\"\r\n [answerObj]=\"getQuestionAnswerObj(question.id!, parentOptionId, parentQuestionId)\"></lib-question-type-multiselect>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.PREFERENCE'\">\r\n <lib-question-type-preference [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\"></lib-question-type-preference>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.NUMBER'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.EMAIL'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.CONTACT_NUMBER'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.URL'\">\r\n <lib-question-type-short [question]=\"question\" [formControlName]=\"question.id!\" [required]=\"isMandatory\"\r\n [previewMode]=\"previewMode\" [labelConfig]=\"labelConfig\"></lib-question-type-short>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.FILE_UPLOAD'\">\r\n <lib-question-type-file-upload [question]=\"question\" [assessmentInstanceId]=\"assessmentInstanceId\"\r\n [formControlName]=\"question.id!\" [required]=\"isMandatory\" [labelConfig]=\"labelConfig\"\r\n [imageConfig]=\"imageConfig\" (snackbarMessage)=\"snackbarMessage.emit($event)\"></lib-question-type-file-upload>\r\n </ng-container>\r\n\r\n <ng-container *ngSwitchCase=\"'QUESTION_TYPE.DATE_PICKER'\">\r\n <lib-question-type-date-picker [question]=\"question\" [formControlName]=\"question.id!\"\r\n [required]=\"isMandatory\" [previewMode]=\"previewMode\"\r\n [labelConfig]=\"labelConfig\"></lib-question-type-date-picker>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Error Messages and Character Count Container -->\r\n <ng-container\r\n *ngIf=\"!previewMode && sectionFormGroups[groupIndex].formGroup.get(question.id?.toString() || '') as control\">\r\n <div class=\"d-flex justify-content-between align-items-start mt-1\">\r\n <span>\r\n <div class=\"assessment-text-regular-12 assessment-text-danger\"\r\n *ngIf=\"control.touched && control.errors?.['required']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.REQUIRED_RESPONSE']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['pattern']\">\r\n {{question?.validationMessage || labelConfig['COMMONS_ASSESSMENT.ERROR.INVALID_FORMAT']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['privateGdriveLink']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.PRIVATE_DRIVE_LINK']}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['minlength']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MIN_CHARS']?.replace('{{length}}',\r\n control.errors?.['minlength'].requiredLength + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxlength']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_CHARS']?.replace('{{length}}',\r\n control.errors?.['maxlength'].requiredLength + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['minOptions']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MIN_OPTIONS']?.replace('{{count}}',\r\n control.errors?.['minOptions'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxOptions']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_OPTIONS']?.replace('{{count}}',\r\n control.errors?.['maxOptions'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxFiles']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_FILES']?.replace('{{count}}',\r\n control.errors?.['maxFiles'].required + '')}}\r\n </div>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-danger mt-1\"\r\n *ngIf=\"control.touched && control.errors?.['maxFileSize']\">\r\n {{labelConfig['COMMONS_ASSESSMENT.ERROR.MAX_FILE_SIZE']?.replace('{{size}}',\r\n control.errors?.['maxFileSize'].requiredSize + '')}}\r\n </div>\r\n </span>\r\n\r\n <div class=\"assessment-text-regular-12 assessment-text-grey-seven white-space-nowrap ms-2\"\r\n *ngIf=\"getMaxCharCount(question) > 0\">\r\n {{ getRemainingChars(question, control) }}\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.CHARACTER']}}{{getRemainingChars(question, control) !==\r\n 1\r\n ? 's' : ''}} {{labelConfig['COMMONS_ASSESSMENT.LABEL.REMAINING']}}\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Reusable Section Form Template -->\r\n<ng-template #sectionContent let-section=\"section\" let-i=\"i\">\r\n <form class=\"w-100\" *ngIf=\"sectionFormGroups[i].formGroup\" [formGroup]=\"sectionFormGroups[i].formGroup\"\r\n [name]=\"'sectionfrm-' + i\" novalidate>\r\n <div class=\"d-flex justify-content-between align-items-center mb-4\"\r\n *ngIf=\"!previewMode && (section?.qpsDesc?.[0]?.text || section?.mediaUrl)\">\r\n <span class=\"assessment-text-semibold-14 assessment-text-grey-ten\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.TOTAL_QUESTIONS']}}: {{ section?.totalQuestions || 0 }}\r\n </span>\r\n <button (click)=\"openInstructionsDialog(section)\"\r\n class=\"assessment-zoom-animation assessment-button-padding assessment-text-medium-13 assessment-btn-primary-transparent\">\r\n {{labelConfig['COMMONS_ASSESSMENT.LABEL.VIEW_INSTRUCTIONS']}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"col-12 d-flex flex-column gap-3\">\r\n <ng-container *ngFor=\"let sq of section.sectionQuestionsList | orderBy; let j = index; trackBy: trackBySectionQuestion\">\r\n <ng-container *ngTemplateOutlet=\"questionTemplate; context: {\r\n questionId: sq.questionId,\r\n isMandatory: questionBank[sq.questionId]?.isMandatory,\r\n groupIndex: i,\r\n parentOptionId: null,\r\n parentQuestionId: null,\r\n sequence: j + 1\r\n }\"></ng-container>\r\n </ng-container>\r\n </div>\r\n </form>\r\n</ng-template>\r\n\r\n<!-- video preview -->\r\n<ng-template let-videoUrl=\"videoUrl\" #VideoTemplate>\r\n <div class=\"assessment-border-radius-two overflow-hidden col-md-10 col-12\">\r\n <video *ngIf=\"videoUrl?.includes('.mp4') else youtubeVideo\" width=\"400\" controls class=\"mw-100 d-block mx-auto\">\r\n <source [src]=\"videoUrl\" type=\"video/mp4\">\r\n </video>\r\n <ng-template #youtubeVideo>\r\n <div class=\"youtube-video position-relative h-100\">\r\n <iframe [src]=\"addYoutubeIframeSrc(videoUrl)\" title=\"YouTube video player\" frameborder=\"0\"\r\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\r\n allowfullscreen class=\"position-absolute top-0 start-0 w-100 h-100 d-block\">\r\n </iframe>\r\n </div>\r\n </ng-template>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";.assessment-text-grey-ten{color:var(--assessment-grey-ten)!important}.assessment-bg-grey-ten{background-color:var(--assessment-grey-ten)!important}.assessment-text-grey-nine{color:var(--assessment-grey-nine)!important}.assessment-bg-grey-nine{background-color:var(--assessment-grey-nine)!important}.assessment-text-grey-eight{color:var(--assessment-grey-eight)!important}.assessment-bg-grey-eight{background-color:var(--assessment-grey-eight)!important}.assessment-text-grey-seven{color:var(--assessment-grey-seven)!important}.assessment-bg-grey-seven{background-color:var(--assessment-grey-seven)!important}.assessment-text-grey-six{color:var(--assessment-grey-six)!important}.assessment-bg-grey-six{background-color:var(--assessment-grey-six)!important}.assessment-text-grey-five{color:var(--assessment-grey-five)!important}.assessment-bg-grey-five{background-color:var(--assessment-grey-five)!important}.assessment-text-grey-four{color:var(--assessment-grey-four)!important}.assessment-bg-grey-four{background-color:var(--assessment-grey-four)!important}.assessment-text-grey-three{color:var(--assessment-grey-three)!important}.assessment-bg-grey-three{background-color:var(--assessment-grey-three)!important}.assessment-text-grey-two{color:var(--assessment-grey-two)!important}.assessment-bg-grey-two{background-color:var(--assessment-grey-two)!important}.assessment-text-grey-one{color:var(--assessment-grey-one)!important}.assessment-bg-grey-one{background-color:var(--assessment-grey-one)!important}.assessment-text-white{color:var(--assessment-white)!important}.assessment-bg-white{background-color:var(--assessment-white)!important}.assessment-text-black{color:var(--assessment-black)!important}.assessment-bg-black{background-color:var(--assessment-black)!important}.assessment-text-danger{color:var(--assessment-danger)!important}.assessment-bg-danger{background-color:var(--assessment-danger)!important}.assessment-text-danger-bg{color:var(--assessment-danger-bg)!important}.assessment-bg-danger-bg{background-color:var(--assessment-danger-bg)!important}.assessment-text-success{color:var(--assessment-success)!important}.assessment-bg-success{background-color:var(--assessment-success)!important}.assessment-text-success-bg{color:var(--assessment-success-bg)!important}.assessment-bg-success-bg{background-color:var(--assessment-success-bg)!important}.assessment-text-warning{color:var(--assessment-warning)!important}.assessment-bg-warning{background-color:var(--assessment-warning)!important}.assessment-text-warning-bg{color:var(--assessment-warning-bg)!important}.assessment-bg-warning-bg{background-color:var(--assessment-warning-bg)!important}.assessment-text-primary-one{color:var(--assessment-primary-one)!important}.assessment-bg-primary-one{background-color:var(--assessment-primary-one)!important}.assessment-text-primary-four{color:var(--assessment-primary-four)!important}.assessment-bg-primary-four{background-color:var(--assessment-primary-four)!important}.assessment-text-palette-EDF3FD{color:var(--assessment-palette-EDF3FD)!important}.assessment-bg-palette-EDF3FD{background-color:var(--assessment-palette-EDF3FD)!important}.assessment-text-palette-C8DAF9{color:var(--assessment-palette-C8DAF9)!important}.assessment-bg-palette-C8DAF9{background-color:var(--assessment-palette-C8DAF9)!important}.assessment-text-palette-ADC9F6{color:var(--assessment-palette-ADC9F6)!important}.assessment-bg-palette-ADC9F6{background-color:var(--assessment-palette-ADC9F6)!important}.assessment-text-palette-FEF9F1{color:var(--assessment-palette-FEF9F1)!important}.assessment-bg-palette-FEF9F1{background-color:var(--assessment-palette-FEF9F1)!important}.assessment-text-palette-F9DAA6{color:var(--assessment-palette-F9DAA6)!important}.assessment-bg-palette-F9DAA6{background-color:var(--assessment-palette-F9DAA6)!important}.assessment-text-palette-E8F7F0{color:var(--assessment-palette-E8F7F0)!important}.assessment-bg-palette-E8F7F0{background-color:var(--assessment-palette-E8F7F0)!important}.assessment-text-palette-B7E7CF{color:var(--assessment-palette-B7E7CF)!important}.assessment-bg-palette-B7E7CF{background-color:var(--assessment-palette-B7E7CF)!important}.assessment-text-palette-FEF1E8{color:var(--assessment-palette-FEF1E8)!important}.assessment-bg-palette-FEF1E8{background-color:var(--assessment-palette-FEF1E8)!important}.assessment-text-palette-FAD2B9{color:var(--assessment-palette-FAD2B9)!important}.assessment-bg-palette-FAD2B9{background-color:var(--assessment-palette-FAD2B9)!important}.assessment-box-shadow-one{box-shadow:var(--assessment-box-shadow-one)!important}.assessment-border-radius-one{border-radius:var(--assessment-border-radius-one)!important}.assessment-border-radius-two{border-radius:var(--assessment-border-radius-two)!important}.assessment-border-radius-three{border-radius:var(--assessment-border-radius-three)!important}.assessment-border-radius-four{border-radius:var(--assessment-border-radius-four)!important}.assessment-border-radius-five{border-radius:var(--assessment-border-radius-five)!important}.assessment-border-radius-six{border-radius:var(--assessment-border-radius-six)!important}.assessment-input-border-one{border:var(--assessment-input-border-one)!important}.assessment-input-border-invalid{border:var(--assessment-input-border-invalid)!important}.assessment-input-focus-border{border:var(--assessment-input-focus-border)!important}.assessment-border-two{border:var(--assessment-border-two)!important}.assessment-card-border{border:var(--assessment-card-border)!important}.assessment-tooltip-border{border:var(--assessment-tooltip-border)!important}.assessment-box-shadow-tooltip{box-shadow:var(--assessment-box-shadow-tooltip)!important}.assessment-input-focus-box-shadow{box-shadow:var(--assessment-input-focus-box-shadow)!important}.assessment-button-padding{padding:var(--assessment-button-padding)!important}.assessment-button-padding-large{padding:var(--assessment-button-padding-large)!important}.assessment-input-padding{padding:var(--assessment-input-padding)!important}.assessment-text-font-family{color:var(--assessment-font-family)!important}.assessment-bg-font-family{background-color:var(--assessment-font-family)!important}.assessment-text-regular-12{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-semibold-12{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-medium-11{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.48rem + .25vw);line-height:calc(.8rem + .25vw)}.assessment-text-medium-10{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.42rem + .2vw);line-height:calc(.72rem + .2vw)}.assessment-text-regular-11{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.48rem + .25vw);line-height:calc(.8rem + .25vw)}.assessment-text-medium-12{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.48rem + .3vw);line-height:calc(.9rem + .3vw)}.assessment-text-regular-13{font-weight:400;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-semibold-13{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-medium-13{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.64rem + .2vw)!important;line-height:calc(.9rem + .2vw)!important}.assessment-text-medium-14{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.7rem + .2vw)!important;line-height:calc(1.2rem + .2vw)!important}.assessment-text-semibold-14{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.7rem + .2vw);line-height:calc(1.2rem + .2vw)}.assessment-text-regular-15{font-weight:400;font-family:var(--assessment-font-family);font-size:calc(.85rem + .1vw);line-height:calc(1.4rem + .1vw)}.assessment-text-medium-15{font-weight:500;font-family:var(--assessment-font-family);font-size:calc(.85rem + .1vw);line-height:calc(1.25rem + .1vw)}.assessment-text-semibold-15{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.85rem + .1vw);line-height:calc(1.25rem + .1vw)}.assessment-text-semibold-16{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(.77rem + .25vw);line-height:calc(1.25rem + .2vw)}.assessment-text-medium-16{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(.77rem + .25vw);line-height:calc(1.25rem + .2vw)}.assessment-text-medium-18{font-weight:500;font-family:var(--assessment-font-family)!important;font-size:calc(1rem + .125vw)!important;line-height:calc(1.5rem + .1vw)!important}.assessment-text-semibold-18{font-weight:600;font-family:var(--assessment-font-family)!important;font-size:calc(1rem + .125vw)!important;line-height:calc(1.5rem + .1vw)!important}@media (min-height: 100vw) and (orientation: portrait){.assessment-text-medium-18,.assessment-text-semibold-18{font-size:calc(1rem + .1vh)!important;line-height:calc(1.6rem + .1vh)!important}.assessment-text-medium-16,.assessment-text-semibold-16{font-size:calc(.9rem + .2vh)!important;line-height:calc(1.4rem + .2vh)!important}.assessment-text-regular-15,.assessment-text-semibold-15{font-size:calc(.8rem + .2vh);line-height:calc(1.27rem + .2vh)}.assessment-text-medium-15{font-size:calc(.82rem + .2vh);line-height:calc(1.27rem + .2vh)}.assessment-text-medium-12,.assessment-text-regular-12,.assessment-text-semibold-12{font-size:calc(.5rem + .4vh);line-height:calc(.8rem + .4vh)}.assessment-text-medium-14,.assessment-text-semibold-14{font-size:calc(.8rem + .1vh)!important;line-height:calc(1.2rem + .2vh)!important}.assessment-text-regular-13,.assessment-text-medium-13,.assessment-text-semibold-13{font-size:calc(.7rem + .2vh)!important;line-height:calc(1rem + .3vh)!important}.assessment-text-regular-11,.assessment-text-medium-11{font-size:calc(.5rem + .2vh)!important;line-height:calc(.8rem + .2vh)!important}.assessment-text-medium-10{font-size:calc(.45rem + .2vh)!important;line-height:calc(.72rem + .2vh)!important}}.assessment-btn-primary{background-color:var(--assessment-primary-one);color:var(--assessment-white);border:.064rem solid var(--assessment-primary-one);border-radius:var(--assessment-border-radius-two)}.assessment-btn-primary-transparent{background-color:var(--assessment-white);color:var(--assessment-primary-one);border-radius:var(--assessment-border-radius-two);border:.064rem solid var(--assessment-primary-one)}.assessment-zoom-animation{transition:transform .2s ease;transform:translateZ(0);text-rendering:optimizeLegibility}.assessment-zoom-animation:hover{transform:scale(1.03)}.assessment-zoom-animation:active{transform:scale(1)}.assessment-zoom-animation:disabled{transform:none!important}.change-direction{transform:rotate(180deg);transition:.3s ease-out}.change-direction-reverse{transform:rotate(0);transition:.3s ease-out}.outline-0{outline:none}.cursor-grab{cursor:grab}.cursor-pointer{cursor:pointer}.action-icon{width:1.2rem}.mat-menu-item,.mat-mdc-menu-item{height:inherit;min-height:unset;--mat-menu-item-label-text-font: var(--assessment-font-family) !important;--mat-menu-item-label-text-size: 14px !important;--mat-menu-item-label-text-weight: 600 !important;--mat-menu-item-label-text-line-height: inherit !important}.skill-chip{width:-moz-fit-content;width:fit-content;background:var(--assessment-palette-EDF3FD);border:.064rem solid var(--assessment-palette-C8DAF9)}.assessment-form-check-input-primary-one{min-height:unset}.assessment-form-check-input-primary-one .form-check-input{width:1rem;height:1rem}.assessment-form-check-input-primary-one .form-check-input:checked{background-color:var(--assessment-primary-one);color:var(--assessment-primary-one)}.assessment-form-check-input-primary-one .form-check-input:disabled{opacity:.8}.form-check-input:checked{background-color:var(--assessment-primary-one);border-color:var(--assessment-primary-one)}.form-check-input:focus{border-color:var(--assessment-primary-one);box-shadow:none}.height-without-footer{height:calc(100% - 4.4rem)!important}.z-index-1{z-index:1}.question-info{min-width:15rem;max-width:40vw}@media screen and (max-width: 768px){.question-info{max-width:75vw}}.assessment-marks-field{min-width:6.5rem;width:6.5rem}.youtube-video{aspect-ratio:16/9}.assessment-panel-header{padding-top:.7rem;padding-bottom:.7rem}.timer-container{border:.064rem solid var(--assessment-palette-FAD2B9)}.info-icon{width:1.2rem}\n"], components: [{ type: ProctoringConsentComponent, selector: "lib-proctoring-consent", inputs: ["labelConfig", "proctoringEnabled", "requireCapture", "sectionCount", "questionCount", "durationSeconds", "confirmAction"], outputs: ["proceeded"] }, { type: i8__namespace.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple"], exportAs: ["matTabGroup"] }, { type: i8__namespace.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby"], exportAs: ["matTab"] }, { type: i3__namespace.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { type: i3__namespace.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }, { type: i10__namespace.MatSpinner, selector: "mat-spinner", inputs: ["color"] }, { type: QuestionTypeShortComponent, selector: "lib-question-type-short", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeLongComponent, selector: "lib-question-type-long", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeEditorComponent, selector: "lib-question-type-editor", inputs: ["required", "question", "previewMode", "labelConfig"] }, { type: QuestionTypeObjectiveComponent, selector: "lib-question-type-objective", inputs: ["required", "question", "showCorrectAnswers", "imageConfig", "answerObj"], outputs: ["viewChild"] }, { type: QuestionTypeMultiselectComponent, selector: "lib-question-type-multiselect", inputs: ["required", "question", "showCorrectAnswers", "imageConfig", "answerObj"], outputs: ["viewChild"] }, { type: QuestionTypePreferenceComponent, selector: "lib-question-type-preference", inputs: ["required", "question"], outputs: ["viewChild"] }, { type: QuestionTypeFileUploadComponent, selector: "lib-question-type-file-upload", inputs: ["required", "assessmentInstanceId", "question", "labelConfig", "imageConfig"], outputs: ["snackbarMessage"] }, { type: QuestionTypeDatePickerComponent, selector: "lib-question-type-date-picker", inputs: ["required", "question", "previewMode", "labelConfig"] }], directives: [{ type: i2__namespace$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2__namespace$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2__namespace$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i8__namespace.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { type: i2__namespace$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3__namespace.MatAccordion, selector: "mat-accordion", inputs: ["multi", "displayMode", "togglePosition", "hideToggle"], exportAs: ["matAccordion"] }, { type: i1__namespace$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1__namespace$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1__namespace$2.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i1__namespace$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1__namespace$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i20__namespace.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { type: i20__namespace.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayPositions", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayTransformOriginOn"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { type: i1__namespace$2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { type: i1__namespace$2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i1__namespace$2.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i2__namespace$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2__namespace$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i1__namespace$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i1__namespace$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }], pipes: { "orderBy": OrderByPipe } });
3824
3853
  i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0__namespace, type: AssessmentTakerComponent, decorators: [{
3825
3854
  type: i0.Component,
3826
3855
  args: [{
@@ -4283,6 +4312,8 @@
4283
4312
  var _a;
4284
4313
  this.http = http;
4285
4314
  this.assetsBaseUrl = (_a = document === null || document === void 0 ? void 0 : document.baseURI) === null || _a === void 0 ? void 0 : _a.replace(/\/$/, '');
4315
+ // cache the static config JSON so multiple maker instances on one page fetch it only once
4316
+ this.configCache = {};
4286
4317
  }
4287
4318
  AssessmentMakerService.prototype.getHeaders = function () {
4288
4319
  return new i1$1.HttpHeaders().set('X-Library-Source', 'commons-assessment');
@@ -4306,7 +4337,17 @@
4306
4337
  return param;
4307
4338
  };
4308
4339
  AssessmentMakerService.prototype.getConfigJSON = function (fileName) {
4309
- return this.http.get(this.assetsBaseUrl + "/assets/commons-assessment/" + fileName + ".json");
4340
+ var _this = this;
4341
+ if (!this.configCache[fileName]) {
4342
+ this.configCache[fileName] = this.http
4343
+ .get(this.assetsBaseUrl + "/assets/commons-assessment/" + fileName + ".json")
4344
+ .pipe(
4345
+ // drop the cache entry on error so a later render can retry the fetch
4346
+ operators.catchError(function (err) { delete _this.configCache[fileName]; return rxjs.throwError(err); }),
4347
+ // share one request across all subscribers and replay the loaded config to later ones
4348
+ operators.shareReplay(1));
4349
+ }
4350
+ return this.configCache[fileName];
4310
4351
  };
4311
4352
  AssessmentMakerService.prototype.getResponseCount = function (assessmentInstanceId) {
4312
4353
  return this.http.get(assessmentMakerController.getResponseCount + this.createParams({ assessmentInstanceId: assessmentInstanceId }), { headers: this.getHeaders() });