From 993703012f86ec3ffd89686dbb3a03a24432aac7 Mon Sep 17 00:00:00 2001
From: Andre Lammers <andre.lammers@mni.thm.de>
Date: Tue, 17 Sep 2019 11:54:05 +0200
Subject: [PATCH] Added extended live-announcer function for all sites (hidden
 button)

home-page, all room-pages, comment-page, moderation-page, user-page
---
 .../home/user-home/user-home.component.html   |  1 +
 .../home/user-home/user-home.component.ts     | 10 +++++---
 .../moderator-comment-page.component.html     |  6 ++---
 .../moderator-comment-page.component.ts       | 21 ++++++++++++++---
 .../room-moderator-page.component.html        |  3 ++-
 .../room-moderator-page.component.ts          | 23 +++++++++++++++----
 .../room-participant-page.component.html      |  1 +
 .../room-participant-page.component.ts        | 13 +++++++----
 .../comment-page/comment-page.component.html  |  1 +
 .../comment-page/comment-page.component.ts    | 10 +++++---
 src/assets/i18n/creator/de.json               |  4 +++-
 src/assets/i18n/creator/en.json               |  4 +++-
 src/assets/i18n/home/de.json                  |  1 +
 src/assets/i18n/home/en.json                  |  1 +
 src/assets/i18n/participant/de.json           |  2 ++
 src/assets/i18n/participant/en.json           |  2 ++
 16 files changed, 79 insertions(+), 24 deletions(-)

diff --git a/src/app/components/home/user-home/user-home.component.html b/src/app/components/home/user-home/user-home.component.html
index 91368fa40..ed885a33c 100644
--- a/src/app/components/home/user-home/user-home.component.html
+++ b/src/app/components/home/user-home/user-home.component.html
@@ -12,5 +12,6 @@
   <div fxLayout="row" fxLayoutAlign="center" fxLayoutGap="15px">
     <app-room-list [user]="user"></app-room-list>
   </div>
+  <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'home-page.live-announcer-user' | translate }}</button>
 </div>
 
diff --git a/src/app/components/home/user-home/user-home.component.ts b/src/app/components/home/user-home/user-home.component.ts
index 441d46319..0a1769e1a 100644
--- a/src/app/components/home/user-home/user-home.component.ts
+++ b/src/app/components/home/user-home/user-home.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy, Renderer2 } from '@angular/core';
+import { Component, OnInit, OnDestroy, Renderer2, AfterContentInit } from '@angular/core';
 import { MatDialog } from '@angular/material';
 import { TranslateService } from '@ngx-translate/core';
 import { LanguageService } from '../../../services/util/language.service';
@@ -16,7 +16,7 @@ import { KeyboardKey } from '../../../utils/keyboard/keys';
   templateUrl: './user-home.component.html',
   styleUrls: [ './user-home.component.scss' ]
 })
