diff --git a/src/app/iqb-common/confirm-dialog/confirm-dialog.component.html b/src/app/iqb-common/confirm-dialog/confirm-dialog.component.html index 8de87e10f2f37cc42cb3a99753a353acd8c5343d..fd9eb14ed52e7b558acb6c49d4d8a7e817503c97 100644 --- a/src/app/iqb-common/confirm-dialog/confirm-dialog.component.html +++ b/src/app/iqb-common/confirm-dialog/confirm-dialog.component.html @@ -8,5 +8,5 @@ <mat-dialog-actions> <button mat-raised-button color="primary" [mat-dialog-close]="true">{{ confirmdata.confirmbuttonlabel }}</button> - <button mat-raised-button [mat-dialog-close]="false">Abbrechen</button> + <button mat-raised-button *ngIf="showcancel" [mat-dialog-close]="false">Abbrechen</button> </mat-dialog-actions> diff --git a/src/app/iqb-common/confirm-dialog/confirm-dialog.component.ts b/src/app/iqb-common/confirm-dialog/confirm-dialog.component.ts index 9751f762398a6f8af11425f1c84dc4506bf1bc76..18282e86b47c2a678e0c75d9ea0d17b9a4c6d155 100644 --- a/src/app/iqb-common/confirm-dialog/confirm-dialog.component.ts +++ b/src/app/iqb-common/confirm-dialog/confirm-dialog.component.ts @@ -7,6 +7,7 @@ import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; styleUrls: ['./confirm-dialog.component.css'] }) export class ConfirmDialogComponent implements OnInit { + public showcancel = true; constructor(@Inject(MAT_DIALOG_DATA) public confirmdata: ConfirmDialogData) { @@ -19,6 +20,9 @@ export class ConfirmDialogComponent implements OnInit { if ((typeof this.confirmdata.confirmbuttonlabel === 'undefined') || (this.confirmdata.confirmbuttonlabel.length === 0)) { this.confirmdata.confirmbuttonlabel = 'Bestätigen'; } + if (!this.confirmdata.showcancel) { + this.showcancel = false; + } } } @@ -27,4 +31,5 @@ export interface ConfirmDialogData { title: string; content: string; confirmbuttonlabel: string; + showcancel: boolean; } diff --git a/src/app/start/start.component.html b/src/app/start/start.component.html index 05d7d47632cad2b876ce09d62f249d861ca157c6..27e80f9dd740e706963913328ac590c46711c36e 100644 --- a/src/app/start/start.component.html +++ b/src/app/start/start.component.html @@ -37,7 +37,7 @@ <mat-card-title>{{ showCodeForm | customText:'login_codeInputTitle' }}</mat-card-title> <mat-card-content> <mat-form-field> - <input matInput formControlName="code" placeholder="Personen-Code"(keyup.enter)="codeinput()"> + <input matInput formControlName="code" placeholder="Personen-Code" (keyup.enter)="codeinput()"> </mat-form-field> </mat-card-content> <mat-card-actions> diff --git a/src/app/test-controller/start-lock-input/start-lock-input.component.html b/src/app/test-controller/start-lock-input/start-lock-input.component.html index 04231365581fcd1f21803eda8687c821377dae57..cb0b7675c0a743324c5781d75161f0981ad2d70d 100644 --- a/src/app/test-controller/start-lock-input/start-lock-input.component.html +++ b/src/app/test-controller/start-lock-input/start-lock-input.component.html @@ -4,12 +4,14 @@ <mat-dialog-content> <mat-form-field *ngFor="let c of data.codes" fxLayout="column"> <p>{{ c.prompt }}</p> - <input matInput [formControlName]="c.testletId" [(ngModel)]="c.value"> + <input matInput [formControlName]="c.testletId" [(ngModel)]="c.value" (keyup.enter)="close()"> </mat-form-field> </mat-dialog-content> <mat-dialog-actions> - <button mat-raised-button color="primary" type="submit" [mat-dialog-close]="data.codes">Weiter</button> + <button mat-raised-button #okButton color="primary" + [disabled]="startkeyform.invalid" + type="submit" [mat-dialog-close]="data.codes">Weiter</button> <button mat-raised-button [mat-dialog-close]="false">Abbrechen</button> </mat-dialog-actions> </form> diff --git a/src/app/test-controller/start-lock-input/start-lock-input.component.ts b/src/app/test-controller/start-lock-input/start-lock-input.component.ts index 1d7226ada69ead9914a8a5b8ee2a53e817476c30..07a01da18a7500a0745b27c17023e79c14a17772 100644 --- a/src/app/test-controller/start-lock-input/start-lock-input.component.ts +++ b/src/app/test-controller/start-lock-input/start-lock-input.component.ts @@ -1,4 +1,4 @@ -import { MAT_DIALOG_DATA } from '@angular/material'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Component, OnInit, Inject } from '@angular/core'; import { StartLockData } from '../test-controller.interfaces'; @@ -8,17 +8,22 @@ import { StartLockData } from '../test-controller.interfaces'; templateUrl: './start-lock-input.component.html', styleUrls: ['./start-lock-input.component.css'] }) -export class StartLockInputComponent implements OnInit{ +export class StartLockInputComponent implements OnInit { startkeyform: FormGroup; constructor(private fb: FormBuilder, + private dialogRef: MatDialogRef<StartLockInputComponent>, @Inject(MAT_DIALOG_DATA) public data: StartLockData) { } ngOnInit() { const controlsConfig = {}; this.data.codes.forEach(c => { - controlsConfig[c.testletId] = this.fb.control('', [Validators.required, Validators.minLength(3)]) + controlsConfig[c.testletId] = this.fb.control('', [Validators.required, Validators.minLength(3)]); }); this.startkeyform = this.fb.group(controlsConfig); } + + close() { + this.dialogRef.close(this.data.codes); + } } diff --git a/src/app/test-controller/test-controller.component.html b/src/app/test-controller/test-controller.component.html index c8b611a73b0ca7bd5e24d1779bdce25cdf03e3ee..98703cab638ef7657479fc501228e34fce9f8542 100644 --- a/src/app/test-controller/test-controller.component.html +++ b/src/app/test-controller/test-controller.component.html @@ -5,10 +5,10 @@ </div> <div id="buttonsContainer" fxLayout="row wrap" fxLayoutAlign="end center"> <p class="timer" *ngIf="tcs.mode !== 'hot'">{{ timerValue?.timeLeftString }}</p> - <button mat-fab [disabled]="!(tcs.unitPrevEnabled$ | async)" color="accent" (click)="tcs.setUnitNavigationRequest('#previous')" matTooltip="Zurück"> + <button mat-fab [disabled]="!(tcs.unitPrevEnabled$ | async)" *ngIf="tcs.navArrows" color="accent" (click)="tcs.setUnitNavigationRequest('#previous')" matTooltip="Zurück"> <i class="material-icons">chevron_left</i> </button> - <div *ngIf="tcs.showNavButtons" fxLayout="row" fxLayoutAlign="start center"> + <div *ngIf="tcs.navButtons" fxLayout="row" fxLayoutAlign="start center"> <div *ngFor="let u of (tcs.unitListForNaviButtons$ | async)"> <div fxLayout="column" fxLayoutAlign="start center"> <button (click)="gotoUnit(u.sequenceId)" class="unit-button" [disabled]="u.disabled">{{ u.label }}</button> @@ -17,7 +17,7 @@ </div> </div> </div> - <button mat-fab [disabled]="!(tcs.unitNextEnabled$ | async)" color="accent" (click)="tcs.setUnitNavigationRequest('#next')" matTooltip="Weiter"> + <button mat-fab [disabled]="!(tcs.unitNextEnabled$ | async)" *ngIf="tcs.navArrows" color="accent" (click)="tcs.setUnitNavigationRequest('#next')" matTooltip="Weiter"> <i class="material-icons">chevron_right</i> </button> <button mat-button (click)="showReviewDialog()" *ngIf="tcs.mode === 'review'" matTooltip="Kommentar senden"> diff --git a/src/app/test-controller/test-controller.component.ts b/src/app/test-controller/test-controller.component.ts index 0582b199f45b3e30ee3d283207a8e5b6f7f98b9e..380f3e8f760de0ca91af9bb68ee1a8d0328fbe44 100644 --- a/src/app/test-controller/test-controller.component.ts +++ b/src/app/test-controller/test-controller.component.ts @@ -177,27 +177,61 @@ export class TestControllerComponent implements OnInit, OnDestroy { if (bookletConfigElements.length > 0) { const bookletConfigs = bookletConfigElements[0].children; for (let childIndex = 0; childIndex < bookletConfigs.length; childIndex++) { - if (bookletConfigs[childIndex].nodeName === 'NavPolicy') { - const configParameter = bookletConfigs[childIndex].getAttribute('parameter'); - if ((typeof configParameter !== 'undefined') && (configParameter !== null)) { - if (configParameter.toUpperCase() === 'NextOnlyIfPresentationComplete'.toUpperCase()) { - this.tcs.navPolicyNextOnlyIfPresentationComplete = true; + const configParameter = bookletConfigs[childIndex].getAttribute('parameter'); + const configValue = bookletConfigs[childIndex].textContent; + switch (bookletConfigs[childIndex].nodeName) { + // ---------------------- + case 'NavPolicy': + if (configParameter) { + if (configParameter.toUpperCase() === 'NextOnlyIfPresentationComplete'.toUpperCase()) { + this.tcs.navPolicyNextOnlyIfPresentationComplete = true; + } } - } - } else if (bookletConfigs[childIndex].nodeName === 'ShowNaviButtons') { - const configParameter = bookletConfigs[childIndex].getAttribute('parameter'); - if ((typeof configParameter !== 'undefined') && (configParameter !== null)) { - if (configParameter === '1') { - this.tcs.showNavButtons = true; + break; + // ---------------------- + case 'ShowNaviButtons': + case 'NavButtons': + if (configParameter) { + switch (configParameter.toUpperCase()) { + case '1': + case 'ON': + this.tcs.navButtons = true; + this.tcs.navArrows = true; + break; + case 'OFF': + this.tcs.navButtons = false; + this.tcs.navArrows = false; + break; + case 'ARROWSONLY': // default + this.tcs.navButtons = false; + this.tcs.navArrows = true; + break; + default: + console.log('unknown booklet configParameter NavButtons "' + configParameter + '"'); + break; + } } - } - } else if (bookletConfigs[childIndex].nodeName === 'LockOnlyIfResponsesComplete') { - const configParameter = bookletConfigs[childIndex].getAttribute('parameter'); - if ((typeof configParameter !== 'undefined') && (configParameter !== null)) { - if (configParameter === '1') { - this.tcs.LockOnlyIfResponsesComplete = true; + break; + // ---------------------- + case 'PageNavBar': + if (configParameter) { + if (configParameter.toUpperCase() === 'OFF') { + this.tcs.pageNav = false; + } } - } + break; + // ---------------------- + case 'Logging': + if (configParameter) { + if (configParameter.toUpperCase() === 'OFF') { + this.tcs.logging = false; + } + } + break; + // ---------------------- + default: + console.log('unknown booklet config "' + bookletConfigs[childIndex].nodeName + '"'); + break; } } } diff --git a/src/app/test-controller/test-controller.service.ts b/src/app/test-controller/test-controller.service.ts index 53a69e34b57bc5bdeaf3e512abc49aea6522ac1b..2d2f4c0acd9faa65a94bdb7e60785e62402c3dda 100644 --- a/src/app/test-controller/test-controller.service.ts +++ b/src/app/test-controller/test-controller.service.ts @@ -22,6 +22,7 @@ export class TestControllerService { public minUnitSequenceId = 0; public loginname = ''; public mode = ''; + public logging = true; public navigationRequest$ = new Subject<string>(); public maxTimeTimer$ = new Subject<MaxTimerData>(); @@ -35,8 +36,9 @@ export class TestControllerService { public unitNextEnabled$ = new BehaviorSubject<boolean>(false); public unitListForNaviButtons$ = new BehaviorSubject<UnitNaviButtonData[]>([]); public navPolicyNextOnlyIfPresentationComplete = false; - public showNavButtons = false; - public LockOnlyIfResponsesComplete = false; + public navButtons = false; + public navArrows = true; + public pageNav = true; public get currentUnitSequenceId(): number { return this._currentUnitSequenceId; @@ -44,7 +46,7 @@ export class TestControllerService { public set currentUnitSequenceId(v: number) { this.unitPrevEnabled$.next(v > this.minUnitSequenceId); this.unitNextEnabled$.next(v < this.maxUnitSequenceId); - if (this.rootTestlet && this.showNavButtons) { + if (this.rootTestlet && this.navButtons) { const myUnitListForNaviButtons: UnitNaviButtonData[] = []; for (let sequ = 1; sequ <= this.rootTestlet.getMaxSequenceId(); sequ++) { const myUnitData = this.rootTestlet.getUnitAt(sequ); @@ -112,6 +114,7 @@ export class TestControllerService { this.rootTestlet = null; this.maxUnitSequenceId = 0; this.mode = ''; + this.logging = true; this.loginname = ''; this.currentUnitSequenceId = 0; this.currentUnitDbKey = ''; @@ -126,7 +129,9 @@ export class TestControllerService { this.LastMaxTimerState = {}; this.unitListForNaviButtons$.next([]); this.navPolicyNextOnlyIfPresentationComplete = false; - this.showNavButtons = false; + this.navButtons = false; + this.navArrows = true; + this.pageNav = true; this._costumTexts = {}; } @@ -199,7 +204,7 @@ export class TestControllerService { // 7777777777777777777777777777777777777777777777777777777777777777777777 public addBookletLog(logKey: LogEntryKey, entry = '') { - if (this.mode !== 'review') { + if ((this.mode !== 'review') && this.logging) { this.bs.addBookletLog(this.bookletDbId, Date.now(), entry.length > 0 ? logKey + ': ' + JSON.stringify(entry) : logKey).subscribe(ok => { if (ok instanceof ServerError) { @@ -218,7 +223,7 @@ export class TestControllerService { } } public addUnitLog(unitDbKey: string, logKey: LogEntryKey, entry = '') { - if (this.mode !== 'review') { + if ((this.mode !== 'review') && this.logging) { this.bs.addUnitLog(this.bookletDbId, Date.now(), unitDbKey, entry.length > 0 ? logKey + ': ' + JSON.stringify(entry) : logKey).subscribe(ok => { if (ok instanceof ServerError) { diff --git a/src/app/test-controller/unithost/unit-routing-guards.ts b/src/app/test-controller/unithost/unit-routing-guards.ts index 9221949c1708834c896beb09b72375d96a3eb1db..9c8c1adbc958c2bae2b3dcd91e631821a389c338 100644 --- a/src/app/test-controller/unithost/unit-routing-guards.ts +++ b/src/app/test-controller/unithost/unit-routing-guards.ts @@ -38,29 +38,20 @@ export class UnitActivateGuard implements CanActivate { checkPC = this.tcs.currentUnitSequenceId < newUnit.unitDef.sequenceId; } if (checkPC) { - if (this.tcs.hasUnitPresentationComplete(this.tcs.currentUnitSequenceId)) { - const pcValue = this.tcs.getUnitPresentationComplete(this.tcs.currentUnitSequenceId); - if (pcValue === 'yes') { - return of(true); - } else { - if (this.tcs.mode === 'hot') { - const dialogCDRef = this.confirmDialog.open(ConfirmDialogComponent, { - width: '500px', - // height: '300px', - data: <ConfirmDialogData>{ - title: this.getCostumText('booklet_msgPresentationNotCompleteTitle'), - content: this.getCostumText('booklet_msgPresentationNotCompleteText'), - confirmbuttonlabel: 'OK', - confirmbuttonreturn: false - } - }); - return dialogCDRef.afterClosed().pipe(map(ok => false)); - } else { - this.snackBar.open('Im Hot-Modus dürfte hier nicht weitergeblättert werden (PresentationNotComplete).', - 'Weiterblättern', {duration: 3000}); - return of(true); + let myreturn = true; + let checkUnitSequenceId = newUnit.unitDef.sequenceId - 1; + while (myreturn && (checkUnitSequenceId >= this.tcs.currentUnitSequenceId)) { + if (this.tcs.hasUnitPresentationComplete(checkUnitSequenceId)) { + if (this.tcs.getUnitPresentationComplete(checkUnitSequenceId) !== 'yes') { + myreturn = false; } + } else { + myreturn = false; } + checkUnitSequenceId -= 1; + } + if (myreturn) { + return of(true); } else { if (this.tcs.mode === 'hot') { const dialogCDRef = this.confirmDialog.open(ConfirmDialogComponent, { @@ -70,7 +61,8 @@ export class UnitActivateGuard implements CanActivate { title: this.getCostumText('booklet_msgPresentationNotCompleteTitle'), content: this.getCostumText('booklet_msgPresentationNotCompleteText'), confirmbuttonlabel: 'OK', - confirmbuttonreturn: false + confirmbuttonreturn: false, + showcancel: false } }); return dialogCDRef.afterClosed().pipe(map(ok => false)); @@ -101,6 +93,7 @@ export class UnitActivateGuard implements CanActivate { const dialogRef = this.startLockDialog.open(StartLockInputComponent, { width: '500px', + autoFocus: true, data: <StartLockData>{ title: this.getCostumText('booklet_codeToEnterTitle'), prompt: this.getCostumText('booklet_codeToEnterPrompt'), @@ -114,6 +107,7 @@ export class UnitActivateGuard implements CanActivate { } else { const codeData = result as CodeInputData[]; let codesOk = true; + console.log(codeData); for (const c of codeData) { if (c.value.toUpperCase().trim() !== c.code) { codesOk = false; @@ -160,7 +154,8 @@ export class UnitActivateGuard implements CanActivate { title: this.getCostumText('booklet_warningLeaveTimerBlockTitle'), content: this.getCostumText('booklet_warningLeaveTimerBlockPrompt'), confirmbuttonlabel: 'Trotzdem weiter', - confirmbuttonreturn: true + confirmbuttonreturn: true, + showcancel: true } }); return dialogCDRef.afterClosed().pipe( @@ -196,12 +191,12 @@ export class UnitActivateGuard implements CanActivate { const dialogCDRef = this.confirmDialog.open(ConfirmDialogComponent, { width: '500px', - // height: '300px', data: <ConfirmDialogData>{ title: this.getCostumText('booklet_warningLeaveTimerBlockTitle'), content: this.getCostumText('booklet_warningLeaveTimerBlockTextPrompt'), confirmbuttonlabel: 'Trotzdem weiter', - confirmbuttonreturn: true + confirmbuttonreturn: true, + showcancel: true } }); return dialogCDRef.afterClosed().pipe( diff --git a/src/app/test-controller/unithost/unithost.component.html b/src/app/test-controller/unithost/unithost.component.html index cb22160a00eeaf5c3007948ca50f52c7814d00c4..b890e7636670667713215cf7141c30383c56c4b5 100644 --- a/src/app/test-controller/unithost/unithost.component.html +++ b/src/app/test-controller/unithost/unithost.component.html @@ -2,15 +2,15 @@ {{ unitTitle }} </div> <div id="iFrameHost" iqbResizeIFrameChild class="unit-body"> - + </div> -<div id="pageNav" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="10px"> - +<div id="pageNav" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="10px" *ngIf="tcs.pageNav"> + <div fxLayout="row" fxLayoutAlign="space-between center" *ngIf="showPageNav"> <div id="pageNavPrompt"> Wähle hier andere Seiten dieser Aufgabe: </div> - + <div *ngFor="let p of pageList"> <button *ngIf="p.type === '#previous'" (click)="gotoPage(p.type)" [disabled]="p.disabled" fxLayout="row" fxLayoutAlign="center center"> <i class="material-icons">chevron_left</i> diff --git a/src/app/test-controller/unithost/unithost.component.ts b/src/app/test-controller/unithost/unithost.component.ts index 6d19f7d59228a3007f49e5917045487aa5789804..9412ed5c33c30d128641a9312ff415a2edad4d9f 100644 --- a/src/app/test-controller/unithost/unithost.component.ts +++ b/src/app/test-controller/unithost/unithost.component.ts @@ -43,7 +43,7 @@ export class UnithostComponent implements OnInit, OnDestroy { constructor( - private tcs: TestControllerService, + public tcs: TestControllerService, private mds: MainDataService, private route: ActivatedRoute ) { @@ -205,7 +205,9 @@ export class UnithostComponent implements OnInit, OnDestroy { } this.leaveWarning = false; - + if (!this.tcs.pageNav) { + this.iFrameHostElement.style.bottom = '0px'; + } this.iFrameHostElement.appendChild(this.iFrameItemplayer); } }); diff --git a/src/environments/environment.build.ts b/src/environments/environment.build.ts index cbe7d0cb085a7df39d16c0255707654890aac2b2..4bd5a151a71d16c598548449579ed0eb58bd2131 100644 --- a/src/environments/environment.build.ts +++ b/src/environments/environment.build.ts @@ -5,5 +5,5 @@ export const environment = { testcenterUrl: '/', appName: 'IQB-Testcenter', appPublisher: 'IQB - Institut zur Qualitätsentwicklung im Bildungswesen', - appVersion: '1.0 - 24.3.2019' + appVersion: '1.1 - 25.3.2019' }; diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts index 680a2432afd6b0480b2edcba099e786cb7285a28..fd9dd57b6a4b9894a46e5e0a673659801a116a5f 100644 --- a/src/environments/environment.prod.ts +++ b/src/environments/environment.prod.ts @@ -5,5 +5,5 @@ export const environment = { testcenterUrl: '/', appName: 'IQB-Testcenter', appPublisher: 'IQB - Institut zur Qualitätsentwicklung im Bildungswesen', - appVersion: '1.0 - 24.3.2019' + appVersion: '1.1 - 25.3.2019' };