commons-assessment 12.1.0 → 12.1.2-dev.0

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.
Files changed (82) hide show
  1. package/README.md +11 -0
  2. package/bundles/commons-assessment.umd.js +2304 -247
  3. package/bundles/commons-assessment.umd.js.map +1 -1
  4. package/esm2015/lib/modules/assessment-maker/assessment-maker.component.js +293 -32
  5. package/esm2015/lib/modules/assessment-maker/assessment-maker.module.js +10 -5
  6. package/esm2015/lib/modules/assessment-maker/components/add-edit-section-introduction/add-edit-section-introduction.component.js +1 -1
  7. package/esm2015/lib/modules/assessment-maker/components/assessment-builder/assessment-builder.component.js +77 -22
  8. package/esm2015/lib/modules/assessment-maker/components/question-bank-picker/question-bank-picker.component.js +276 -0
  9. package/esm2015/lib/modules/assessment-maker/components/question-details/question-details.component.js +22 -2
  10. package/esm2015/lib/modules/assessment-maker/services/assessment-builder.service.js +22 -7
  11. package/esm2015/lib/modules/assessment-maker/services/assessment-maker.service.js +32 -5
  12. package/esm2015/lib/modules/assessment-taker/assessment-taker.component.js +365 -42
  13. package/esm2015/lib/modules/assessment-taker/assessment-taker.module.js +9 -3
  14. package/esm2015/lib/modules/assessment-taker/components/proctoring-consent/proctoring-consent.component.js +137 -0
  15. package/esm2015/lib/modules/assessment-taker/components/proctoring-result/proctoring-result.component.js +177 -0
  16. package/esm2015/lib/modules/assessment-taker/components/question-type-date-picker/question-type-date-picker.component.js +2 -3
  17. package/esm2015/lib/modules/assessment-taker/components/question-type-editor/question-type-editor.component.js +1 -1
  18. package/esm2015/lib/modules/assessment-taker/components/question-type-file-upload/question-type-file-upload.component.js +5 -2
  19. package/esm2015/lib/modules/assessment-taker/components/question-type-long/question-type-long.component.js +1 -1
  20. package/esm2015/lib/modules/assessment-taker/components/question-type-multiselect/question-type-multiselect.component.js +7 -3
  21. package/esm2015/lib/modules/assessment-taker/components/question-type-objective/question-type-objective.component.js +7 -3
  22. package/esm2015/lib/modules/assessment-taker/components/question-type-preference/question-type-preference.component.js +9 -4
  23. package/esm2015/lib/modules/assessment-taker/components/question-type-short/question-type-short.component.js +78 -8
  24. package/esm2015/lib/modules/assessment-taker/components/section-instructions/section-instructions.component.js +1 -1
  25. package/esm2015/lib/modules/assessment-taker/services/assessment-taker.service.js +18 -3
  26. package/esm2015/lib/modules/assessment-taker/services/proctoring.service.js +125 -0
  27. package/esm2015/lib/modules/assessment-taker/services/response-builder.service.js +15 -1
  28. package/esm2015/lib/modules/question-bank/question-bank.component.js +313 -0
  29. package/esm2015/lib/modules/question-bank/question-bank.module.js +45 -0
  30. package/esm2015/lib/shared/components/confirmation-dialog/confirmation-dialog.component.js +56 -0
  31. package/esm2015/lib/shared/components/skill-allocation/skill-allocation.component.js +5 -2
  32. package/esm2015/lib/shared/controllers.js +18 -4
  33. package/esm2015/lib/shared/interfaces/assessment.interface.js +1 -1
  34. package/esm2015/lib/shared/interfaces/proctoring.interface.js +2 -0
  35. package/esm2015/lib/shared/material-modules.js +1 -16
  36. package/esm2015/lib/shared/shared.module.js +8 -3
  37. package/esm2015/lib/shared/utils.js +19 -1
  38. package/esm2015/public-api.js +4 -1
  39. package/fesm2015/commons-assessment.js +2071 -152
  40. package/fesm2015/commons-assessment.js.map +1 -1
  41. package/lib/modules/assessment-maker/assessment-maker.component.d.ts +40 -2
  42. package/lib/modules/assessment-maker/assessment-maker.module.d.ts +6 -5
  43. package/lib/modules/assessment-maker/components/assessment-builder/assessment-builder.component.d.ts +7 -0
  44. package/lib/modules/assessment-maker/components/question-bank-picker/question-bank-picker.component.d.ts +81 -0
  45. package/lib/modules/assessment-maker/components/question-details/question-details.component.d.ts +6 -1
  46. package/lib/modules/assessment-maker/services/assessment-builder.service.d.ts +10 -3
  47. package/lib/modules/assessment-maker/services/assessment-maker.service.d.ts +15 -11
  48. package/lib/modules/assessment-taker/assessment-taker.component.d.ts +81 -2
  49. package/lib/modules/assessment-taker/assessment-taker.module.d.ts +7 -5
  50. package/lib/modules/assessment-taker/components/proctoring-consent/proctoring-consent.component.d.ts +39 -0
  51. package/lib/modules/assessment-taker/components/proctoring-result/proctoring-result.component.d.ts +82 -0
  52. package/lib/modules/assessment-taker/components/question-type-file-upload/question-type-file-upload.component.d.ts +1 -0
  53. package/lib/modules/assessment-taker/components/question-type-multiselect/question-type-multiselect.component.d.ts +1 -0
  54. package/lib/modules/assessment-taker/components/question-type-objective/question-type-objective.component.d.ts +1 -0
  55. package/lib/modules/assessment-taker/components/question-type-preference/question-type-preference.component.d.ts +1 -0
  56. package/lib/modules/assessment-taker/components/question-type-short/question-type-short.component.d.ts +14 -2
  57. package/lib/modules/assessment-taker/services/assessment-taker.service.d.ts +5 -0
  58. package/lib/modules/assessment-taker/services/proctoring.service.d.ts +40 -0
  59. package/lib/modules/assessment-taker/services/response-builder.service.d.ts +9 -0
  60. package/lib/modules/question-bank/question-bank.component.d.ts +65 -0
  61. package/lib/modules/question-bank/question-bank.module.d.ts +12 -0
  62. package/lib/shared/components/confirmation-dialog/confirmation-dialog.component.d.ts +36 -0
  63. package/lib/shared/components/skill-allocation/skill-allocation.component.d.ts +1 -0
  64. package/lib/shared/controllers.d.ts +14 -1
  65. package/lib/shared/interfaces/assessment.interface.d.ts +8 -0
  66. package/lib/shared/interfaces/proctoring.interface.d.ts +101 -0
  67. package/lib/shared/material-modules.d.ts +5 -8
  68. package/lib/shared/shared.module.d.ts +5 -4
  69. package/lib/shared/utils.d.ts +4 -0
  70. package/package.json +1 -1
  71. package/public-api.d.ts +3 -0
  72. package/src/lib/assets/images/arrow-down-blue.svg +3 -0
  73. package/src/lib/assets/images/arrow-up-blue.svg +3 -0
  74. package/src/lib/assets/images/file-import.svg +11 -0
  75. package/src/lib/assets/images/plus-white.svg +1 -0
  76. package/src/lib/assets/images/proctoring.svg +3 -0
  77. package/src/lib/assets/images/user.svg +3 -0
  78. package/src/lib/assets/json/imageConfig.json +7 -1
  79. package/src/lib/assets/json/labelConfig.json +107 -2
  80. package/src/lib/assets/theme/_theme.global.scss +6 -0
  81. package/src/lib/assets/theme/_theme.scss +17 -346
  82. package/src/lib/assets/theme/styles.scss +13 -0
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter, OnInit } from '@angular/core';
2
2
  import { CdkDragDrop } from '@angular/cdk/drag-drop';