-export class UserHomeComponent implements OnInit, OnDestroy {
+export class UserHomeComponent implements OnInit, OnDestroy, AfterContentInit {
   user: User;
   creatorRole: UserRole = UserRole.CREATOR;
   participantRole: UserRole = UserRole.PARTICIPANT;
@@ -35,10 +35,14 @@ export class UserHomeComponent implements OnInit, OnDestroy {
     langService.langEmitter.subscribe(lang => translateService.use(lang));
   }
 
+  ngAfterContentInit(): void {
+    setTimeout( () => {
+      document.getElementById('live_announcer-button').focus();
+    }, 700);
+  }
   ngOnInit() {
     this.translateService.use(localStorage.getItem('currentLang'));
     this.authenticationService.watchUser.subscribe(newUser => this.user = newUser);
-    this.announce();
     this.listenerFn = this._r.listen(document, 'keyup', (event) => {
       if (KeyboardUtils.isKeyEvent(event, KeyboardKey.Digit1) === true && this.eventService.focusOnInput === false) {
         document.getElementById('session_id-input').focus();
diff --git a/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.html b/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.html
index 7bf34b687..8777583be 100644
--- a/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.html
+++ b/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.html
@@ -2,6 +2,6 @@
     <div fxLayout="row" fxLayoutAlign="center">
       <app-moderator-comment-list [user]="user" [roomId]="roomId" comments></app-moderator-comment-list>
     </div>
-  </div>
-  
-  
\ No newline at end of file
+  <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'comment-page.live-announcer-moderation' | translate }}</button>
+</div>
+
diff --git a/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.ts b/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.ts
index c657955ae..4dc7a408a 100644
--- a/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.ts
+++ b/src/app/components/moderator/moderator-comment-page/moderator-comment-page.component.ts
@@ -1,25 +1,40 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, AfterContentInit, Renderer2 } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { User } from '../../../models/user';
 import { NotificationService } from '../../../services/util/notification.service';
 import { AuthenticationService } from '../../../services/http/authentication.service';
+import { LiveAnnouncer } from '@angular/cdk/a11y';
+import { EventService } from '../../../services/util/event.service';
 
 @Component({
   selector: 'app-moderator-comment-page',
   templateUrl: './moderator-comment-page.component.html',
   styleUrls: ['./moderator-comment-page.component.scss']
 })
-export class ModeratorCommentPageComponent implements OnInit {
+export class ModeratorCommentPageComponent implements OnInit, AfterContentInit {
   roomId: string;
   user: User;
 
   constructor(private route: ActivatedRoute,
               private notification: NotificationService,
-              private authenticationService: AuthenticationService) { }
+              private authenticationService: AuthenticationService,
+              private liveAnnouncer: LiveAnnouncer,
+              private _r: Renderer2,
+              public eventService: EventService) { }
 
+  ngAfterContentInit(): void {
+    setTimeout( () => {
+      document.getElementById('live_announcer-button').focus();
+    }, 500);
+  }
   ngOnInit(): void {
     this.roomId = localStorage.getItem('roomId');
     this.user = this.authenticationService.getUser();
   }
 
+  public announce() {
+    this.liveAnnouncer.clear();
+    this.liveAnnouncer.announce('', 'assertive');
+  }
+
 }
diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
index 66fa3bc4c..77c3d19ff 100644
--- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
+++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.html
@@ -57,4 +57,5 @@
       </mat-card>
 
     </div>
-  </div>
+  <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'room-page.live-announcer' | translate }}</button>
+</div>
diff --git a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
index b123e904f..7515c835c 100644
--- a/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
+++ b/src/app/components/moderator/room-moderator-page/room-moderator-page.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, AfterContentInit, Renderer2 } from '@angular/core';
 import { Room } from '../../../models/room';
 import { RoomPageComponent } from '../../shared/room-page/room-page.component';
 import { Location } from '@angular/common';
@@ -10,13 +10,15 @@ import { WsCommentServiceService } from '../../../services/websockets/ws-comment
 import { CommentService } from '../../../services/http/comment.service';
 import { Message } from '@stomp/stompjs';
 import { NotificationService } from '../../../services/util/notification.service';
+import { LiveAnnouncer } from '@angular/cdk/a11y';
+import { EventService } from '../../../services/util/event.service';
 
 @Component({
   selector: 'app-room-moderator-page',
   templateUrl: './room-moderator-page.component.html',
   styleUrls: ['./room-moderator-page.component.scss']
 })
-export class RoomModeratorPageComponent extends RoomPageComponent implements OnInit {
+export class RoomModeratorPageComponent extends RoomPageComponent implements OnInit, AfterContentInit {
 
   room: Room;
   isLoading = true;
@@ -24,7 +26,6 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI
   moderatorCommentCounter: number;
   viewModuleCount = 1;
 
-
   constructor(protected location: Location,
               protected roomService: RoomService,
               protected route: ActivatedRoute,
@@ -32,7 +33,10 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI
               protected langService: LanguageService,
               protected wsCommentService: WsCommentServiceService,
               protected commentService: CommentService,
-              protected notification: NotificationService) {
+              protected notification: NotificationService,
+              private liveAnnouncer: LiveAnnouncer,
+              private _r: Renderer2,
+              public eventService: EventService) {
     super(roomService, route, location, wsCommentService, commentService);
     langService.langEmitter.subscribe(lang => translateService.use(lang));
   }
@@ -83,6 +87,12 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI
     });
   }
 
