Commit 0d2074a6 authored by Christopher Fullarton's avatar Christopher Fullarton

Adds warning if the quiz data can be lost by navigation interactions

parent 4ad94e6c
export interface IHasTriggeredNavigation {
hasTriggeredNavigation: boolean;
}
...@@ -13,7 +13,7 @@ export class ServerUnavailableModalComponent implements OnDestroy { ...@@ -13,7 +13,7 @@ export class ServerUnavailableModalComponent implements OnDestroy {
} }
public reloadPage(): void { public reloadPage(): void {
location.reload(true); window.caches.keys().then(keys => Promise.all(keys.map(key => window.caches.delete(key)))).finally(() => location.reload(true));
} }
public ngOnDestroy(): void { public ngOnDestroy(): void {
......
...@@ -9,6 +9,7 @@ import { StorageKey } from '../../../lib/enums/enums'; ...@@ -9,6 +9,7 @@ import { StorageKey } from '../../../lib/enums/enums';
import { MessageProtocol } from '../../../lib/enums/Message'; import { MessageProtocol } from '../../../lib/enums/Message';
import { QuizState } from '../../../lib/enums/QuizState'; import { QuizState } from '../../../lib/enums/QuizState';
import { IMessage } from '../../../lib/interfaces/communication/IMessage'; import { IMessage } from '../../../lib/interfaces/communication/IMessage';
import { IHasTriggeredNavigation } from '../../../lib/interfaces/IHasTriggeredNavigation';
import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component'; import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component';
import { MemberApiService } from '../../../service/api/member/member-api.service'; import { MemberApiService } from '../../../service/api/member/member-api.service';
import { AttendeeService } from '../../../service/attendee/attendee.service'; import { AttendeeService } from '../../../service/attendee/attendee.service';
...@@ -22,9 +23,11 @@ import { QuizService } from '../../../service/quiz/quiz.service'; ...@@ -22,9 +23,11 @@ import { QuizService } from '../../../service/quiz/quiz.service';
templateUrl: './confidence-rate.component.html', templateUrl: './confidence-rate.component.html',
styleUrls: ['./confidence-rate.component.scss'], styleUrls: ['./confidence-rate.component.scss'],
}) })
export class ConfidenceRateComponent implements OnInit, OnDestroy { export class ConfidenceRateComponent implements OnInit, OnDestroy, IHasTriggeredNavigation {
public static TYPE = 'ConfidenceRateComponent'; public static TYPE = 'ConfidenceRateComponent';
public hasTriggeredNavigation: boolean;
private _confidenceValue = '100'; private _confidenceValue = '100';
get confidenceValue(): string { get confidenceValue(): string {
...@@ -60,11 +63,18 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy { ...@@ -60,11 +63,18 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy {
} }
if (this.quizService.quiz.state === QuizState.Inactive) { if (this.quizService.quiz.state === QuizState.Inactive) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
return; return;
} }
}); });
if (this.attendeeService.hasConfidenceValue()) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']);
return;
}
this.quizService.loadDataToPlay(sessionStorage.getItem(StorageKey.CurrentQuizName)).then(() => { this.quizService.loadDataToPlay(sessionStorage.getItem(StorageKey.CurrentQuizName)).then(() => {
this.handleMessages(); this.handleMessages();
}); });
...@@ -111,6 +121,7 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy { ...@@ -111,6 +121,7 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy {
public async sendConfidence(): Promise<Subscription> { public async sendConfidence(): Promise<Subscription> {
return this.memberApiService.putConfidenceValue(parseInt(this._confidenceValue, 10)).subscribe((data: IMessage) => { return this.memberApiService.putConfidenceValue(parseInt(this._confidenceValue, 10)).subscribe((data: IMessage) => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']); this.router.navigate(['/quiz', 'flow', 'results']);
}); });
} }
...@@ -122,8 +133,10 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy { ...@@ -122,8 +133,10 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy {
sessionStorage.removeItem(StorageKey.CurrentQuestionIndex); sessionStorage.removeItem(StorageKey.CurrentQuestionIndex);
}), this.messageQueue.subscribe(MessageProtocol.Start, payload => { }), this.messageQueue.subscribe(MessageProtocol.Start, payload => {
this.quizService.quiz.currentStartTimestamp = payload.currentStartTimestamp; this.quizService.quiz.currentStartTimestamp = payload.currentStartTimestamp;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'voting']); this.router.navigate(['/quiz', 'flow', 'voting']);
}), this.messageQueue.subscribe(MessageProtocol.Stop, payload => { }), this.messageQueue.subscribe(MessageProtocol.Stop, () => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']); this.router.navigate(['/quiz', 'flow', 'results']);
}), this.messageQueue.subscribe(MessageProtocol.UpdatedResponse, payload => { }), this.messageQueue.subscribe(MessageProtocol.UpdatedResponse, payload => {
console.log('ConfidenceRateComponent: modify response data for nickname', payload.nickname); console.log('ConfidenceRateComponent: modify response data for nickname', payload.nickname);
...@@ -131,6 +144,7 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy { ...@@ -131,6 +144,7 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy {
}), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => { }), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => {
this.quizService.quiz.sessionConfig = payload.sessionConfig; this.quizService.quiz.sessionConfig = payload.sessionConfig;
}), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => { }), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => {
this.hasTriggeredNavigation = true;
if (environment.readingConfirmationEnabled) { if (environment.readingConfirmationEnabled) {
this.router.navigate(['/quiz', 'flow', 'reading-confirmation']); this.router.navigate(['/quiz', 'flow', 'reading-confirmation']);
} else { } else {
...@@ -139,12 +153,14 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy { ...@@ -139,12 +153,14 @@ export class ConfidenceRateComponent implements OnInit, OnDestroy {
}), this.messageQueue.subscribe(MessageProtocol.Reset, payload => { }), this.messageQueue.subscribe(MessageProtocol.Reset, payload => {
this.attendeeService.clearResponses(); this.attendeeService.clearResponses();
this.quizService.quiz.currentQuestionIndex = -1; this.quizService.quiz.currentQuestionIndex = -1;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'lobby']); this.router.navigate(['/quiz', 'flow', 'lobby']);
}), this.messageQueue.subscribe(MessageProtocol.Added, payload => { }), this.messageQueue.subscribe(MessageProtocol.Added, payload => {
this.attendeeService.addMember(payload.member); this.attendeeService.addMember(payload.member);
}), this.messageQueue.subscribe(MessageProtocol.Removed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Removed, payload => {
this.attendeeService.removeMember(payload.name); this.attendeeService.removeMember(payload.name);
}), this.messageQueue.subscribe(MessageProtocol.Closed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Closed, () => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}), }),
]); ]);
......
import { isPlatformBrowser } from '@angular/common';
import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID, SecurityContext } from '@angular/core'; import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
...@@ -10,6 +9,7 @@ import { environment } from '../../../../environments/environment'; ...@@ -10,6 +9,7 @@ import { environment } from '../../../../environments/environment';
import { StorageKey } from '../../../lib/enums/enums'; import { StorageKey } from '../../../lib/enums/enums';
import { MessageProtocol } from '../../../lib/enums/Message'; import { MessageProtocol } from '../../../lib/enums/Message';
import { QuizState } from '../../../lib/enums/QuizState'; import { QuizState } from '../../../lib/enums/QuizState';
import { IHasTriggeredNavigation } from '../../../lib/interfaces/IHasTriggeredNavigation';
import { ILeaderBoardItem } from '../../../lib/interfaces/ILeaderboard'; import { ILeaderBoardItem } from '../../../lib/interfaces/ILeaderboard';
import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component'; import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component';
import { LeaderboardApiService } from '../../../service/api/leaderboard/leaderboard-api.service'; import { LeaderboardApiService } from '../../../service/api/leaderboard/leaderboard-api.service';
...@@ -26,9 +26,10 @@ import { QuizService } from '../../../service/quiz/quiz.service'; ...@@ -26,9 +26,10 @@ import { QuizService } from '../../../service/quiz/quiz.service';
templateUrl: './leaderboard.component.html', templateUrl: './leaderboard.component.html',
styleUrls: ['./leaderboard.component.scss'], styleUrls: ['./leaderboard.component.scss'],
}) })
export class LeaderboardComponent implements OnInit, OnDestroy { export class LeaderboardComponent implements OnInit, OnDestroy, IHasTriggeredNavigation {
public static TYPE = 'LeaderboardComponent'; public static TYPE = 'LeaderboardComponent';
public isLoadingData = true; public isLoadingData = true;
public hasTriggeredNavigation: boolean;
private _questionIndex: number; private _questionIndex: number;
private readonly _destroy = new Subject(); private readonly _destroy = new Subject();
...@@ -89,6 +90,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy { ...@@ -89,6 +90,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy {
} }
if (this.quizService.quiz.state === QuizState.Inactive) { if (this.quizService.quiz.state === QuizState.Inactive) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
return; return;
} }
...@@ -177,6 +179,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy { ...@@ -177,6 +179,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy {
this.headerLabelService.headerLabel = 'component.leaderboard.global_header'; this.headerLabelService.headerLabel = 'component.leaderboard.global_header';
this._questionIndex = null; this._questionIndex = null;
if (params['questionIndex']) { if (params['questionIndex']) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'leaderboard']); this.router.navigate(['/quiz', 'flow', 'leaderboard']);
return; return;
} }
...@@ -205,6 +208,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy { ...@@ -205,6 +208,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy {
sessionStorage.removeItem(StorageKey.CurrentQuestionIndex); sessionStorage.removeItem(StorageKey.CurrentQuestionIndex);
}), }),
this.messageQueue.subscribe(MessageProtocol.Start, payload => { this.messageQueue.subscribe(MessageProtocol.Start, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'voting']); this.router.navigate(['/quiz', 'flow', 'voting']);
}), this.messageQueue.subscribe(MessageProtocol.UpdatedResponse, payload => { }), this.messageQueue.subscribe(MessageProtocol.UpdatedResponse, payload => {
console.log('LeaderboardComponent: modify response data for nickname', payload.nickname); console.log('LeaderboardComponent: modify response data for nickname', payload.nickname);
...@@ -214,15 +218,16 @@ export class LeaderboardComponent implements OnInit, OnDestroy { ...@@ -214,15 +218,16 @@ export class LeaderboardComponent implements OnInit, OnDestroy {
}), this.messageQueue.subscribe(MessageProtocol.Reset, payload => { }), this.messageQueue.subscribe(MessageProtocol.Reset, payload => {
this.attendeeService.clearResponses(); this.attendeeService.clearResponses();
this.quizService.quiz.currentQuestionIndex = -1; this.quizService.quiz.currentQuestionIndex = -1;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'lobby']); this.router.navigate(['/quiz', 'flow', 'lobby']);
}), this.messageQueue.subscribe(MessageProtocol.Removed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Removed, payload => {
if (isPlatformBrowser(this.platformId)) { const existingNickname = sessionStorage.getItem(StorageKey.CurrentNickName);
const existingNickname = sessionStorage.getItem(StorageKey.CurrentNickName); if (existingNickname === payload.name) {
if (existingNickname === payload.name) { this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}
} }
}), this.messageQueue.subscribe(MessageProtocol.Closed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Closed, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}), }),
]); ]);
...@@ -234,6 +239,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy { ...@@ -234,6 +239,7 @@ export class LeaderboardComponent implements OnInit, OnDestroy {
]; ];
this.footerBarService.footerElemBack.onClickCallback = () => { this.footerBarService.footerElemBack.onClickCallback = () => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']); this.router.navigate(['/quiz', 'flow', 'results']);
}; };
......
...@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router'; ...@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
import { QRCodeModule } from 'angularx-qrcode'; import { QRCodeModule } from 'angularx-qrcode';
import { MarkdownModule } from 'ngx-markdown'; import { MarkdownModule } from 'ngx-markdown';
import { CasLoginService } from '../../service/login/cas-login.service'; import { CasLoginService } from '../../service/login/cas-login.service';
import { ShowUnloadWarningGuard } from '../../service/show-unload-warning-guard/show-unload-warning.guard';
import { SharedModule } from '../../shared/shared.module'; import { SharedModule } from '../../shared/shared.module';
import { ConfidenceRateComponent } from './confidence-rate/confidence-rate.component'; import { ConfidenceRateComponent } from './confidence-rate/confidence-rate.component';
import { LeaderboardComponent } from './leaderboard/leaderboard.component'; import { LeaderboardComponent } from './leaderboard/leaderboard.component';
...@@ -26,6 +27,7 @@ export const quizFlowRoutes: Routes = [ ...@@ -26,6 +27,7 @@ export const quizFlowRoutes: Routes = [
canLoad: [CasLoginService], canLoad: [CasLoginService],
component: QuizLobbyComponent, component: QuizLobbyComponent,
data: {}, data: {},
canDeactivate: [ShowUnloadWarningGuard],
}, { }, {
path: 'results', path: 'results',
component: QuizResultsComponent, component: QuizResultsComponent,
...@@ -46,14 +48,17 @@ export const quizFlowRoutes: Routes = [ ...@@ -46,14 +48,17 @@ export const quizFlowRoutes: Routes = [
path: 'voting', path: 'voting',
component: VotingComponent, component: VotingComponent,
data: {}, data: {},
canDeactivate: [ShowUnloadWarningGuard],
}, { }, {
path: 'reading-confirmation', path: 'reading-confirmation',
component: ReadingConfirmationComponent, component: ReadingConfirmationComponent,
data: {}, data: {},
canDeactivate: [ShowUnloadWarningGuard],
}, { }, {
path: 'confidence-rate', path: 'confidence-rate',
component: ConfidenceRateComponent, component: ConfidenceRateComponent,
data: {}, data: {},
canDeactivate: [ShowUnloadWarningGuard],
}, },
]; ];
......
import { isPlatformBrowser } from '@angular/common';
import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID, SecurityContext, TemplateRef } from '@angular/core'; import { Component, Inject, OnDestroy, OnInit, PLATFORM_ID, SecurityContext, TemplateRef } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
...@@ -14,6 +13,7 @@ import { UserRole } from '../../../lib/enums/UserRole'; ...@@ -14,6 +13,7 @@ import { UserRole } from '../../../lib/enums/UserRole';
import { FooterbarElement } from '../../../lib/footerbar-element/footerbar-element'; import { FooterbarElement } from '../../../lib/footerbar-element/footerbar-element';
import { IMessage } from '../../../lib/interfaces/communication/IMessage'; import { IMessage } from '../../../lib/interfaces/communication/IMessage';
import { IMemberSerialized } from '../../../lib/interfaces/entities/Member/IMemberSerialized'; import { IMemberSerialized } from '../../../lib/interfaces/entities/Member/IMemberSerialized';
import { IHasTriggeredNavigation } from '../../../lib/interfaces/IHasTriggeredNavigation';
import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component'; import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component';
import { MemberApiService } from '../../../service/api/member/member-api.service'; import { MemberApiService } from '../../../service/api/member/member-api.service';
import { QuizApiService } from '../../../service/api/quiz/quiz-api.service'; import { QuizApiService } from '../../../service/api/quiz/quiz-api.service';
...@@ -35,9 +35,11 @@ import { QrCodeContentComponent } from './modals/qr-code-content/qr-code-content ...@@ -35,9 +35,11 @@ import { QrCodeContentComponent } from './modals/qr-code-content/qr-code-content
templateUrl: './quiz-lobby.component.html', templateUrl: './quiz-lobby.component.html',
styleUrls: ['./quiz-lobby.component.scss'], styleUrls: ['./quiz-lobby.component.scss'],
}) })
export class QuizLobbyComponent implements OnInit, OnDestroy { export class QuizLobbyComponent implements OnInit, OnDestroy, IHasTriggeredNavigation {
public static TYPE = 'QuizLobbyComponent'; public static TYPE = 'QuizLobbyComponent';
public hasTriggeredNavigation: boolean;
private _nickToRemove: string; private _nickToRemove: string;
get nickToRemove(): string { get nickToRemove(): string {
...@@ -81,6 +83,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -81,6 +83,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
} }
if (this.quizService.quiz.state === QuizState.Inactive) { if (this.quizService.quiz.state === QuizState.Inactive) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
return; return;
} }
...@@ -200,6 +203,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -200,6 +203,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
this.memberApiService.deleteMember(this.quizService.quiz.name, this.attendeeService.ownNick).subscribe(); this.memberApiService.deleteMember(this.quizService.quiz.name, this.attendeeService.ownNick).subscribe();
this.attendeeService.cleanUp(); this.attendeeService.cleanUp();
this.connectionService.cleanUp(); this.connectionService.cleanUp();
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}; };
} }
...@@ -238,6 +242,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -238,6 +242,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
this.quizService.readingConfirmationRequested = environment.readingConfirmationEnabled ? data.step this.quizService.readingConfirmationRequested = environment.readingConfirmationEnabled ? data.step
=== MessageProtocol.ReadingConfirmationRequested === MessageProtocol.ReadingConfirmationRequested
: false; : false;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']); this.router.navigate(['/quiz', 'flow', 'results']);
self.isLoading = false; self.isLoading = false;
}); });
...@@ -252,6 +257,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -252,6 +257,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
this.quizService.close(); this.quizService.close();
this.attendeeService.cleanUp(); this.attendeeService.cleanUp();
this.connectionService.cleanUp(); this.connectionService.cleanUp();
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'manager', 'overview']); this.router.navigate(['/quiz', 'manager', 'overview']);
}).catch(() => {}); }).catch(() => {});
}; };
...@@ -273,6 +279,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -273,6 +279,7 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
}), this.messageQueue.subscribe(MessageProtocol.Start, payload => { }), this.messageQueue.subscribe(MessageProtocol.Start, payload => {
this.quizService.quiz.currentStartTimestamp = payload.currentStartTimestamp; this.quizService.quiz.currentStartTimestamp = payload.currentStartTimestamp;
}), this.messageQueue.subscribe(MessageProtocol.Closed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Closed, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}), }),
]); ]);
...@@ -295,21 +302,22 @@ export class QuizLobbyComponent implements OnInit, OnDestroy { ...@@ -295,21 +302,22 @@ export class QuizLobbyComponent implements OnInit, OnDestroy {
private handleMessagesForAttendee(): void { private handleMessagesForAttendee(): void {
this._messageSubscriptions.push(...[ this._messageSubscriptions.push(...[
this.messageQueue.subscribe(MessageProtocol.Start, payload => { this.messageQueue.subscribe(MessageProtocol.Start, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'voting']); this.router.navigate(['/quiz', 'flow', 'voting']);
}), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => { }), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => {
this.quizService.quiz.sessionConfig = payload.sessionConfig; this.quizService.quiz.sessionConfig = payload.sessionConfig;
}), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => { }), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => {
this.hasTriggeredNavigation = true;
if (environment.readingConfirmationEnabled) { if (environment.readingConfirmationEnabled) {
this.router.navigate(['/quiz', 'flow', 'reading-confirmation']); this.router.navigate(['/quiz', 'flow', 'reading-confirmation']);
} else { } else {
this.router.navigate(['/quiz', 'flow', 'voting']); this.router.navigate(['/quiz', 'flow', 'voting']);
} }
}), this.messageQueue.subscribe(MessageProtocol.Removed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Removed, payload => {
if (isPlatformBrowser(this.platformId)) { const existingNickname = sessionStorage.getItem(StorageKey.CurrentNickName);
const existingNickname = sessionStorage.getItem(StorageKey.CurrentNickName); if (existingNickname === payload.name) {
if (existingNickname === payload.name) { this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}
} }
}), }),
]); ]);
......
...@@ -11,6 +11,7 @@ import { RangedQuestionEntity } from '../../../../lib/entities/question/RangedQu ...@@ -11,6 +11,7 @@ import { RangedQuestionEntity } from '../../../../lib/entities/question/RangedQu
import { StorageKey } from '../../../../lib/enums/enums'; import { StorageKey } from '../../../../lib/enums/enums';
import { MessageProtocol } from '../../../../lib/enums/Message'; import { MessageProtocol } from '../../../../lib/enums/Message';
import { IMemberSerialized } from '../../../../lib/interfaces/entities/Member/IMemberSerialized'; import { IMemberSerialized } from '../../../../lib/interfaces/entities/Member/IMemberSerialized';
import { IHasTriggeredNavigation } from '../../../../lib/interfaces/IHasTriggeredNavigation';
import { ServerUnavailableModalComponent } from '../../../../modals/server-unavailable-modal/server-unavailable-modal.component'; import { ServerUnavailableModalComponent } from '../../../../modals/server-unavailable-modal/server-unavailable-modal.component';
import { AttendeeService } from '../../../../service/attendee/attendee.service'; import { AttendeeService } from '../../../../service/attendee/attendee.service';
import { ConnectionService } from '../../../../service/connection/connection.service'; import { ConnectionService } from '../../../../service/connection/connection.service';
...@@ -23,8 +24,9 @@ import { QuizService } from '../../../../service/quiz/quiz.service'; ...@@ -23,8 +24,9 @@ import { QuizService } from '../../../../service/quiz/quiz.service';
templateUrl: './question-details.component.html', templateUrl: './question-details.component.html',
styleUrls: ['./question-details.component.scss'], styleUrls: ['./question-details.component.scss'],
}) })
export class QuestionDetailsComponent implements OnInit, OnDestroy { export class QuestionDetailsComponent implements OnInit, OnDestroy, IHasTriggeredNavigation {
public static TYPE = 'QuestionDetailsComponent'; public static TYPE = 'QuestionDetailsComponent';
public hasTriggeredNavigation: boolean;
private _question: AbstractQuestionEntity; private _question: AbstractQuestionEntity;
...@@ -75,6 +77,11 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy { ...@@ -75,6 +77,11 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy {
footerBarService.replaceFooterElements([ footerBarService.replaceFooterElements([
this.footerBarService.footerElemBack, this.footerBarService.footerElemBack,
]); ]);
this.footerBarService.footerElemBack.onClickCallback = () => {
this.hasTriggeredNavigation = true;
history.back();
};
} }
public sanitizeHTML(value: string): string { public sanitizeHTML(value: string): string {
...@@ -121,6 +128,7 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy { ...@@ -121,6 +128,7 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy {
this._questionIndex = questionIndex; this._questionIndex = questionIndex;
if (this._questionIndex < 0 || this._questionIndex > this.quizService.quiz.currentQuestionIndex) { if (this._questionIndex < 0 || this._questionIndex > this.quizService.quiz.currentQuestionIndex) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'results']); this.router.navigate(['/quiz', 'flow', 'results']);
return; return;
} }
...@@ -136,6 +144,7 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy { ...@@ -136,6 +144,7 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy {
} }
public ngOnDestroy(): void { public ngOnDestroy(): void {
this.footerBarService.footerElemBack.restoreClickCallback();
this._messageSubscriptions.forEach(id => this.messageQueue.unsubscribe(id)); this._messageSubscriptions.forEach(id => this.messageQueue.unsubscribe(id));
this._destroy.next(); this._destroy.next();
this._destroy.complete(); this._destroy.complete();
...@@ -165,8 +174,10 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy { ...@@ -165,8 +174,10 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy {
}), this.messageQueue.subscribe(MessageProtocol.Reset, payload => { }), this.messageQueue.subscribe(MessageProtocol.Reset, payload => {
this.attendeeService.clearResponses(); this.attendeeService.clearResponses();
this.quizService.quiz.currentQuestionIndex = -1; this.quizService.quiz.currentQuestionIndex = -1;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'lobby']); this.router.navigate(['/quiz', 'flow', 'lobby']);
}), this.messageQueue.subscribe(MessageProtocol.Closed, payload => { }), this.messageQueue.subscribe(MessageProtocol.Closed, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
}), }),
]); ]);
...@@ -179,10 +190,12 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy { ...@@ -179,10 +190,12 @@ export class QuestionDetailsComponent implements OnInit, OnDestroy {
private handleMessagesForAttendee(): void { private handleMessagesForAttendee(): void {
this._messageSubscriptions.push(...[ this._messageSubscriptions.push(...[
this.messageQueue.subscribe(MessageProtocol.Start, payload => { this.messageQueue.subscribe(MessageProtocol.Start, payload => {
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'voting']); this.router.navigate(['/quiz', 'flow', 'voting']);
}), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => { }), this.messageQueue.subscribe(MessageProtocol.UpdatedSettings, payload => {
this.quizService.quiz.sessionConfig = payload.sessionConfig; this.quizService.quiz.sessionConfig = payload.sessionConfig;
}), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => { }), this.messageQueue.subscribe(MessageProtocol.ReadingConfirmationRequested, payload => {
this.hasTriggeredNavigation = true;
if (environment.readingConfirmationEnabled) { if (environment.readingConfirmationEnabled) {
this.router.navigate(['/quiz', 'flow', 'reading-confirmation']); this.router.navigate(['/quiz', 'flow', 'reading-confirmation']);
} else { } else {
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
<div *ngIf="showLeaderBoardButton(selectedQuestionIndex) || showQuestionButton(selectedQuestionIndex)" <div *ngIf="showLeaderBoardButton(selectedQuestionIndex) || showQuestionButton(selectedQuestionIndex)"
class="btn-group w-100"> class="btn-group w-100">
<button *ngIf="showLeaderBoardButton(selectedQuestionIndex)" <button *ngIf="showLeaderBoardButton(selectedQuestionIndex)"
(click)="hasTriggeredNavigation = true"
[routerLink]="['/quiz', 'flow', 'leaderboard', visibleQuestions.length > 1 ? selectedQuestionIndex : 'all']" [routerLink]="['/quiz', 'flow', 'leaderboard', visibleQuestions.length > 1 ? selectedQuestionIndex : 'all']"
class="btn btn-light w-100 cursor-pointer" class="btn btn-light w-100 cursor-pointer"
type="button"> type="button">
...@@ -89,6 +90,7 @@ ...@@ -89,6 +90,7 @@
<span>{{'component.liveResults.ranking' | translate}}</span> <span>{{'component.liveResults.ranking' | translate}}</span>
</button> </button>
<button *ngIf="showQuestionButton(selectedQuestionIndex)" <button *ngIf="showQuestionButton(selectedQuestionIndex)"
(click)="hasTriggeredNavigation = true"
[routerLink]="['/quiz', 'flow', 'results', selectedQuestionIndex]" [routerLink]="['/quiz', 'flow', 'results', selectedQuestionIndex]"
class="btn btn-light w-100 cursor-pointer" class="btn btn-light w-100 cursor-pointer"
type="button"> type="button">
......
...@@ -11,6 +11,7 @@ import { MessageProtocol, StatusProtocol } from '../../../lib/enums/Message'; ...@@ -11,6 +11,7 @@ import { MessageProtocol, StatusProtocol } from '../../../lib/enums/Message';
import { QuestionType } from '../../../lib/enums/QuestionType'; import { QuestionType } from '../../../lib/enums/QuestionType';
import { QuizState } from '../../../lib/enums/QuizState'; import { QuizState } from '../../../lib/enums/QuizState';
import { IMemberSerialized } from '../../../lib/interfaces/entities/Member/IMemberSerialized'; import { IMemberSerialized } from '../../../lib/interfaces/entities/Member/IMemberSerialized';
import { IHasTriggeredNavigation } from '../../../lib/interfaces/IHasTriggeredNavigation';
import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component'; import { ServerUnavailableModalComponent } from '../../../modals/server-unavailable-modal/server-unavailable-modal.component';
import { QuizApiService } from '../../../service/api/quiz/quiz-api.service'; import { QuizApiService } from '../../../service/api/quiz/quiz-api.service';
import { AttendeeService } from '../../../service/attendee/attendee.service'; import { AttendeeService } from '../../../service/attendee/attendee.service';
...@@ -28,8 +29,9 @@ import { ToLobbyConfirmComponent } from './modals/to-lobby-confirm/to-lobby-conf ...@@ -28,8 +29,9 @@ import { ToLobbyConfirmComponent } from './modals/to-lobby-confirm/to-lobby-conf
styleUrls: ['./quiz-results.component.scss'], styleUrls: ['./quiz-results.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class QuizResultsComponent implements OnInit, OnDestroy { export class QuizResultsComponent implements OnInit, OnDestroy, IHasTriggeredNavigation {
public static TYPE = 'QuizResultsComponent'; public static TYPE = 'QuizResultsComponent';
public hasTriggeredNavigation: boolean;
public countdown: number; public countdown: number;
public answers: Array<string> = []; public answers: Array<string> = [];
public showStartQuizButton: boolean; public showStartQuizButton: boolean;
...@@ -222,6 +224,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy { ...@@ -222,6 +224,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy {
} }
if (this.quizService.quiz.state === QuizState.Inactive) { if (this.quizService.quiz.state === QuizState.Inactive) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
return; return;
} }
...@@ -327,6 +330,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy { ...@@ -327,6 +330,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy {
return this.quizApiService.getQuizStatus(this.quizService.quiz.name).toPromise().then(currentStateData => { return this.quizApiService.getQuizStatus(this.quizService.quiz.name).toPromise().then(currentStateData => {
if (currentStateData.status !== StatusProtocol.Success) { if (currentStateData.status !== StatusProtocol.Success) {
this.hasTriggeredNavigation = true;
this.router.navigate(['/']); this.router.navigate(['/']);
return; return;
} }
...@@ -334,6 +338,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy { ...@@ -334,6 +338,7 @@ export class QuizResultsComponent implements OnInit, OnDestroy {
if (currentStateData.payload.state === QuizState.Active) { if (currentStateData.payload.state === QuizState.Active) {
this.attendeeService.clearResponses(); this.attendeeService.clearResponses();
this.quizService.quiz.currentQuestionIndex = -1; this.quizService.quiz.currentQuestionIndex = -1;
this.hasTriggeredNavigation = true;
this.router.navigate(['/quiz', 'flow', 'lobby']); this.router.navigate(['/quiz', 'flow', 'lobby']);