commons-assessment 12.0.37 → 12.0.39-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.
- package/bundles/commons-assessment.umd.js +12 -7
- package/bundles/commons-assessment.umd.js.map +1 -1
- package/esm2015/lib/modules/assessment-maker/assessment-maker.component.js +3 -2
- package/esm2015/lib/modules/assessment-taker/assessment-taker.component.js +6 -4
- package/esm2015/lib/modules/assessment-taker/components/proctoring-consent/proctoring-consent.component.js +3 -2
- package/esm2015/lib/modules/assessment-taker/components/proctoring-result/proctoring-result.component.js +2 -2
- package/esm2015/lib/modules/assessment-taker/services/proctoring.service.js +3 -2
- package/fesm2015/commons-assessment.js +12 -7
- package/fesm2015/commons-assessment.js.map +1 -1
- package/lib/modules/assessment-taker/assessment-taker.component.d.ts +1 -0
- package/package.json +1 -1
|
@@ -415,7 +415,7 @@ class ProctoringResultComponent {
|
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
417
|
ProctoringResultComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: ProctoringResultComponent, deps: [{ token: i1.MatDialogRef }, { token: AssessmentTakerService }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
418
|
-
ProctoringResultComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: ProctoringResultComponent, selector: "lib-proctoring-result", ngImport: i0, template: "<div class=\"d-flex flex-column h-100 overflow-hidden assessment-bg-white\">\r\n\r\n <!-- Header -->\r\n <div class=\"d-flex align-items-start justify-content-between gap-3 p-3 px-md-4 border-bottom\">\r\n <div class=\"flex-grow-1\">\r\n <p class=\"assessment-text-semibold-16 assessment-text-grey-ten mb-1\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.RESULT_TITLE'] }}\r\n </p>\r\n <p class=\"assessment-text-regular-12 assessment-text-grey-seven mb-0\">\r\n <span *ngIf=\"assesseeName\">{{ assesseeName }} \u00B7 </span>{{ totalElements }} {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_COUNT'] }}\r\n </p>\r\n </div>\r\n <button type=\"button\" class=\"btn-close\" (click)=\"close()\" aria-label=\"Close\"></button>\r\n </div>\r\n\r\n <!-- Body -->\r\n <div class=\"flex-grow-1 overflow-auto p-3 px-md-4\">\r\n\r\n <!-- Loading (initial) -->\r\n <div *ngIf=\"loading && !sessions.length\" class=\"d-flex align-items-center justify-content-center gap-2 py-5 assessment-text-regular-13 assessment-text-grey-seven\">\r\n <span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_LOADING'] }}\r\n </div>\r\n\r\n <!-- Error -->\r\n <div *ngIf=\"errored && !sessions.length\" class=\"text-center py-5\">\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-3\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_ERROR'] }}</p>\r\n <button type=\"button\" (click)=\"loadSessions()\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORTS_RETRY'] }}\r\n </button>\r\n </div>\r\n\r\n <!-- Empty -->\r\n <div *ngIf=\"!loading && !errored && !sessions.length\" class=\"text-center py-5 assessment-text-regular-13 assessment-text-grey-seven\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_EMPTY'] }}\r\n </div>\r\n\r\n <!-- Sessions accordion -->\r\n <mat-accordion class=\"d-block\" *ngIf=\"sessions.length\">\r\n <mat-expansion-panel *ngFor=\"let session of sessions; trackBy: trackBySessionId\"\r\n class=\"shadow-none assessment-border-radius-two assessment-panel border mb-2\" (opened)=\"loadReport(session)\">\r\n\r\n <mat-expansion-panel-header class=\"proctoring-panel-header p-3\">\r\n <mat-panel-title class=\"d-flex flex-column my-1 align-items-start\">\r\n <span class=\"assessment-text-semibold-13 assessment-text-grey-ten\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_SESSION'] }} {{ session.id }}\r\n </span>\r\n <span class=\"d-flex align-items-center gap-2 mt-1\">\r\n <span *ngIf=\"session.status\" class=\"badge rounded-pill text-capitalize assessment-text-medium-10\" [ngClass]=\"statusBadgeClass(session.status)\">\r\n {{ session.status }}\r\n </span>\r\n <span *ngIf=\"session.integrityFlagged || reportBySession[session.id!]?.integrityFlagged\"\r\n class=\"badge rounded-pill assessment-bg-danger assessment-text-white assessment-text-medium-10\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FLAGGED'] }}\r\n </span>\r\n </span>\r\n </mat-panel-title>\r\n <mat-panel-description class=\"justify-content-end align-items-center me-3\">\r\n <span *ngIf=\"toMillis(session.startedAt) as started\" class=\"assessment-text-regular-11 assessment-text-grey-seven\">\r\n {{ started | date:'dd MMM, HH:mm' }}\r\n </span>\r\n </mat-panel-description>\r\n </mat-expansion-panel-header>\r\n\r\n <!-- Report is fetched when the panel opens -->\r\n <ng-template matExpansionPanelContent>\r\n <div class=\"p-3 pt-1\" [ngSwitch]=\"reportState[session.id!]\">\r\n\r\n <!-- Loading -->\r\n <div *ngSwitchCase=\"'loading'\" class=\"d-flex align-items-center gap-2 py-3 assessment-text-regular-13 assessment-text-grey-seven\">\r\n <span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_LOADING'] }}\r\n </div>\r\n\r\n <!-- Error -->\r\n <div *ngSwitchCase=\"'error'\" class=\"py-3\">\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ERROR'] }}</p>\r\n <button type=\"button\" (click)=\"loadReport(session)\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORTS_RETRY'] }}\r\n </button>\r\n </div>\r\n\r\n <!-- No report yet -->\r\n <div *ngSwitchCase=\"'empty'\" class=\"py-3 assessment-text-regular-13 assessment-text-grey-seven\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_EMPTY'] }}\r\n </div>\r\n\r\n <!-- Loaded report -->\r\n <ng-container *ngSwitchCase=\"'loaded'\">\r\n <ng-container *ngIf=\"reportBySession[session.id!] as report\">\r\n\r\n <!-- Flagged chip \u2014 highlights suspicious activity -->\r\n <div *ngIf=\"report.integrityFlagged\" class=\"mb-3\">\r\n <span class=\"badge rounded-pill assessment-bg-danger assessment-text-white assessment-text-medium-12 px-3 py-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FLAGGED'] }}\r\n </span>\r\n </div>\r\n\r\n <!-- Integrity summary (report top-level) -->\r\n <div class=\"row g-2\">\r\n <div class=\"col-6\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_INTEGRITY_SCORE'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-grey-ten mb-0\" [class.assessment-text-danger]=\"report.integrityFlagged\">\r\n {{ report.integrityScore }}<span *ngIf=\"report.integrityLevel\"> ({{ report.integrityLevel }})</span>\r\n </p>\r\n </div>\r\n <div class=\"col-6\" *ngIf=\"report.identityMatch\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_IDENTITY_MATCH'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-grey-ten mb-0\">{{ report.identityMatch }}</p>\r\n </div>\r\n <div class=\"col-12\" *ngIf=\"report.failureReason\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FAILURE_REASON'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-0\">{{ report.failureReason }}</p>\r\n </div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"getParsedPayload(report) as p; else rawPayload\">\r\n\r\n <!-- Summary meta -->\r\n <div class=\"d-flex flex-wrap align-items-center gap-2 mt-3 assessment-text-regular-12 assessment-text-grey-seven\">\r\n <span *ngIf=\"p.duration_seconds != null\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_DURATION'] }}: {{ formatDuration(p.duration_seconds) }}</span>\r\n <span *ngIf=\"p.started_at\">\u00B7 {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_STARTED'] }}: {{ p.started_at | date:'dd MMM, HH:mm:ss' }}</span>\r\n <span *ngIf=\"p.ended_at\">\u00B7 {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ENDED'] }}: {{ p.ended_at | date:'HH:mm:ss' }}</span>\r\n </div>\r\n\r\n <!-- Reasons -->\r\n <div *ngIf=\"p.integrity?.reasons?.length\" class=\"d-flex flex-column gap-2 mt-2\">\r\n <div *ngFor=\"let r of p.integrity?.reasons; trackBy: trackByIndex\" class=\"border rounded p-2\">\r\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\r\n <span class=\"assessment-text-semibold-12 assessment-text-grey-ten\">{{ reasonCodeLabel(r.code) }}</span>\r\n <span *ngIf=\"r.weight != null\" class=\"badge rounded-pill assessment-text-white\" [ngClass]=\"(r.weight || 0) < 0 ? 'assessment-bg-danger' : 'assessment-bg-success'\">{{ (r.weight || 0) > 0 ? '+' : '' }}{{ r.weight }}</span>\r\n </div>\r\n <p class=\"assessment-text-regular-12 assessment-text-grey-seven mb-0 mt-1\">{{ r.detail }}</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Stat tiles: face analysis -->\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ANALYSIS'] }}</p>\r\n <div class=\"row row-cols-2 row-cols-md-4 g-2 text-center\">\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\">{{ p.face_analysis?.frames_checked ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FRAMES'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.no_face_frames || 0) > 0\">{{ p.face_analysis?.no_face_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_NO_FACE'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.multi_face_frames || 0) > 0\">{{ p.face_analysis?.multi_face_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_MULTI_FACE'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.impersonation_frames || 0) > 0\">{{ p.face_analysis?.impersonation_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_IMPERSONATION'] }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity breakdown -->\r\n <div *ngIf=\"p.activity?.by_type\" class=\"d-flex flex-wrap gap-2 mt-3\">\r\n <span *ngFor=\"let item of (p.activity?.by_type | keyvalue); trackBy: trackByIndex\"\r\n class=\"badge rounded-pill assessment-bg-palette-EDF3FD assessment-text-grey-ten assessment-text-medium-12\">\r\n {{ eventTypeLabel(item.key) }} <span class=\"assessment-text-semibold-12\">{{ item.value }}</span>\r\n </span>\r\n </div>\r\n\r\n <!-- Evidence images -->\r\n <ng-container *ngIf=\"p.evidence?.length\">\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_EVIDENCE'] }}</p>\r\n <div class=\"d-flex flex-wrap gap-3\">\r\n <a *ngFor=\"let ev of p.evidence; trackBy: trackByIndex\" class=\"text-center text-decoration-none\"\r\n [href]=\"ev.image_url\" target=\"_blank\" rel=\"noopener\">\r\n <img class=\"proctoring-evi-img rounded border\" [src]=\"ev.image_url\" [attr.alt]=\"'frame ' + ev.seq\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/user.svg')\" />\r\n <span class=\"d-block assessment-text-regular-11 assessment-text-grey-seven mt-1\">\r\n <span *ngIf=\"ev.is_reference\" class=\"badge rounded-pill assessment-bg-primary-one assessment-text-white me-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_REFERENCE'] }}</span>\r\n #{{ ev.seq }} \u00B7 {{ ev.captured_at | date:'HH:mm:ss' }}\r\n </span>\r\n </a>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Timeline -->\r\n <ng-container *ngIf=\"p.timeline?.length\">\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_TIMELINE'] }} ({{ p.timeline?.length }})\r\n </p>\r\n <div class=\"proctoring-log assessment-bg-grey-ten assessment-text-grey-one font-monospace small rounded p-3 overflow-auto\">\r\n <div *ngFor=\"let ev of p.timeline; trackBy: trackByIndex\" class=\"text-nowrap\" [class.fw-semibold]=\"isNoteworthy(ev.type)\">\r\n <span class=\"assessment-text-grey-five me-2\">#{{ ev.seq }}</span>\r\n <span [class.assessment-text-palette-ADC9F6]=\"isNoteworthy(ev.type)\">{{ eventTypeLabel(ev.type) }}</span>\r\n <span class=\"assessment-text-grey-five ms-2\">{{ ev.at | date:'HH:mm:ss' }} ({{ ev.source }})</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </ng-container>\r\n\r\n <!-- Fallback: raw payload if it isn't parseable JSON -->\r\n <ng-template #rawPayload>\r\n <pre *ngIf=\"report.reportPayload\" class=\"proctoring-payload assessment-bg-grey-ten assessment-text-grey-one small rounded p-3 overflow-auto mb-0 mt-3\">{{ report.reportPayload }}</pre>\r\n </ng-template>\r\n\r\n </ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n </ng-template>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n\r\n <!-- Load more -->\r\n <div *ngIf=\"sessions.length && !last\" class=\"text-center mt-3\">\r\n <button type=\"button\" (click)=\"loadMore()\" [disabled]=\"loading\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2 d-inline-flex align-items-center gap-2\">\r\n <span *ngIf=\"loading\" class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.LOAD_MORE'] }}\r\n </button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n", 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-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}.badge{font-weight:500}.proctoring-panel-header{height:auto!important}.proctoring-log{max-height:16rem}.proctoring-payload{max-height:18rem;white-space:pre-wrap;word-break:break-word}.proctoring-evi-img{width:5rem;height:5rem;object-fit:cover}\n"], components: [{ type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }], directives: [{ type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.MatAccordion, selector: "mat-accordion", inputs: ["multi", "displayMode", "togglePosition", "hideToggle"], exportAs: ["matAccordion"] }, { type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i3.MatExpansionPanelDescription, selector: "mat-panel-description" }, { type: i3.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { type: i2$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }], pipes: { "date": i2$1.DatePipe, "keyvalue": i2$1.KeyValuePipe } });
|
|
418
|
+
ProctoringResultComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: ProctoringResultComponent, selector: "lib-proctoring-result", ngImport: i0, template: "<div class=\"d-flex flex-column h-100 overflow-hidden assessment-bg-white\">\r\n\r\n <!-- Header -->\r\n <div class=\"d-flex align-items-start justify-content-between gap-3 p-3 px-md-4 border-bottom\">\r\n <div class=\"flex-grow-1\">\r\n <p class=\"assessment-text-semibold-16 assessment-text-grey-ten mb-1\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.RESULT_TITLE'] }}\r\n </p>\r\n <p class=\"assessment-text-regular-12 assessment-text-grey-seven mb-0\">\r\n <span *ngIf=\"assesseeName\">{{ assesseeName }} \u00B7 </span>{{ totalElements }} {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_COUNT'] }}\r\n </p>\r\n </div>\r\n <button type=\"button\" class=\"btn-close\" (click)=\"close()\" aria-label=\"Close\"></button>\r\n </div>\r\n\r\n <!-- Body -->\r\n <div class=\"flex-grow-1 overflow-auto p-3 px-md-4\">\r\n\r\n <!-- Loading (initial) -->\r\n <div *ngIf=\"loading && !sessions.length\" class=\"d-flex align-items-center justify-content-center gap-2 py-5 assessment-text-regular-13 assessment-text-grey-seven\">\r\n <span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_LOADING'] }}\r\n </div>\r\n\r\n <!-- Error -->\r\n <div *ngIf=\"errored && !sessions.length\" class=\"text-center py-5\">\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-3\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_ERROR'] }}</p>\r\n <button type=\"button\" (click)=\"loadSessions()\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORTS_RETRY'] }}\r\n </button>\r\n </div>\r\n\r\n <!-- Empty -->\r\n <div *ngIf=\"!loading && !errored && !sessions.length\" class=\"text-center py-5 assessment-text-regular-13 assessment-text-grey-seven\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.SESSIONS_EMPTY'] }}\r\n </div>\r\n\r\n <!-- Sessions accordion -->\r\n <mat-accordion class=\"d-block\" *ngIf=\"sessions.length\">\r\n <mat-expansion-panel *ngFor=\"let session of sessions; trackBy: trackBySessionId\"\r\n class=\"shadow-none assessment-border-radius-two assessment-panel border mb-2\" (opened)=\"loadReport(session)\">\r\n\r\n <mat-expansion-panel-header class=\"proctoring-panel-header p-3\">\r\n <mat-panel-title class=\"d-flex flex-column my-1 align-items-start\">\r\n <span class=\"assessment-text-semibold-13 assessment-text-grey-ten\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_SESSION'] }} {{ session.id }}\r\n </span>\r\n <span class=\"d-flex align-items-center gap-2 mt-1\">\r\n <span *ngIf=\"session.status\" class=\"badge rounded-pill text-capitalize assessment-text-medium-10\" [ngClass]=\"statusBadgeClass(session.status)\">\r\n {{ session.status }}\r\n </span>\r\n <span *ngIf=\"session.integrityFlagged || reportBySession[session.id!]?.integrityFlagged\"\r\n class=\"badge rounded-pill assessment-bg-danger assessment-text-white assessment-text-medium-10\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FLAGGED'] }}\r\n </span>\r\n </span>\r\n </mat-panel-title>\r\n <mat-panel-description class=\"justify-content-end align-items-center me-3\">\r\n <span *ngIf=\"toMillis(session.startedAt) as started\" class=\"assessment-text-regular-11 assessment-text-grey-seven\">\r\n {{ started | date:'dd MMM, HH:mm' }}\r\n </span>\r\n </mat-panel-description>\r\n </mat-expansion-panel-header>\r\n\r\n <!-- Report is fetched when the panel opens -->\r\n <ng-template matExpansionPanelContent>\r\n <div class=\"p-3 pt-1\" [ngSwitch]=\"reportState[session.id!]\">\r\n\r\n <!-- Loading -->\r\n <div *ngSwitchCase=\"'loading'\" class=\"d-flex align-items-center gap-2 py-3 assessment-text-regular-13 assessment-text-grey-seven\">\r\n <span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_LOADING'] }}\r\n </div>\r\n\r\n <!-- Error -->\r\n <div *ngSwitchCase=\"'error'\" class=\"py-3\">\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ERROR'] }}</p>\r\n <button type=\"button\" (click)=\"loadReport(session)\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORTS_RETRY'] }}\r\n </button>\r\n </div>\r\n\r\n <!-- No report yet -->\r\n <div *ngSwitchCase=\"'empty'\" class=\"py-3 assessment-text-regular-13 assessment-text-grey-seven\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_EMPTY'] }}\r\n </div>\r\n\r\n <!-- Loaded report -->\r\n <ng-container *ngSwitchCase=\"'loaded'\">\r\n <ng-container *ngIf=\"reportBySession[session.id!] as report\">\r\n\r\n <!-- Integrity summary (report top-level) -->\r\n <div class=\"row g-2\">\r\n <div class=\"col-6\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_INTEGRITY_SCORE'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-grey-ten mb-0\" [class.assessment-text-danger]=\"report.integrityFlagged\">\r\n {{ report.integrityScore }}<span *ngIf=\"report.integrityLevel\"> ({{ report.integrityLevel }})</span>\r\n </p>\r\n </div>\r\n <div class=\"col-6\" *ngIf=\"report.identityMatch\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_IDENTITY_MATCH'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-grey-ten mb-0\">{{ report.identityMatch }}</p>\r\n </div>\r\n <div class=\"col-12\" *ngIf=\"report.failureReason\">\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven text-uppercase mb-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FAILURE_REASON'] }}</p>\r\n <p class=\"assessment-text-regular-13 assessment-text-danger mb-0\">{{ report.failureReason }}</p>\r\n </div>\r\n </div>\r\n\r\n <ng-container *ngIf=\"getParsedPayload(report) as p; else rawPayload\">\r\n\r\n <!-- Summary meta -->\r\n <div class=\"d-flex flex-wrap align-items-center gap-2 mt-3 assessment-text-regular-12 assessment-text-grey-seven\">\r\n <span *ngIf=\"p.duration_seconds != null\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_DURATION'] }}: {{ formatDuration(p.duration_seconds) }}</span>\r\n <span *ngIf=\"p.started_at\">\u00B7 {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_STARTED'] }}: {{ p.started_at | date:'dd MMM, HH:mm:ss' }}</span>\r\n <span *ngIf=\"p.ended_at\">\u00B7 {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ENDED'] }}: {{ p.ended_at | date:'HH:mm:ss' }}</span>\r\n </div>\r\n\r\n <!-- Reasons -->\r\n <div *ngIf=\"p.integrity?.reasons?.length\" class=\"d-flex flex-column gap-2 mt-2\">\r\n <div *ngFor=\"let r of p.integrity?.reasons; trackBy: trackByIndex\" class=\"border rounded p-2\">\r\n <div class=\"d-flex align-items-center justify-content-between gap-2\">\r\n <span class=\"assessment-text-semibold-12 assessment-text-grey-ten\">{{ reasonCodeLabel(r.code) }}</span>\r\n <span *ngIf=\"r.weight != null\" class=\"badge rounded-pill assessment-text-white\" [ngClass]=\"(r.weight || 0) < 0 ? 'assessment-bg-danger' : 'assessment-bg-success'\">{{ (r.weight || 0) > 0 ? '+' : '' }}{{ r.weight }}</span>\r\n </div>\r\n <p class=\"assessment-text-regular-12 assessment-text-grey-seven mb-0 mt-1\">{{ r.detail }}</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Stat tiles: face analysis -->\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_ANALYSIS'] }}</p>\r\n <div class=\"row row-cols-2 row-cols-md-4 g-2 text-center\">\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\">{{ p.face_analysis?.frames_checked ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_FRAMES'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.no_face_frames || 0) > 0\">{{ p.face_analysis?.no_face_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_NO_FACE'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.multi_face_frames || 0) > 0\">{{ p.face_analysis?.multi_face_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_MULTI_FACE'] }}</p>\r\n </div>\r\n </div>\r\n <div class=\"col\">\r\n <div class=\"border rounded p-2 h-100\">\r\n <p class=\"assessment-text-semibold-18 mb-1\" [class.assessment-text-danger]=\"(p.face_analysis?.impersonation_frames || 0) > 0\">{{ p.face_analysis?.impersonation_frames ?? 0 }}</p>\r\n <p class=\"assessment-text-regular-11 assessment-text-grey-seven mb-0\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_IMPERSONATION'] }}</p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Activity breakdown -->\r\n <div *ngIf=\"p.activity?.by_type\" class=\"d-flex flex-wrap gap-2 mt-3\">\r\n <span *ngFor=\"let item of (p.activity?.by_type | keyvalue); trackBy: trackByIndex\"\r\n class=\"badge rounded-pill assessment-bg-palette-EDF3FD assessment-text-grey-ten assessment-text-medium-12\">\r\n {{ eventTypeLabel(item.key) }} <span class=\"assessment-text-semibold-12\">{{ item.value }}</span>\r\n </span>\r\n </div>\r\n\r\n <!-- Evidence images -->\r\n <ng-container *ngIf=\"p.evidence?.length\">\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_EVIDENCE'] }}</p>\r\n <div class=\"d-flex flex-wrap gap-3\">\r\n <a *ngFor=\"let ev of p.evidence; trackBy: trackByIndex\" class=\"text-center text-decoration-none\"\r\n [href]=\"ev.image_url\" target=\"_blank\" rel=\"noopener\">\r\n <img class=\"proctoring-evi-img rounded border\" [src]=\"ev.image_url\" [attr.alt]=\"'frame ' + ev.seq\"\r\n (error)=\"imageErrorHandler($event, 'assets/commons-assessment/images/user.svg')\" />\r\n <span class=\"d-block assessment-text-regular-11 assessment-text-grey-seven mt-1\">\r\n <span *ngIf=\"ev.is_reference\" class=\"badge rounded-pill assessment-bg-primary-one assessment-text-white me-1\">{{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_REFERENCE'] }}</span>\r\n #{{ ev.seq }} \u00B7 {{ ev.captured_at | date:'HH:mm:ss' }}\r\n </span>\r\n </a>\r\n </div>\r\n </ng-container>\r\n\r\n <!-- Timeline -->\r\n <ng-container *ngIf=\"p.timeline?.length\">\r\n <p class=\"assessment-text-semibold-13 assessment-text-grey-ten mt-3 mb-2\">\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.REPORT_TIMELINE'] }} ({{ p.timeline?.length }})\r\n </p>\r\n <div class=\"proctoring-log assessment-bg-grey-ten assessment-text-grey-one font-monospace small rounded p-3 overflow-auto\">\r\n <div *ngFor=\"let ev of p.timeline; trackBy: trackByIndex\" class=\"text-nowrap\" [class.fw-semibold]=\"isNoteworthy(ev.type)\">\r\n <span class=\"assessment-text-grey-five me-2\">#{{ ev.seq }}</span>\r\n <span [class.assessment-text-palette-ADC9F6]=\"isNoteworthy(ev.type)\">{{ eventTypeLabel(ev.type) }}</span>\r\n <span class=\"assessment-text-grey-five ms-2\">{{ ev.at | date:'HH:mm:ss' }} ({{ ev.source }})</span>\r\n </div>\r\n </div>\r\n </ng-container>\r\n\r\n </ng-container>\r\n\r\n <!-- Fallback: raw payload if it isn't parseable JSON -->\r\n <ng-template #rawPayload>\r\n <pre *ngIf=\"report.reportPayload\" class=\"proctoring-payload assessment-bg-grey-ten assessment-text-grey-one small rounded p-3 overflow-auto mb-0 mt-3\">{{ report.reportPayload }}</pre>\r\n </ng-template>\r\n\r\n </ng-container>\r\n </ng-container>\r\n\r\n </div>\r\n </ng-template>\r\n </mat-expansion-panel>\r\n </mat-accordion>\r\n\r\n <!-- Load more -->\r\n <div *ngIf=\"sessions.length && !last\" class=\"text-center mt-3\">\r\n <button type=\"button\" (click)=\"loadMore()\" [disabled]=\"loading\"\r\n class=\"assessment-btn-primary-transparent assessment-border-radius-two assessment-text-semibold-13 px-3 py-2 d-inline-flex align-items-center gap-2\">\r\n <span *ngIf=\"loading\" class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>\r\n {{ labelConfig['COMMONS_ASSESSMENT.PROCTORING.LOAD_MORE'] }}\r\n </button>\r\n </div>\r\n\r\n </div>\r\n</div>\r\n", 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-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}.badge{font-weight:500}.proctoring-panel-header{height:auto!important}.proctoring-log{max-height:16rem}.proctoring-payload{max-height:18rem;white-space:pre-wrap;word-break:break-word}.proctoring-evi-img{width:5rem;height:5rem;object-fit:cover}\n"], components: [{ type: i3.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { type: i3.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }], directives: [{ type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.MatAccordion, selector: "mat-accordion", inputs: ["multi", "displayMode", "togglePosition", "hideToggle"], exportAs: ["matAccordion"] }, { type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.MatExpansionPanelTitle, selector: "mat-panel-title" }, { type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i3.MatExpansionPanelDescription, selector: "mat-panel-description" }, { type: i3.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { type: i2$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i2$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }], pipes: { "date": i2$1.DatePipe, "keyvalue": i2$1.KeyValuePipe } });
|
|
419
419
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: ProctoringResultComponent, decorators: [{
|
|
420
420
|
type: Component,
|
|
421
421
|
args: [{
|
|
@@ -728,7 +728,8 @@ class ProctoringService {
|
|
|
728
728
|
const ProctorLink = (sdk === null || sdk === void 0 ? void 0 : sdk.ProctorLink) || ((_a = sdk === null || sdk === void 0 ? void 0 : sdk.default) === null || _a === void 0 ? void 0 : _a.ProctorLink) || (sdk === null || sdk === void 0 ? void 0 : sdk.default);
|
|
729
729
|
this.session = ProctorLink.createSession({
|
|
730
730
|
jwt: options.jwt,
|
|
731
|
-
sessionId: options.sessionId
|
|
731
|
+
sessionId: options.sessionId,
|
|
732
|
+
draggable: true
|
|
732
733
|
});
|
|
733
734
|
const offPermission = this.session.on('permission', (result) => {
|
|
734
735
|
if ((result === null || result === void 0 ? void 0 : result.camera) === 'denied') {
|
|
@@ -820,7 +821,8 @@ class ProctoringConsentComponent {
|
|
|
820
821
|
return !this.requireCapture || this.captured;
|
|
821
822
|
}
|
|
822
823
|
get durationMinutes() {
|
|
823
|
-
|
|
824
|
+
// keep fractional minutes (e.g. 30s -> 0.5) so the display matches the saved duration
|
|
825
|
+
return Math.round((this.durationSeconds / 60) * 100) / 100;
|
|
824
826
|
}
|
|
825
827
|
ngAfterViewInit() {
|
|
826
828
|
if (this.requireCapture) {
|
|
@@ -2072,6 +2074,7 @@ class AssessmentTakerComponent {
|
|
|
2072
2074
|
this.overallNotesCtrl = new FormControl('');
|
|
2073
2075
|
this.expandedState = [];
|
|
2074
2076
|
this.youtubeUrlCache = {};
|
|
2077
|
+
this.newAssesseeSession = false;
|
|
2075
2078
|
this._selectedTabIndex = 0;
|
|
2076
2079
|
this.sectionErrors = [];
|
|
2077
2080
|
this.tenantId = 0;
|
|
@@ -2347,6 +2350,7 @@ class AssessmentTakerComponent {
|
|
|
2347
2350
|
this.assesseeResponse = Object.assign(Object.assign({}, this.assesseeResponse), res);
|
|
2348
2351
|
}
|
|
2349
2352
|
if (!assesseeId) {
|
|
2353
|
+
this.newAssesseeSession = true;
|
|
2350
2354
|
// first attempt just created the assessee — notify the host it's in progress
|
|
2351
2355
|
this.submitAssessment.emit({
|
|
2352
2356
|
assesseeId: (_b = this.assesseeResponse) === null || _b === void 0 ? void 0 : _b.id,
|
|
@@ -2402,7 +2406,7 @@ class AssessmentTakerComponent {
|
|
|
2402
2406
|
this.updateDisplayTime();
|
|
2403
2407
|
return;
|
|
2404
2408
|
}
|
|
2405
|
-
if (this.resumeTimerAcrossVisits) {
|
|
2409
|
+
if (this.resumeTimerAcrossVisits && !this.newAssesseeSession) {
|
|
2406
2410
|
this.beginTrackedTimer(duration);
|
|
2407
2411
|
}
|
|
2408
2412
|
else {
|
|
@@ -2823,7 +2827,7 @@ class AssessmentTakerComponent {
|
|
|
2823
2827
|
this.submitAssessment.emit({
|
|
2824
2828
|
assesseeId: ((_c = this.assesseeResponse) === null || _c === void 0 ? void 0 : _c.id) || res,
|
|
2825
2829
|
assesseeResponse: ((_d = this.assesseeResponse) === null || _d === void 0 ? void 0 : _d.id) ? this.assesseeResponse : payload,
|
|
2826
|
-
completed: goNext && (this.selectedTabIndex == this.sectionFormGroups.length - 1 || this.verticalView)
|
|
2830
|
+
completed: goNext && (this.selectedTabIndex == this.sectionFormGroups.length - 1 || this.verticalView || this.isAutoSubmitting)
|
|
2827
2831
|
});
|
|
2828
2832
|
if (goNext && this.selectedTabIndex < this.sectionFormGroups.length - 1 && !this.isAutoSubmitting) {
|
|
2829
2833
|
this.selectedTabIndex++;
|
|
@@ -2978,7 +2982,7 @@ class AssessmentTakerComponent {
|
|
|
2978
2982
|
this.updateDisplayTime();
|
|
2979
2983
|
this.disableForm();
|
|
2980
2984
|
this.isAutoSubmitting = true;
|
|
2981
|
-
this.save(
|
|
2985
|
+
this.save();
|
|
2982
2986
|
}
|
|
2983
2987
|
disableForm() {
|
|
2984
2988
|
var _a;
|
|
@@ -4663,7 +4667,8 @@ class AssessmentMakerComponent {
|
|
|
4663
4667
|
readDuration(instance) {
|
|
4664
4668
|
var _a;
|
|
4665
4669
|
const seconds = (_a = instance === null || instance === void 0 ? void 0 : instance.duration) !== null && _a !== void 0 ? _a : 0;
|
|
4666
|
-
|
|
4670
|
+
// keep fractional minutes (e.g. 30s -> 0.5) rather than rounding to whole minutes
|
|
4671
|
+
this.durationMinutes = seconds > 0 ? Math.round((seconds / 60) * 100) / 100 : null;
|
|
4667
4672
|
}
|
|
4668
4673
|
/** Blocks characters that would enter a negative/exponent value in the duration input. */
|
|
4669
4674
|
blockNegativeKeys(event) {
|