+  ngAfterContentInit(): void {
+    setTimeout( () => {
+      document.getElementById('live_announcer-button').focus();
+    }, 700);
+  }
+
   ngOnInit() {
     window.scroll(0, 0);
     this.route.params.subscribe(params => {
@@ -107,4 +117,9 @@ export class RoomModeratorPageComponent extends RoomPageComponent implements OnI
       this.notification.show(msg, '', { duration: 2000 });
     });
   }
+
+  public announce() {
+    this.liveAnnouncer.clear();
+    this.liveAnnouncer.announce('', 'assertive');
+  }
 }
diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.html b/src/app/components/participant/room-participant-page/room-participant-page.component.html
index a34bbfaca..1fb712bf0 100644
--- a/src/app/components/participant/room-participant-page/room-participant-page.component.html
+++ b/src/app/components/participant/room-participant-page/room-participant-page.component.html
@@ -48,6 +48,7 @@
     </mat-card>
 
   </div>
+  <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'room-page.live-announcer' | translate }}</button>
 </div>
 
 <!--Hidden Div's for a11y-Descriptions-->
diff --git a/src/app/components/participant/room-participant-page/room-participant-page.component.ts b/src/app/components/participant/room-participant-page/room-participant-page.component.ts
index 71705d561..78912bb65 100644
--- a/src/app/components/participant/room-participant-page/room-participant-page.component.ts
+++ b/src/app/components/participant/room-participant-page/room-participant-page.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy, Renderer2 } from '@angular/core';
+import { Component, OnInit, OnDestroy, Renderer2, AfterContentInit } from '@angular/core';
 import { Room } from '../../../models/room';
 import { User } from '../../../models/user';
 import { UserRole } from '../../../models/user-roles.enum';
@@ -21,7 +21,7 @@ import { KeyboardKey } from '../../../utils/keyboard/keys';
   templateUrl: './room-participant-page.component.html',
   styleUrls: ['./room-participant-page.component.scss']
 })