3
3
  import { MatDialog } from '@angular/material/dialog';
4
- import { QuestionType, Assessment, RefData, AssessmentContextDTO, AssessmentInstance } from '../../shared/interfaces/assessment.interface';
4
+ import { QuestionType, Assessment, RefData, AssessmentContextDTO, AssessmentInstance, QuestionBankConfig } from '../../shared/interfaces/assessment.interface';
5
5
  import { AssessmentQuestionPaper, SectionQuestion, QuestionPaperSection } from '../../shared/interfaces/question-paper.interface';
6
6
  import { AssessmentQuestion } from '../../shared/interfaces/question.interface';
7
7
  import { AssessmentBuilderService } from './services/assessment-builder.service';
@@ -27,6 +27,11 @@ export declare class AssessmentMakerComponent implements OnInit {
27
27
  enableSkillsToQuestionMapping: boolean;
28
28
  assessmentContext: AssessmentContextDTO;
29
29
  minimumRequiredSections: number;
30
+ checkForResponses: boolean;
31
+ showProctoringToggle: boolean;
32
+ showTimeInput: boolean;
33
+ enableImportFromQuestionBank: boolean;
34
+ questionBankConfig?: QuestionBankConfig;
30
35
  assessmentIdChange: EventEmitter<number>;
31
36
  assessmentInstanceIdChange: EventEmitter<number>;
32
37
  snackbarMessage: EventEmitter<{
@@ -35,15 +40,28 @@ export declare class AssessmentMakerComponent implements OnInit {
35
40
  }>;
36
41
  showLoader: boolean;
37
42
  questionBank: Record<number, AssessmentQuestion>;
43
+ lockedQuestionsMap: Record<number, boolean>;
38
44
  assessmentQuestionPaperData: AssessmentQuestionPaper;
39
45
  configsLoaded: boolean;
40
46
  rules: any;
41
47
  isSubmitting: boolean;
42
48
  skillsList: RefData[];
49
+ responseCount: number;
50
+ proctoringEnabled: boolean;
51
+ durationMinutes: number | null;
52
+ private readonly PROCTORING_CONFIG_KEY;
43
53
  constructor(assessmentMakerService: AssessmentMakerService, assessmentBuilderService: AssessmentBuilderService, dialog: MatDialog);
44
54
  ngOnInit(): void;
55
+ private loadResponseCount;
56
+ /**
57
+ * Runs `action`, but first warns the user if the assessment already has responses
58
+ * (only when `checkForResponses` is enabled and the count is greater than 0).
59
+ */
60
+ private confirmResponsesWarning;
45
61
  getConfigsFromJSON(): void;
46
62
  loadAssessmentData(): void;
63
+ checkAssessmentQuestionsLocked(): void;
64
+ isQuestionLocked(questionId?: number): boolean;
47
65
  generateQuestionBank(): void;
48
66
  imageErrorHandler(event: any, filePath: string): void;
49
67
  focusSectionInput(sectionIndex: number, event: Event): void;
@@ -54,8 +72,22 @@ export declare class AssessmentMakerComponent implements OnInit {
54
72
  deleteParentQuestion(sectionQuestion: SectionQuestion): void;
55
73
  deleteSection(section: QuestionPaperSection): void;
56
74
  createEditQuestion(sectionDetails?: any, sectionQuestionId?: number, isChild?: boolean): void;
75
+ private openQuestionBuilder;
57
76
  duplicateSection(sectionId: number): void;
58
77
  duplicateQuestion(section: QuestionPaperSection, sectionQuestion: SectionQuestion): void;
78
+ private readProctoringConfig;
79
+ /** Initializes the minutes input from an existing instance's duration (seconds). */
80
+ private readDuration;
81
+ /** Blocks characters that would enter a negative/exponent value in the duration input. */
82
+ blockNegativeKeys(event: KeyboardEvent): void;
83
+ /** Duration to persist, in SECONDS (the unit the taker's timer uses). 0 means untimed. */
84
+ private get durationSeconds();
85
+ /**
86
+ * Returns the assessment configs with the proctoring flag ('1'/'0') upserted, preserving
87
+ * any other existing configs. Returns undefined when the proctoring toggle is not enabled
88
+ * so the saved payload is unchanged for consumers not using proctoring.
89
+ */
90
+ private buildProctoringConfigs;
59
91
  patchAssessmentAndQuestionPaper(successMessage?: string): void;
60
92
  finalSubmit(): void;
61
93
  createAssessmentInstance(): void;
@@ -65,6 +97,12 @@ export declare class AssessmentMakerComponent implements OnInit {
65
97
  filterInactiveSectionsAndQuestions(): void;
66
98
  capitalizeFirst(text: string | undefined): string;
67
99
  getSkillsList(): void;
100
+ trackBySectionId(index: number, section: any): string;
101
+ trackBySectionQuestion(index: number, sq: any): string;
102
+ private collectExistingQuestionIds;
103
+ openQuestionBankPicker(section?: QuestionPaperSection): void;
104
+ private importQuestionsToSection;
105
+ private createAssessmentAndQuestionPaperOnImport;
68
106
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentMakerComponent, never>;
69
- static ɵcmp: i0.ɵɵComponentDeclaration<AssessmentMakerComponent, "lib-assessment-maker", never, { "labelConfig": "labelConfig"; "imageConfig": "imageConfig"; "questionTypes": "questionTypes"; "showFooter": "showFooter"; "customRules": "customRules"; "assessmentId": "assessmentId"; "assessmentInstanceId": "assessmentInstanceId"; "defaultAssessmentDTO": "defaultAssessmentDTO"; "predefinedAssessmentInstance": "predefinedAssessmentInstance"; "enableSkillsToQuestionMapping": "enableSkillsToQuestionMapping"; "assessmentContext": "assessmentContext"; "minimumRequiredSections": "minimumRequiredSections"; }, { "assessmentIdChange": "assessmentIdChange"; "assessmentInstanceIdChange": "assessmentInstanceIdChange"; "snackbarMessage": "snackbarMessage"; }, never, never>;
107
+ static ɵcmp: i0.ɵɵComponentDeclaration<AssessmentMakerComponent, "lib-assessment-maker", never, { "labelConfig": "labelConfig"; "imageConfig": "imageConfig"; "questionTypes": "questionTypes"; "showFooter": "showFooter"; "customRules": "customRules"; "assessmentId": "assessmentId"; "assessmentInstanceId": "assessmentInstanceId"; "defaultAssessmentDTO": "defaultAssessmentDTO"; "predefinedAssessmentInstance": "predefinedAssessmentInstance"; "enableSkillsToQuestionMapping": "enableSkillsToQuestionMapping"; "assessmentContext": "assessmentContext"; "minimumRequiredSections": "minimumRequiredSections"; "checkForResponses": "checkForResponses"; "showProctoringToggle": "showProctoringToggle"; "showTimeInput": "showTimeInput"; "enableImportFromQuestionBank": "enableImportFromQuestionBank"; "questionBankConfig": "questionBankConfig"; }, { "assessmentIdChange": "assessmentIdChange"; "assessmentInstanceIdChange": "assessmentInstanceIdChange"; "snackbarMessage": "snackbarMessage"; }, never, never>;
70
108
  }
@@ -3,12 +3,13 @@ import * as i1 from "./assessment-maker.component";
3
3
  import * as i2 from "./components/add-edit-section-introduction/add-edit-section-introduction.component";
4
4
  import * as i3 from "./components/assessment-builder/assessment-builder.component";
5
5
  import * as i4 from "./components/question-details/question-details.component";
6
- import * as i5 from "@angular/common";
7
- import * as i6 from "../../shared/shared.module";
8
- import * as i7 from "../../shared/material-modules";
9
- import * as i8 from "@angular/forms";
6
+ import * as i5 from "./components/question-bank-picker/question-bank-picker.component";
7
+ import * as i6 from "@angular/common";
8
+ import * as i7 from "../../shared/shared.module";
9
+ import * as i8 from "../../shared/material-modules";
10
+ import * as i9 from "@angular/forms";
10
11
  export declare class AssessmentMakerModule {
11
12
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentMakerModule, never>;
12
- static ɵmod: i0.ɵɵNgModuleDeclaration<AssessmentMakerModule, [typeof i1.AssessmentMakerComponent, typeof i2.AddEditSectionIntroductionComponent, typeof i3.AssessmentBuilderComponent, typeof i4.QuestionDetailsComponent], [typeof i5.CommonModule, typeof i6.SharedModule, typeof i7.MaterialModules, typeof i8.FormsModule, typeof i8.ReactiveFormsModule], [typeof i1.AssessmentMakerComponent]>;
13
+ static ɵmod: i0.ɵɵNgModuleDeclaration<AssessmentMakerModule, [typeof i1.AssessmentMakerComponent, typeof i2.AddEditSectionIntroductionComponent, typeof i3.AssessmentBuilderComponent, typeof i4.QuestionDetailsComponent, typeof i5.QuestionBankPickerComponent], [typeof i6.CommonModule, typeof i7.SharedModule, typeof i8.MaterialModules, typeof i9.FormsModule, typeof i9.ReactiveFormsModule], [typeof i1.AssessmentMakerComponent, typeof i3.AssessmentBuilderComponent]>;
13
14
  static ɵinj: i0.ɵɵInjectorDeclaration<AssessmentMakerModule>;
14
15
  }
@@ -36,6 +36,8 @@ export declare class AssessmentBuilderComponent implements OnInit {
36
36
  questionBank: Record<number, AssessmentQuestion>;
37
37
  isChild: boolean;
38
38
  assessmentId: number;
39
+ standaloneMode: boolean;
40
+ isLocked: boolean;
39
41
  isSubmitting: boolean;
40
42
  skillsList: RefData[];
41
43
  constructor(formBuilder: FormBuilder, assessmentBuilderService: AssessmentBuilderService, assessmentMakerService: AssessmentMakerService, dialogRef: MatDialogRef<AssessmentBuilderComponent>, dialogData: any);
@@ -44,6 +46,7 @@ export declare class AssessmentBuilderComponent implements OnInit {
44
46
  setupFormGroup(): void;
45
47
  populateForm(questionDetails: AssessmentQuestion, buildChildGroups?: boolean): void;
46
48
  onSubmit(): Promise<void>;
49
+ private createStandaloneQuestion;
47
50
  createQuestion(payload: any): Promise<AssessmentQuestion>;
48
51
  updateQuestion(payload: any): Promise<AssessmentQuestion>;
49
52
  createOrEditAssessmentAndQuestionPaper(question: AssessmentQuestion): void;
@@ -68,6 +71,10 @@ export declare class AssessmentBuilderComponent implements OnInit {
68
71
  goBack(): void;
69
72
  private resetAndPopulate;
70
73
  private scrollToTop;
74
+ trackByCode(index: number, item: any): string;
75
+ trackByControl(index: number, control: any): any;
76
+ trackByGroupId(index: number, group: any): string;
77
+ trackByQuestionId(index: number, id: any): string;
71
78
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentBuilderComponent, never>;
72
79
  static ɵcmp: i0.ɵɵComponentDeclaration<AssessmentBuilderComponent, "lib-app-assessment-builder", never, {}, {}, never, never>;
73
80
  }
@@ -0,0 +1,81 @@
1
+ import { OnDestroy, OnInit } from '@angular/core';
2
+ import { MatDialogRef } from '@angular/material/dialog';
3
+ import { QuestionBankConfig, QuestionType } from '../../../../shared/interfaces/assessment.interface';
4
+ import { AssessmentQuestion } from '../../../../shared/interfaces/question.interface';
5
+ import { AssessmentMakerService } from '../../services/assessment-maker.service';
6
+ import * as i0 from "@angular/core";
7
+ export interface QuestionBankPickerDialogData {
8
+ questionBankConfig: QuestionBankConfig;
9
+ existingQuestionIds: Set<number>;
10
+ labelConfig: {
11
+ [key: string]: string;
12
+ };
13
+ imageConfig: {
14
+ [key: string]: string;
15
+ };
16
+ questionTypes: QuestionType[];
17
+ targetSectionName?: string;
18
+ }
19
+ export declare class QuestionBankPickerComponent implements OnInit, OnDestroy {
20
+ private assessmentMakerService;
21
+ dialogRef: MatDialogRef<QuestionBankPickerComponent>;
22
+ dialogData: QuestionBankPickerDialogData;
23
+ labelConfig: {
24
+ [key: string]: string;
25
+ };
26
+ imageConfig: {
27
+ [key: string]: string;
28
+ };
29
+ questionTypes: QuestionType[];
30
+ existingQuestionIds: Set<number>;
31
+ targetSectionName: string;
32
+ allQuestions: AssessmentQuestion[];
33
+ filteredQuestions: AssessmentQuestion[];
34
+ currentPage: number;
35
+ pageSize: number;
36
+ totalElements: number;
37
+ hasNext: boolean;
38
+ isLoading: boolean;
39
+ isInitialLoading: boolean;
40
+ searchTerm: string;
41
+ selectedTypeCode: string;
42
+ selectedQuestions: Map<number, AssessmentQuestion>;
43
+ expandedQuestionIds: Set<number>;
44
+ private questionBankConfig;
45
+ private searchSubject$;
46
+ private destroy$;
47
+ constructor(assessmentMakerService: AssessmentMakerService, dialogRef: MatDialogRef<QuestionBankPickerComponent>, dialogData: QuestionBankPickerDialogData);
48
+ ngOnInit(): void;
49
+ ngOnDestroy(): void;
50
+ loadPage(page: number, append?: boolean): void;
51
+ loadMore(): void;
52
+ onScroll(event: Event): void;
53
+ applyFilters(): void;
54
+ onSearchChange(term: string): void;
55
+ clearSearch(): void;
56
+ onTypeFilterChange(typeCode: string | undefined): void;
57
+ selectQuickTypeFilter(typeCode: string | undefined): void;
58
+ toggleSelection(question: AssessmentQuestion): void;
59
+ isSelected(question: AssessmentQuestion): boolean;
60
+ isAlreadyInAssessment(questionId: number | undefined): boolean;
61
+ get eligibleVisibleQuestions(): AssessmentQuestion[];
62
+ get isAllVisibleSelected(): boolean;
63
+ get isSomeVisibleSelected(): boolean;
64
+ toggleSelectAllVisible(): void;
65
+ clearAllSelection(): void;
66
+ hasOptions(question: AssessmentQuestion): boolean;
67
+ toggleExpandOptions(questionId: number | undefined, event: Event): void;
68
+ isOptionsExpanded(questionId: number | undefined): boolean;
69
+ get selectedCount(): number;
70
+ get totalSelectedMarks(): number;
71
+ getTypeCount(typeCode: string | undefined): number;
72
+ getCategoryClass(question: AssessmentQuestion): string;
73
+ importSelected(): void;
74
+ close(): void;
75
+ capitalizeFirst(text: string | undefined): string;
76
+ getQuestionTypeLabel(question: AssessmentQuestion): string;
77
+ imageErrorHandler(event: any, filePath: string): void;
78
+ trackByQuestionId(index: number, question: AssessmentQuestion): string;
79
+ static ɵfac: i0.ɵɵFactoryDeclaration<QuestionBankPickerComponent, never>;
80
+ static ɵcmp: i0.ɵɵComponentDeclaration<QuestionBankPickerComponent, "lib-question-bank-picker", never, {}, {}, never, never>;
81
+ }
@@ -13,6 +13,7 @@ export declare class QuestionDetailsComponent implements AfterViewInit {
13
13
  [key: string]: string;
14
14
  };
15
15
  allowDelete: boolean;
16
+ isLocked: boolean;
16
17
  editQuestion: EventEmitter<{
17
18
  questionId: any;
18
19
  isChildQuestion: boolean;
@@ -29,9 +30,13 @@ export declare class QuestionDetailsComponent implements AfterViewInit {
29
30
  ngAfterViewInit(): void;
30
31
  toggleText(): void;
31
32
  checkOverflow(): void;
33
+ onQuestionClick(event: Event, questionId: any, isChild?: boolean): void;
32
34
  capitalizeFirst(text: string | undefined): string;
33
35
  imageErrorHandler(event: any, filePath: string): void;
34
36
  childQuestionPresent(question: AssessmentQuestion): boolean | undefined;
37
+ trackByOptionId(index: number, option: any): string;
38
+ trackByChildId(index: number, id: any): string;
39
+ trackBySkillCode(index: number, skill: any): string;
35
40
  static ɵfac: i0.ɵɵFactoryDeclaration<QuestionDetailsComponent, never>;
36
- static ɵcmp: i0.ɵɵComponentDeclaration<QuestionDetailsComponent, "lib-question-details", never, { "sectionQuestion": "sectionQuestion"; "question": "question"; "questionBank": "questionBank"; "labelConfig": "labelConfig"; "imageConfig": "imageConfig"; "allowDelete": "allowDelete"; }, { "editQuestion": "editQuestion"; "duplicateQuestion": "duplicateQuestion"; "deleteParentQuestion": "deleteParentQuestion"; "deleteChildQuestion": "deleteChildQuestion"; }, never, never>;
41
+ static ɵcmp: i0.ɵɵComponentDeclaration<QuestionDetailsComponent, "lib-question-details", never, { "sectionQuestion": "sectionQuestion"; "question": "question"; "questionBank": "questionBank"; "labelConfig": "labelConfig"; "imageConfig": "imageConfig"; "allowDelete": "allowDelete"; "isLocked": "isLocked"; }, { "editQuestion": "editQuestion"; "duplicateQuestion": "duplicateQuestion"; "deleteParentQuestion": "deleteParentQuestion"; "deleteChildQuestion": "deleteChildQuestion"; }, never, never>;
37
42
  }
@@ -1,4 +1,4 @@
1
- import { Assessment, AssessmentInstance } from '../../../shared/interfaces/assessment.interface';
1
+ import { Assessment, AssessmentInstance, Config } from '../../../shared/interfaces/assessment.interface';
2
2
  import { QuestionPaperSection, SectionQuestion, AssessmentQuestionPaper } from '../../../shared/interfaces/question-paper.interface';
3
3
  import { AssessmentQuestion } from '../../../shared/interfaces/question.interface';
4
4
  import * as i0 from "@angular/core";
@@ -39,8 +39,15 @@ export declare class AssessmentBuilderService {
39
39
  createNewSection(sequence: number): QuestionPaperSection;
40
40
  generateSectionQuestion(question: AssessmentQuestion, sectionQuestion?: SectionQuestion): SectionQuestion;
41
41
  generateQuestionPaperDTO(questionPaper: AssessmentQuestionPaper, questionBank: Record<number, AssessmentQuestion>): AssessmentQuestionPaper;
42
- generateAssessmentDTO(assessmentId: number, questionPaper: AssessmentQuestionPaper): Assessment;
43
- generateAssessmentInstanceDTO(assessmentId: number, predefinedAssessmentInstance: AssessmentInstance): AssessmentInstance;
42
+ generateAssessmentDTO(assessmentId: number, questionPaper: AssessmentQuestionPaper, assessmentConfigs?: Config[]): Assessment;
43
+ generateAssessmentInstanceDTO(assessmentId: number, predefinedAssessmentInstance: AssessmentInstance, duration?: number): AssessmentInstance;
44
+ /**
45
+ * Patch fragment carrying the duration onto an already-created instance (by id), to bundle into
46
+ * the assessment/question-paper patch. Empty unless the time input is enabled and an instance exists.
47
+ */
48
+ buildInstancePatch(showTimeInput: boolean, assessmentInstanceId: number, durationSeconds: number): {
49
+ assessmentInstance?: AssessmentInstance;
50
+ };
44
51
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentBuilderService, never>;
45
52
  static ɵprov: i0.ɵɵInjectableDeclaration<AssessmentBuilderService>;
46
53
  }
@@ -1,4 +1,5 @@
1
1
  import { HttpClient, HttpParams } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
2
3
  import * as i0 from "@angular/core";
3
4
  export declare class AssessmentMakerService {
4
5
  private http;
@@ -6,19 +7,22 @@ export declare class AssessmentMakerService {
6
7
  constructor(http: HttpClient);
7
8
  private getHeaders;
8
9
  createParams(params: any): HttpParams;
9
- getConfigJSON(fileName: string): import("rxjs").Observable<Object>;
10
- createAssessmentAndQuestionPaper(payload: any): import("rxjs").Observable<Object>;
11
- patchAssessmentAndQuestionPaper(payload: any): import("rxjs").Observable<Object>;
12
- createQuestion(payload: any): import("rxjs").Observable<Object>;
13
- patchQuestion(payload: any): import("rxjs").Observable<Object>;
10
+ getConfigJSON(fileName: string): Observable<Object>;
11
+ getResponseCount(assessmentInstanceId: number): Observable<Object>;
12
+ createAssessmentAndQuestionPaper(payload: any): Observable<Object>;
13
+ patchAssessmentAndQuestionPaper(payload: any): Observable<Object>;
14
+ createQuestion(payload: any): Observable<Object>;
15
+ patchQuestion(payload: any): Observable<Object>;
14
16
  getQuestionsByIds(params: {
15
17
  questionIds: number[];
16
- }): import("rxjs").Observable<Object>;
17
- getAssessmentContext(params: any): import("rxjs").Observable<Object>;
18
- duplicateSection(questionPaperId: number, sectionId: number): import("rxjs").Observable<Object>;
19
- duplicateQuestion(sectionId: number, sectionQuestionId: number): import("rxjs").Observable<Object>;
20
- createAssessmentInstance(payload: any): import("rxjs").Observable<Object>;
21
- getRefDataByCode(code: string, params: any): import("rxjs").Observable<Object>;
18
+ }): Observable<Object>;
19
+ getAssessmentContext(params: any): Observable<Object>;
20
+ duplicateSection(questionPaperId: number, sectionId: number): Observable<Object>;
21
+ duplicateQuestion(sectionId: number, sectionQuestionId: number): Observable<Object>;
22
+ createAssessmentInstance(payload: any): Observable<Object>;
23
+ getRefDataByCode(code: string, params: any): Observable<Object>;
24
+ getQuestionBankQuestions(params: any): Observable<Object>;
25
+ checkQuestionsLocked(questionIds: (number | string)[], scope?: string): Observable<Record<string, boolean>>;
22
26
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentMakerService, never>;
23
27
  static ɵprov: i0.ɵɵInjectableDeclaration<AssessmentMakerService>;
24
28
  }
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
2
+ import { Observable } from 'rxjs';
2
3
  import { MatDialog } from '@angular/material/dialog';
3
4
  import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
4
5
  import { DomSanitizer } from '@angular/platform-browser';
@@ -7,6 +8,7 @@ import { ResponseBuilderService } from './services/response-builder.service';
7
8
  import { AssesseeDTO, AssessorDTO, Assessment, AssessmentInstanceAssesseDTO, AssessmentStep, AssessmentContextDTO, SectionScore, SkillScore } from '../../shared/interfaces/assessment.interface';
8
9
  import { AssessmentQuestion } from '../../shared/interfaces/question.interface';
9
10
  import { AssessmentQuestionPaper, QuestionPaperSection } from '../../shared/interfaces/question-paper.interface';
11
+ import { ProctoringService } from './services/proctoring.service';
10
12
  import * as i0 from "@angular/core";
11
13
  export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
12
14
  private assessmentTakerService;
@@ -15,6 +17,7 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
15
17
  private sanitizer;
16
18
  private dialog;
17
19
  private cdr;
20
+ private proctoringService;
18
21
  labelConfig: {
19
22
  [key: string]: string;
20
23
  };
@@ -39,13 +42,20 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
39
42
  };
40
43
  showOverallRemarks: boolean;
41
44
  showCorrectAnswers: boolean;
45
+ resumeTimerAcrossVisits: boolean;
46
+ warnOnLeaveDuringProctoring: boolean;
47
+ proctorLinkLoader?: () => Promise<any>;
42
48
  snackbarMessage: EventEmitter<{
43
49
  message: string;
44
50
  type: 'success' | 'error' | 'info';
45
51
  }>;
46
52
  submitAssessment: EventEmitter<any>;
47
53
  stepChanged: EventEmitter<AssessmentStep>;
54
+ consentToProceed: EventEmitter<boolean>;
48
55
  showLoader: boolean;
56
+ introActive: boolean;
57
+ private proctoringSessionStarted;
58
+ private proctoringSessionEnded;
49
59
  questionBank: Record<number, AssessmentQuestion>;
50
60
  assessmentQuestionPaperData: AssessmentQuestionPaper;
51
61
  assessmentData: Assessment;
@@ -53,6 +63,7 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
53
63
  timerInterval: any;
54
64
  remainingTime: number;
55
65
  displayTime: string;
66
+ timeExpired: boolean;
56
67
  isAutoSubmitting: boolean;
57
68
  isSubmitting: boolean;
58
69
  sectionFormGroups: {
@@ -62,6 +73,9 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
62
73
  overallNotesCtrl: FormControl;
63
74
  expandedState: boolean[];
64
75
  private youtubeUrlCache;
76
+ private newAssesseeSession;
77
+ private backGuardArmed;
78
+ private allowBackNavigation;
65
79
  private _selectedTabIndex;
66
80
  get selectedTabIndex(): number;
67
81
  set selectedTabIndex(value: number);
@@ -70,13 +84,72 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
70
84
  tooltipState: Record<number, boolean>;
71
85
  isMobile: boolean;
72
86
  onResize(): void;
73
- constructor(assessmentTakerService: AssessmentTakerService, fb: FormBuilder, responseBuilderService: ResponseBuilderService, sanitizer: DomSanitizer, dialog: MatDialog, cdr: ChangeDetectorRef);
87
+ /**
88
+ * While a proctoring session is running, warn the candidate before they refresh, close the tab, or
89
+ * navigate away. Browsers show their own generic "Leave site?" confirmation here — the message text
90
+ * cannot be customized for security reasons — so this only guarantees a prompt, not our wording.
91
+ */
92
+ onBeforeUnload(event: BeforeUnloadEvent): void;
93
+ /**
94
+ * In-app Back button (SPA popstate — not caught by beforeunload). While proctoring runs we keep a
95
+ * sentinel history entry; when Back pops it we show a custom warning and either re-arm (stay) or
96
+ * proceed with the navigation (leave).
97
+ */
98
+ onPopState(): void;
99
+ private isProctoringRunning;
100
+ /** Pushes a sentinel history entry so the next in-app Back press triggers our guard. */
101
+ private armBackGuard;
102
+ private confirmLeaveAssessment;
103
+ constructor(assessmentTakerService: AssessmentTakerService, fb: FormBuilder, responseBuilderService: ResponseBuilderService, sanitizer: DomSanitizer, dialog: MatDialog, cdr: ChangeDetectorRef, proctoringService: ProctoringService);
74
104
  ngOnInit(): void;
75
105
  ngOnDestroy(): void;
106
+ /**
107
+ * Ends the proctoring session after the assessment is submitted: stops + destroys the ProctorLink
108
+ * SDK and notifies the backend to end the session. Only ends a session that actually started, and
109
+ * is guarded so the backend is called at most once.
110
+ */
111
+ private endProctoringSession;
76
112
  getConfigsFromJSON(): void;
77
113
  loadAssessmentData(): void;
78
114
  handleResponse(): void;
79
115
  formSetup(): void;
116
+ private startAssessment;
117
+ get isProctoringEnabled(): boolean;
118
+ /**
119
+ * The full-screen intro gate is shown when proctoring is enabled, or when a timed assessment tracks
120
+ * elapsed time across visits (so the assessee is created up front to anchor the timer).
121
+ */
122
+ private requiresStartGate;
123
+ /** A reference image is captured only for proctoring, and only on the first attempt (no assessee id yet). */
124
+ get requireReferenceCapture(): boolean;
125
+ get totalSectionCount(): number;
126
+ get totalQuestionCount(): number;
127
+ get assessmentDurationSeconds(): number;
128
+ startSessionAction: (referenceImageBase64: string) => Observable<any>;
129
+ onIntroProceeded(): void;
130
+ /**
131
+ * Creates the assessee up front when the candidate proceeds from the intro gate.
132
+ * - First attempt (no assessee id): POST creates the assessee — for proctoring the response carries
133
+ * a nested `proctoring` session; otherwise it's a plain assessee DTO (with `createdAt`).
134
+ * - Existing attempt: proctoring refreshes the token (flat ProctoringSession); non-proctoring is a no-op
135
+ * (the assessee was already loaded, so `createdAt` is known).
136
+ * When proctoring is enabled it then starts the ProctorLink SDK and waits for camera permission.
137
+ */
138
+ private startAssessmentSession;
139
+ /**
140
+ * Re-mints the proctoring token via the refresh API and returns ONLY the new provider JWT
141
+ * (used by the SDK's token-expired flow). The rest of the refresh response is intentionally
142
+ * ignored — the live session must not be re-seeded from it mid-attempt.
143
+ */
144
+ private refreshProctoringJwt;
145
+ private buildInitAssesseePayload;
146
+ private beginAssessment;
147
+ /**
148
+ * Starts a timer anchored to the assessee's first-visit time. The assessee is already created by the
149
+ * intro gate (so `createdAt` is known); remaining time is `duration - elapsedSinceCreatedAt`.
150
+ * If the time has already run out (candidate left and returned late), shows 00:00 and auto-submits.
151
+ */
152
+ private beginTrackedTimer;
80
153
  updateQuestionConditionalControls(fg: FormGroup, question: AssessmentQuestion): void;
81
154
  emitStepDetails(): void;
82
155
  addControlForQuestion(group: any, question: AssessmentQuestion, isMandatory?: boolean, isChild?: boolean, parentId?: number, parentOptionId?: number): void;
@@ -91,6 +164,7 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
91
164
  getMaxCharCount(question: AssessmentQuestion): number;
92
165
  getRemainingChars(question: AssessmentQuestion, control: any): number;
93
166
  goBack(): void;
167
+ get isCheckingLink(): boolean;
94
168
  shouldDisableTab(index: number): boolean;
95
169
  goNext(saveData?: boolean): void;
96
170
  processSubmit(saveData?: boolean): void;
@@ -102,11 +176,16 @@ export declare class AssessmentTakerComponent implements OnInit, OnDestroy {
102
176
  openInstructionsDialog(section: QuestionPaperSection): void;
103
177
  checkMaxVal(event: any, control: any, maxVal: number | undefined): void;
104
178
  preventNegativeInput(event: KeyboardEvent): void;
179
+ openProctoringResult(): void;
105
180
  openSkillAllocationDialog(skillList?: SkillScore[]): void;
106
181
  startTimer(durationInSeconds: number): void;
107
182
  updateDisplayTime(): void;
108
183
  autoSubmit(): void;
109
184
  disableForm(): void;
185
+ trackBySectionId(index: number, section: any): string;
186
+ trackBySectionQuestion(index: number, sq: any): string;
187
+ trackByOptionId(index: number, option: any): string;
188
+ trackByChildId(index: number, id: any): string;
110
189
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentTakerComponent, never>;
111
- static ɵcmp: i0.ɵɵComponentDeclaration<AssessmentTakerComponent, "lib-assessment-taker", never, { "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"; }, { "snackbarMessage": "snackbarMessage"; "submitAssessment": "submitAssessment"; "stepChanged": "stepChanged"; }, never, never>;
190
+ static ɵcmp: i0.ɵɵComponentDeclaration<AssessmentTakerComponent, "lib-assessment-taker", never, { "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"; }, { "snackbarMessage": "snackbarMessage"; "submitAssessment": "submitAssessment"; "stepChanged": "stepChanged"; "consentToProceed": "consentToProceed"; }, never, never>;
112
191
  }
@@ -9,12 +9,14 @@ import * as i7 from "./components/question-type-preference/question-type-prefere
9
9
  import * as i8 from "./components/question-type-short/question-type-short.component";
10
10
  import * as i9 from "./components/section-instructions/section-instructions.component";
11
11
  import * as i10 from "./components/question-type-date-picker/question-type-date-picker.component";
12
- import * as i11 from "@angular/common";
13
- import * as i12 from "../../shared/shared.module";
14
- import * as i13 from "../../shared/material-modules";
15
- import * as i14 from "@angular/forms";
12
+ import * as i11 from "./components/proctoring-result/proctoring-result.component";
13
+ import * as i12 from "./components/proctoring-consent/proctoring-consent.component";
14
+ import * as i13 from "@angular/common";
15
+ import * as i14 from "../../shared/shared.module";
16
+ import * as i15 from "../../shared/material-modules";
17
+ import * as i16 from "@angular/forms";
16
18
  export declare class AssessmentTakerModule {
17
19
  static ɵfac: i0.ɵɵFactoryDeclaration<AssessmentTakerModule, never>;
18
- static ɵmod: i0.ɵɵNgModuleDeclaration<AssessmentTakerModule, [typeof i1.AssessmentTakerComponent, typeof i2.QuestionTypeEditorComponent, typeof i3.QuestionTypeFileUploadComponent, typeof i4.QuestionTypeLongComponent, typeof i5.QuestionTypeMultiselectComponent, typeof i6.QuestionTypeObjectiveComponent, typeof i7.QuestionTypePreferenceComponent, typeof i8.QuestionTypeShortComponent, typeof i9.SectionInstructionsComponent, typeof i10.QuestionTypeDatePickerComponent], [typeof i11.CommonModule, typeof i12.SharedModule, typeof i13.MaterialModules, typeof i14.FormsModule, typeof i14.ReactiveFormsModule], [typeof i1.AssessmentTakerComponent]>;
20
+ static ɵmod: i0.ɵɵNgModuleDeclaration<AssessmentTakerModule, [typeof i1.AssessmentTakerComponent, typeof i2.QuestionTypeEditorComponent, typeof i3.QuestionTypeFileUploadComponent, typeof i4.QuestionTypeLongComponent, typeof i5.QuestionTypeMultiselectComponent, typeof i6.QuestionTypeObjectiveComponent, typeof i7.QuestionTypePreferenceComponent, typeof i8.QuestionTypeShortComponent, typeof i9.SectionInstructionsComponent, typeof i10.QuestionTypeDatePickerComponent, typeof i11.ProctoringResultComponent, typeof i12.ProctoringConsentComponent], [typeof i13.CommonModule, typeof i14.SharedModule, typeof i15.MaterialModules, typeof i16.FormsModule, typeof i16.ReactiveFormsModule], [typeof i1.AssessmentTakerComponent]>;
19
21
  static ɵinj: i0.ɵɵInjectorDeclaration<AssessmentTakerModule>;
20
22
  }
@@ -0,0 +1,39 @@
1
+ import { AfterViewInit, ElementRef, EventEmitter, OnDestroy } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ export declare class ProctoringConsentComponent implements AfterViewInit, OnDestroy {
5
+ videoRef: ElementRef<HTMLVideoElement>;
6
+ canvasRef: ElementRef<HTMLCanvasElement>;
7
+ labelConfig: {
8
+ [key: string]: string;
9
+ };
10
+ proctoringEnabled: boolean;
11
+ requireCapture: boolean;
12
+ sectionCount: number;
13
+ questionCount: number;
14
+ durationSeconds: number;
15
+ confirmAction?: (referenceImageBase64: string) => Observable<any>;
16
+ proceeded: EventEmitter<void>;
17
+ cameraReady: boolean;
18
+ cameraError: string;
19
+ captured: boolean;
20
+ capturedUrl: string;
21
+ starting: boolean;
22
+ startError: string;
23
+ private stream?;
24
+ private capturedBase64;
25
+ /** Proceed is allowed once a photo is captured, or immediately when no capture is required. */
26
+ get canProceed(): boolean;
27
+ get durationMinutes(): number;
28
+ ngAfterViewInit(): void;
29
+ ngOnDestroy(): void;
30
+ startCamera(): void;
31
+ /** Grabs a still frame from the live preview into a JPEG (used as the reference image). */
32
+ capture(): void;
33
+ retake(): void;
34
+ /** Enabled only once a photo is captured (when required); runs the session-start action. */
35
+ proceed(): void;
36
+ private stopCamera;
37
+ static ɵfac: i0.ɵɵFactoryDeclaration<ProctoringConsentComponent, never>;
38
+ static ɵcmp: i0.ɵɵComponentDeclaration<ProctoringConsentComponent, "lib-proctoring-consent", never, { "labelConfig": "labelConfig"; "proctoringEnabled": "proctoringEnabled"; "requireCapture": "requireCapture"; "sectionCount": "sectionCount"; "questionCount": "questionCount"; "durationSeconds": "durationSeconds"; "confirmAction": "confirmAction"; }, { "proceeded": "proceeded"; }, never, never>;
39
+ }
@@ -0,0 +1,82 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { MatDialogRef } from '@angular/material/dialog';
3
+ import { AssessmentTakerService } from '../../services/assessment-taker.service';
4
+ import { ProctoringPayload, ProctoringReport, ProctoringSessionSummary } from '../../../../shared/interfaces/proctoring.interface';
5
+ import * as i0 from "@angular/core";
6
+ declare type ReportState = 'loading' | 'loaded' | 'empty' | 'error';
7
+ export declare class ProctoringResultComponent implements OnInit {
8
+ dialogRef: MatDialogRef<ProctoringResultComponent>;
9
+ private assessmentTakerService;
10
+ data: {
11
+ labelConfig?: {
12
+ [key: string]: string;
13
+ };
14
+ imageConfig?: {
15
+ [key: string]: string;
16
+ };
17
+ assesseeId?: number;
18
+ assesseeName?: string;
19
+ };
20
+ labelConfig: {
21
+ [key: string]: string;
22
+ };
23
+ imageConfig: {
24
+ [key: string]: string;
25
+ };
26
+ assesseeId: number;
27
+ assesseeName: string;
28
+ sessions: ProctoringSessionSummary[];
29
+ loading: boolean;
30
+ errored: boolean;
31
+ totalElements: number;
32
+ last: boolean;
33
+ private page;
34
+ private readonly size;
35
+ reportBySession: {
36
+ [sessionId: number]: ProctoringReport;
37
+ };
38
+ reportState: {
39
+ [sessionId: number]: ReportState;
40
+ };
41
+ private parsedCache;
42
+ constructor(dialogRef: MatDialogRef<ProctoringResultComponent>, assessmentTakerService: AssessmentTakerService, data: {
43
+ labelConfig?: {
44
+ [key: string]: string;
45
+ };
46
+ imageConfig?: {
47
+ [key: string]: string;
48
+ };
49
+ assesseeId?: number;
50
+ assesseeName?: string;
51
+ });
52
+ ngOnInit(): void;
53
+ loadSessions(): void;
54
+ loadMore(): void;
55
+ /** Fetches the report for a session the first time its panel is expanded. */
56
+ loadReport(session: ProctoringSessionSummary): void;
57
+ trackBySessionId(_index: number, session: ProctoringSessionSummary): number;
58
+ trackByIndex(index: number): number;
59
+ /** Parses (and caches) the reportPayload JSON. Returns null if absent or not valid JSON. */
60
+ getParsedPayload(report: ProctoringReport): ProctoringPayload | null;
61
+ /** Formats a duration in seconds as `Mm Ss` (or `Ss` under a minute). */
62
+ formatDuration(seconds?: number): string;
63
+ /** Session timestamps are epoch milliseconds already; guard 0/undefined so nothing renders. */
64
+ toMillis(epochMillis?: number): number | null;
65
+ /**
66
+ * Theme badge classes for a session status.
67
+ * ACTIVE = running, VALIDATING = report in progress, VALIDATED = report ready,
68
+ * ENDED = stopped/invalidated, FAILED = errored.
69
+ */
70
+ statusBadgeClass(status?: string): string;
71
+ /** Maps a raw event code (e.g. `tab.hidden`) to a friendly label, falling back to the raw code. */
72
+ eventTypeLabel(type?: string): string;
73
+ /** Maps a raw reason code (e.g. `browser_activity`) to a friendly label, falling back to the raw code. */
74
+ reasonCodeLabel(code?: string): string;
75
+ /** Highlights integrity-relevant timeline events (tab switches, face issues, session markers). */
76
+ isNoteworthy(type?: string): boolean;
77
+ close(): void;
78
+ imageErrorHandler(event: any, filePath: string): void;
79
+ static ɵfac: i0.ɵɵFactoryDeclaration<ProctoringResultComponent, never>;
80
+ static ɵcmp: i0.ɵɵComponentDeclaration<ProctoringResultComponent, "lib-proctoring-result", never, {}, {}, never, never>;
81
+ }
82
+ export {};
@@ -38,6 +38,7 @@ export declare class QuestionTypeFileUploadComponent implements ControlValueAcce
38
38
  imageErrorHandler(event: any, filePath: string): void;
39
39
  getFileIcon(attachment: Attachment): string;
40
40
  viewFile(url: string): void;
41
+ trackByFile(index: number, file: Attachment): string;
41
42
  static ɵfac: i0.ɵɵFactoryDeclaration<QuestionTypeFileUploadComponent, [{ optional: true; self: true; }, null]>;
42
43
  static ɵcmp: i0.ɵɵComponentDeclaration<QuestionTypeFileUploadComponent, "lib-question-type-file-upload", never, { "required": "required"; "assessmentInstanceId": "assessmentInstanceId"; "question": "question"; "labelConfig": "labelConfig"; "imageConfig": "imageConfig"; }, { "snackbarMessage": "snackbarMessage"; }, never, never>;
43
44
  }
@@ -29,6 +29,7 @@ export declare class QuestionTypeMultiselectComponent implements ControlValueAcc
29
29
  isEvaluationEnabled(): boolean;
30
30
  getSelectionStatus(option: any): string | null;
31
31
  imageErrorHandler(event: any, filePath: string): void;
32
+ trackByOptionId(index: number, option: any): string;
32
33
  static ɵfac: i0.ɵɵFactoryDeclaration<QuestionTypeMultiselectComponent, [{ optional: true; self: true; }]>;
33
34
  static ɵcmp: i0.ɵɵComponentDeclaration<QuestionTypeMultiselectComponent, "lib-question-type-multiselect", never, { "required": "required"; "question": "question"; "showCorrectAnswers": "showCorrectAnswers"; "imageConfig": "imageConfig"; "answerObj": "answerObj"; }, { "viewChild": "viewChild"; }, never, never>;
34
35
  }