From 2b7ebe6036dbe93663da181c41ac02870492e043 Mon Sep 17 00:00:00 2001 From: paf <paf@titelfrei.de> Date: Wed, 2 Dec 2020 14:39:07 +0100 Subject: [PATCH] make all tests from group available for group-monitor as demo --- docs/test-mode.md | 19 +-- .../monitor-starter.component.css | 26 ++++ .../monitor-starter.component.html | 13 +- .../monitor-starter.component.ts | 135 ++++++++++-------- src/app/app-route-guards.ts | 4 +- src/app/config/test-mode.ts | 2 +- src/app/config/test-modes.json | 12 ++ 7 files changed, 139 insertions(+), 72 deletions(-) create mode 100644 src/app/app-root/monitor-starter/monitor-starter.component.css diff --git a/docs/test-mode.md b/docs/test-mode.md index 2895d07e..861f47e9 100644 --- a/docs/test-mode.md +++ b/docs/test-mode.md @@ -14,17 +14,18 @@ then switch on some restrictions and store responses, and finally evaluate the test like a testtaker. * `DEMO` (default): Nur Ansicht (Demo) +* `MONITOR-GROUP`: Testgruppen-Monitor (Demo) * `HOT`: Durchführung Test/Befragung * `REVIEW`: Prüfdurchgang ohne Speichern * `TRIAL`: Prüfdurchgang mit Speichern -| | `DEMO` | `HOT` | `REVIEW` | `TRIAL` | -| :------------- | :-------------: | :-------------: | :-------------: | :-------------: | -|Es können Reviews abgegeben werden (Kommentare/Einschätzungen zur Unit bzw. zum Test)| | |X | | -|Es werden Antworten und Logs gespeichert.| |X | |X | -|Alle Zeitbeschränkungen für Testabschnitte werden angewendet.| |X | |X | -|Alle Navigationsbeschränkungen des Booklets werden angewendet (z. B. erst weiter, wenn vollständig angezeigt).| |X | |X | -|Sollte ein Testabschnitt mit einem Freigabewort geschützt sein, wird dieses bei der Eingabebox schon eingetragen.|X | |X |X | -|Sollte eine Maximalzeit für einen Testabschnitt festgelegt sein, wird die verbleibende Zeit angezeigt, auch wenn die Booklet-Konfiguration dies unterbindet.|X | |X | | -|Die Seite mit der Aufgaben-Übersicht wird erlaubt, auch wenn das Booklet dies unterbindet.| | |X | | +| | `DEMO` | `MONITOR-GROUP` | `HOT` | `REVIEW` | `TRIAL` | +| :------------- | :-------------: | :-------------: | :-------------: | :-------------: | :-------------: | +|Es können Reviews abgegeben werden (Kommentare/Einschätzungen zur Unit bzw. zum Test)| | | |X | | +|Es werden Antworten und Logs gespeichert.| | |X | |X | +|Alle Zeitbeschränkungen für Testabschnitte werden angewendet.| | |X | |X | +|Alle Navigationsbeschränkungen des Booklets werden angewendet (z. B. erst weiter, wenn vollständig angezeigt).| | |X | |X | +|Sollte ein Testabschnitt mit einem Freigabewort geschützt sein, wird dieses bei der Eingabebox schon eingetragen.|X |X | |X |X | +|Sollte eine Maximalzeit für einen Testabschnitt festgelegt sein, wird die verbleibende Zeit angezeigt, auch wenn die Booklet-Konfiguration dies unterbindet.|X |X | |X | | +|Die Seite mit der Aufgaben-Übersicht wird erlaubt, auch wenn das Booklet dies unterbindet.| | | |X | | diff --git a/src/app/app-root/monitor-starter/monitor-starter.component.css b/src/app/app-root/monitor-starter/monitor-starter.component.css new file mode 100644 index 00000000..43a8e83f --- /dev/null +++ b/src/app/app-root/monitor-starter/monitor-starter.component.css @@ -0,0 +1,26 @@ +mat-card { + margin: 10px; +} + +.mat-card-gray { + background-color: lightgray +} + +.booklet_title { + display: block; + font-size: 16pt; + margin-top: 4px; + margin-bottom: 0; + white-space: pre-wrap; + word-break: break-word; + line-height: 130%; +} + +.booklet_status { + display: block; + font-size: 8pt; + margin-top: 0; + color: mediumturquoise; + height: 24px; + margin-bottom: 18px; +} diff --git a/src/app/app-root/monitor-starter/monitor-starter.component.html b/src/app/app-root/monitor-starter/monitor-starter.component.html index 08a0bc54..05b65e16 100644 --- a/src/app/app-root/monitor-starter/monitor-starter.component.html +++ b/src/app/app-root/monitor-starter/monitor-starter.component.html @@ -6,9 +6,18 @@ <p *ngIf="accessObjects.length === 0"> Sie sind angemeldet. Aktuell sind keine Testgruppen zur Überwachung für Sie freigegeben. </p> + <p style="color: chocolate"><b>{{ problemText }}</b></p> <button mat-raised-button color="primary" (click)="buttonGotoMonitor(accessObject)" - *ngFor="let accessObject of accessObjects"> - {{accessObject.name}} + *ngFor="let accessObject of accessObjects[AuthAccessKeyType.TEST_GROUP_MONITOR]"> + <span class="booklet_title">{{accessObject.name}}</span> + <span class="booklet_status">Überwachung starten</span> + </button> + <br> + <h4>Folgende Testhefte stehen für Sie zur Ansicht bereit:</h4> + <button mat-raised-button color="primary" (click)="startTest(b)" [disabled]="b.locked" + *ngFor="let b of accessObjects[AuthAccessKeyType.TEST]"> + <span class="booklet_title">{{b.label}}</span> + <span class="booklet_status">{{b.locked ? 'gesperrt' : (b.running ? 'Fortsetzen' : 'Ansehen')}}</span> </button> </div> </mat-card-content> diff --git a/src/app/app-root/monitor-starter/monitor-starter.component.ts b/src/app/app-root/monitor-starter/monitor-starter.component.ts index 3a9fbc9f..06f80035 100644 --- a/src/app/app-root/monitor-starter/monitor-starter.component.ts +++ b/src/app/app-root/monitor-starter/monitor-starter.component.ts @@ -1,25 +1,21 @@ -import { Component, OnDestroy, OnInit } from '@angular/core'; -import { from, Subscription } from 'rxjs'; -import { Router } from '@angular/router'; -import { concatMap } from 'rxjs/operators'; -import { CustomtextService } from 'iqb-components'; -import { BackendService } from '../../backend.service'; -import { MainDataService } from '../../maindata.service'; -import { - AccessObject, AuthAccessKeyType, AuthData, WorkspaceData -} from '../../app.interfaces'; +import {Component, OnDestroy, OnInit} from '@angular/core'; +import {from, Subscription} from 'rxjs'; +import {Router} from '@angular/router'; +import {concatMap, map} from 'rxjs/operators'; +import {CustomtextService} from 'iqb-components'; +import {BackendService} from '../../backend.service'; +import {MainDataService} from '../../maindata.service'; +import {AccessObject, AuthAccessKeyType, AuthData, BookletData} from '../../app.interfaces'; @Component({ templateUrl: './monitor-starter.component.html', - styles: [ - 'mat-card {margin: 10px;}', - '.mat-card-gray {background-color: lightgray}' - ] + styleUrls: ['./monitor-starter.component.css'] }) export class MonitorStarterComponent implements OnInit, OnDestroy { - accessObjects: (WorkspaceData|AccessObject)[] = []; - - private getWorkspaceDataSubscription: Subscription = null; + accessObjects: {[accessType: string]: (AccessObject|BookletData)[]} = {}; + private getMonitorDataSubscription: Subscription = null; + public AuthAccessKeyType = AuthAccessKeyType; + public problemText: string; constructor( private router: Router, @@ -32,51 +28,74 @@ export class MonitorStarterComponent implements OnInit, OnDestroy { setTimeout(() => { this.mds.setSpinnerOn(); this.bs.getSessionData().subscribe((authDataUntyped) => { - if (typeof authDataUntyped !== 'number') { - const authData = authDataUntyped as AuthData; - if (authData) { - if (authData.token) { - this.accessObjects = []; - let scopeIdList = []; - if (authData.access[AuthAccessKeyType.TEST_GROUP_MONITOR]) { - scopeIdList = authData.access[AuthAccessKeyType.TEST_GROUP_MONITOR]; - } - if (this.getWorkspaceDataSubscription !== null) { - this.getWorkspaceDataSubscription.unsubscribe(); - } - this.getWorkspaceDataSubscription = from(scopeIdList).pipe( - concatMap((monitorScopeId) => { - let functionReturn = null; - if (authData.access[AuthAccessKeyType.TEST_GROUP_MONITOR]) { - functionReturn = this.bs.getGroupData(monitorScopeId); - } - return functionReturn; - }) - ).subscribe( - (wsData: AccessObject) => { - if (wsData) { - this.accessObjects.push(wsData); - } - }, - () => this.mds.setSpinnerOff(), - () => this.mds.setSpinnerOff() - ); - this.mds.setAuthData(authData); - } else { - this.mds.setAuthData(); - this.mds.setSpinnerOff(); - } - } else { - this.mds.setAuthData(); - this.mds.setSpinnerOff(); - } - } else { + if (typeof authDataUntyped === 'number') { this.mds.setSpinnerOff(); + return; + } + const authData = authDataUntyped as AuthData; + if (!authData || !authData.token) { + this.mds.setAuthData(); + this.mds.setSpinnerOff(); + return; + } + this.accessObjects = {}; + + let scopeIdList: {[id: string]: {id: string, type: AuthAccessKeyType}} = {}; + [AuthAccessKeyType.TEST_GROUP_MONITOR, AuthAccessKeyType.TEST] + .forEach(accessType => { + this.accessObjects[accessType] = []; + (authData.access[accessType] || []) + .forEach(accessObjectId => { + scopeIdList[accessObjectId] = {id: accessObjectId, type: accessType}; + }); + }); + + if (this.getMonitorDataSubscription !== null) { + this.getMonitorDataSubscription.unsubscribe(); } + + this.getMonitorDataSubscription = + from(Object.keys(scopeIdList)) + .pipe( + map((accessType: AuthAccessKeyType) => scopeIdList[accessType]), + concatMap((accessIdAndType) => { + if (accessIdAndType.type === AuthAccessKeyType.TEST_GROUP_MONITOR) { + return this.bs.getGroupData(accessIdAndType.id); + } else if (authData.access[AuthAccessKeyType.TEST]) { + return this.bs.getBookletData(accessIdAndType.id); + } + }) + ) + .subscribe( + (wsData: AccessObject) => { + if (wsData) { + this.accessObjects[scopeIdList[wsData.id].type].push(wsData); + } + }, + () => this.mds.setSpinnerOff(), + () => this.mds.setSpinnerOff() + ); + + this.mds.setAuthData(authData); }); }); } + startTest(b: BookletData) { + this.bs.startTest(b.id).subscribe(testId => { + if (typeof testId === 'number') { + const errCode = testId as number; + if (errCode === 423) { + this.problemText = 'Dieser Test ist gesperrt'; + } else { + this.problemText = `Problem beim Start (${errCode})`; + } + } else { + this.router.navigate(['/t', testId]); + } + }); + } + buttonGotoMonitor(accessObject: AccessObject): void { this.router.navigateByUrl(`/gm/${accessObject.id.toString()}`); } @@ -87,8 +106,8 @@ export class MonitorStarterComponent implements OnInit, OnDestroy { } ngOnDestroy(): void { - if (this.getWorkspaceDataSubscription !== null) { - this.getWorkspaceDataSubscription.unsubscribe(); + if (this.getMonitorDataSubscription !== null) { + this.getMonitorDataSubscription.unsubscribe(); } } } diff --git a/src/app/app-route-guards.ts b/src/app/app-route-guards.ts index 00f10309..630b10d0 100644 --- a/src/app/app-route-guards.ts +++ b/src/app/app-route-guards.ts @@ -25,10 +25,10 @@ export class RouteDispatcherActivateGuard implements CanActivate { this.router.navigate(['/r/admin-starter']); } else if (authData.flags.indexOf(AuthFlagType.CODE_REQUIRED) >= 0) { this.router.navigate(['/r/code-input']); - } else if (authData.access[AuthAccessKeyType.TEST]) { - this.router.navigate(['/r/test-starter']); } else if (authData.access[AuthAccessKeyType.TEST_GROUP_MONITOR]) { this.router.navigate(['/r/monitor-starter']); + } else if (authData.access[AuthAccessKeyType.TEST]) { + this.router.navigate(['/r/test-starter']); } else { this.router.navigate(['/r/login', '']); } diff --git a/src/app/config/test-mode.ts b/src/app/config/test-mode.ts index b61f3f08..a821d65c 100644 --- a/src/app/config/test-mode.ts +++ b/src/app/config/test-mode.ts @@ -17,7 +17,7 @@ export class TestMode { public constructor (loginMode: string = 'DEMO') { if (loginMode) { - const regExPattern = /(DEMO|HOT|REVIEW|TRIAL)/; + const regExPattern = /(DEMO|MONITOR-GROUP|HOT|REVIEW|TRIAL)/; if (regExPattern.test(loginMode.toUpperCase())) { const mode = loginMode.toUpperCase().match(regExPattern)[0]; const modeConfig = testModes[mode]; diff --git a/src/app/config/test-modes.json b/src/app/config/test-modes.json index b5d80d9e..fc64f7fe 100644 --- a/src/app/config/test-modes.json +++ b/src/app/config/test-modes.json @@ -11,6 +11,18 @@ "showUnitMenu": false } }, + "MONITOR-GROUP": { + "label": "Testgruppen-Monitor (Demo)", + "config": { + "canReview": false, + "saveResponses": false, + "forceTimeRestrictions": false, + "forceNaviRestrictions": false, + "presetCode": true, + "showTimeLeft": true, + "showUnitMenu": false + } + }, "HOT": { "label": "Durchführung Test/Befragung", "config": { -- GitLab