-export class RoomParticipantPageComponent extends RoomPageComponent implements OnInit, OnDestroy {
+export class RoomParticipantPageComponent extends RoomPageComponent implements OnInit, OnDestroy, AfterContentInit {
 
   room: Room;
   isLoading = true;
@@ -45,14 +45,18 @@ export class RoomParticipantPageComponent extends RoomPageComponent implements O
     langService.langEmitter.subscribe(lang => translateService.use(lang));
   }
 
+  ngAfterContentInit(): void {
+    setTimeout( () => {
+      document.getElementById('live_announcer-button').focus();
+    }, 700);
+  }
+
   ngOnInit() {
     window.scroll(0, 0);
     this.route.params.subscribe(params => {
       this.initializeRoom(params['roomId']);
     });
     this.translateService.use(localStorage.getItem('currentLang'));
-    this.announce();
-
     this.listenerFn = this._r.listen(document, 'keyup', (event) => {
       if (KeyboardUtils.isKeyEvent(event, KeyboardKey.Digit1) === true && this.eventService.focusOnInput === false) {
         document.getElementById('question_answer-button').focus();
@@ -76,7 +80,6 @@ export class RoomParticipantPageComponent extends RoomPageComponent implements O
   }
 
   public announce() {
-    // this.liveAnnouncer.announce('Willkommen auf dieser Seite' + document.getElementById('announcer_text').textContent, 'assertive');
     this.liveAnnouncer.clear();
     this.liveAnnouncer.announce('Du befindest dich in der Sitzung mit dem von dir eingegebenen Sitzungs-Code. ' +
       'Drücke die Taste 1 um eine Frage zu stellen, die Taste 2 für das Sitzungs-Menü, ' +
diff --git a/src/app/components/shared/comment-page/comment-page.component.html b/src/app/components/shared/comment-page/comment-page.component.html
index 6f6989296..091077689 100644
--- a/src/app/components/shared/comment-page/comment-page.component.html
+++ b/src/app/components/shared/comment-page/comment-page.component.html
@@ -1,6 +1,7 @@
 <div fxLayout="column" fxLayoutAlign="center" fxLayoutGap="20px">
   <div fxLayout="row" fxLayoutAlign="center">
     <app-comment-list [user]="user" [roomId]="roomId" comments></app-comment-list>
+    <button id="live_announcer-button" tabIndex="-1" (click)="announce()" class="visually-hidden">{{ 'comment-page.live-announcer' | translate }}</button>
   </div>
 </div>
 
diff --git a/src/app/components/shared/comment-page/comment-page.component.ts b/src/app/components/shared/comment-page/comment-page.component.ts
index 4a12619d9..d9bb46b0e 100644
--- a/src/app/components/shared/comment-page/comment-page.component.ts
+++ b/src/app/components/shared/comment-page/comment-page.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit, OnDestroy, Renderer2 } from '@angular/core';
+import { Component, OnInit, OnDestroy, Renderer2, AfterContentInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { User } from '../../../models/user';
 import { NotificationService } from '../../../services/util/notification.service';
@@ -14,7 +14,7 @@ import { Room } from '../../../models/room';
   templateUrl: './comment-page.component.html',
   styleUrls: ['./comment-page.component.scss']
 })
-export class CommentPageComponent implements OnInit, OnDestroy {
+export class CommentPageComponent implements OnInit, OnDestroy, AfterContentInit {
   roomId: string;
   room: Room;
   user: User;
@@ -28,10 +28,14 @@ export class CommentPageComponent implements OnInit, OnDestroy {
               private liveAnnouncer: LiveAnnouncer,
               private _r: Renderer2) { }
 
+  ngAfterContentInit(): void {
+    setTimeout( () => {
+      document.getElementById('live_announcer-button').focus();
+    }, 500);
+  }
   ngOnInit(): void {
     this.roomId = localStorage.getItem('roomId');
     this.user = this.authenticationService.getUser();
-    this.announce();
     this.listenerFn = this._r.listen(document, 'keyup', (event) => {
       if (KeyboardUtils.isKeyEvent(event, KeyboardKey.Digit1) === true && this.eventService.focusOnInput === false) {
         if (document.getElementById('add_comment-button')) {
diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json
index bf4e816db..b2bc08d4b 100644
--- a/src/assets/i18n/creator/de.json
+++ b/src/assets/i18n/creator/de.json
@@ -61,6 +61,8 @@
     "error-title": "Bitte gib einen Titel ein.",
     "export": "Exportieren",
     "export-description": "Exportieren",
+    "live-announcer": "Du befindest dich jetzt auf der Fragen-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
+    "live-announcer-moderation": "Du befindest dich jetzt auf der Moderations-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "mark-correct": "Frage bejahen",
     "mark-favorite": "Als Kandidat für einen Bonus markieren",
     "mark-not-correct": "Frage nicht bejahen",
@@ -158,7 +160,7 @@
     "email-error": "E-Mail Adresse ist ungültig.",
     "export-comments": "Fragen exportieren",
     "general": "Sitzung",
-    "live-announcer": "Du befindest dich in der von dir erstellten Sitzung. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
+    "live-announcer": "Du befindest dich jetzt in der Sitzung. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "live-feedback": "Live Feedback",
     "moderating-stream": "Moderation",
     "moderator-added": "Moderator wurde hinzugefügt.",
diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json
index 7c50db68d..1318ed43e 100644
--- a/src/assets/i18n/creator/en.json
+++ b/src/assets/i18n/creator/en.json
@@ -62,6 +62,8 @@
     "error-title": "Please enter a title.",
     "export": "Export",
     "export-description": "Export",
+    "live-announcer": "You are now on the questions page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
+    "live-announcer-moderation": "You are now on the moderation page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "mark-correct": "Mark as correct",
     "mark-favorite": "Mark as bonus question",
     "mark-not-correct": "Mark not as correct",
@@ -159,7 +161,7 @@
     "email-error": "E-Mail is invalid.",
     "export-comments": "Export questions",
     "general": "Session",
-    "live-announcer": "You're in the session you created. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
+    "live-announcer": "You're in the session now. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "live-feedback": "Live feedback",
     "moderating-stream": "Moderation",
     "moderator-added": "Moderator was added.",
diff --git a/src/assets/i18n/home/de.json b/src/assets/i18n/home/de.json
index 209cb5a25..6bf7166ae 100644
--- a/src/assets/i18n/home/de.json
+++ b/src/assets/i18n/home/de.json
@@ -82,6 +82,7 @@
     "created-2": "' wurde erstellt.",
     "exactly-8": "Der Sitzungs-Code ist eine Kombination aus genau 8 Ziffern.",
     "live-announcer": "Willkommen auf der Seite fragpunktjetzt. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
+    "live-announcer-user": "Du befindest dich jetzt auf der Benutzer-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "install": "Installieren",
     "no-empty-name": "Bitte gib einen Namen für die Sitzung ein.",
     "no-room-found": "Es wurde keine Sitzung mit diesem Code gefunden.",
diff --git a/src/assets/i18n/home/en.json b/src/assets/i18n/home/en.json
index 5aaa64fcf..23061d43e 100644
--- a/src/assets/i18n/home/en.json
+++ b/src/assets/i18n/home/en.json
@@ -83,6 +83,7 @@
     "created-2": "' successfully created",
     "exactly-8": "A session ID has exactly 8 digits.",
     "live-announcer": "Welcome to fragpunktjetzt. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
+    "live-announcer-user": "You are now on the user page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "install": "Install",
     "no-empty-name": "Please enter a name.",
     "no-room-found": "No session found with this key",
diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json
index 4306a30c3..f9ac08f72 100644
--- a/src/assets/i18n/participant/de.json
+++ b/src/assets/i18n/participant/de.json
@@ -58,6 +58,7 @@
     "error-both-fields": "Bitte fülle alle Felder aus.",
     "error-comment": "Bitte gib deine Frage ein.",
     "error-title": "Bitte gib einen Titel ein.",
+    "live-announcer": "Du befindest dich jetzt auf der Fragen-Seite. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "mark-not-correct": "Dozent hat die Frage bejaht.",
     "mark-not-favorite": "Bonus-Frage: Dozent hält die Frage für besonders interessant.",
     "mark-not-wrong": "Dozent hat die Frage verneint",
@@ -85,6 +86,7 @@
     "description": "Beschreibung der Sitzung",
     "give-feedback": "Feedback geben",
     "learn": "Lernen",
+    "live-announcer": "Du befindest dich jetzt in der Sitzung. Um Informationen zu Tastenkombinationen zu erhalten drücke jetzt die Enter-Taste oder rufe die Ansage zu einem späteren Zeitpunkt mit der Escape-Taste auf.",
     "live-feedback": "Live Feedback",
     "session-id": "Code"
   },
diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json
index 079ea15c7..acc3ee0ce 100644
--- a/src/assets/i18n/participant/en.json
+++ b/src/assets/i18n/participant/en.json
@@ -58,6 +58,7 @@
     "error-both-fields": "Please fill in all fields.",
     "error-comment": "Please enter a question.",
     "error-title": "Please enter a title.",
+    "live-announcer": "You are now on the questions page. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "mark-not-correct": "Marked as correct by the professor",
     "mark-not-favorite": "Bonus question: Your professor intends to give a bonus for that question.",
     "mark-not-wrong": "Marked as wrong by the professor",
@@ -85,6 +86,7 @@
     "description": "Description",
     "give-feedback": "Give feedback",
     "learn": "Learn",
+    "live-announcer": "You're in the session now. To get information about key combinations press the Enter key or call the announcement later with the Escape key.",
     "live-feedback": "Live feedback",
     "session-id": "Key"
   },
-- 
GitLab