diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html index c2a0e4ddfb09780b81cddec0e1005495a6d66241..d783cc69d61bf0a78e80032c4e365964e614ba0f 100644 --- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html +++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.html @@ -2,17 +2,32 @@ <h2 class="oldtypo-h2">{{'room-page.bonus-token-header' | translate }}</h2> <h3 class="oldtypo-h3">»{{room.name}}«</h3> <h3 class="oldtypo-h3">{{ 'room-page.session-id' | translate}}: {{ room.shortId }}</h3> - <mat-divider></mat-divider> + <div> + <mat-form-field> + <input (focus)="eventService.makeFocusOnInputTrue()" + (blur)="eventService.makeFocusOnInputFalse()" + (keyup)="inputChanged($event)" + matInput + class="input-block" + type="text" + maxlength="14" + name="roomName" + aria-labelledby="room-name-input"/> + <mat-placeholder class="placeholder">{{ 'room-page.hint' | translate }}</mat-placeholder> + <mat-hint align="end" + class="count"><span aria-hidden="true">{{ value.length }} / 8</span></mat-hint> + </mat-form-field> + <button (click)="navToCommentByValue()" + matTooltip="{{ 'room-page.nav-to-comment' | translate }}" + mat-stroked-button> + Go to Question + </button> + </div> <div *ngIf="bonusTokens.length >= 1"> - <p> - <mat-form-field appearance="outline"> - <input matInput (keyup)="inputChanged($event)"> - <mat-hint>{{ 'room-page.hint' | translate}}</mat-hint> - </mat-form-field> - </p> <mat-list> - <mat-list-item *ngFor="let bonusToken of bonusTokens; let index = index"> - <p tabindex="0"> + <mat-list-item *ngFor="let bonusToken of bonusTokens; let index = index" + [appScrollIntoView]="valueEqual(bonusToken.token)"> + <p [ngClass]="{'selected': valueEqual(bonusToken.token)}" tabindex="0"> {{ bonusToken.token }} </p> <p> diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss index a5af15bbbd23e4df5a8eee8b813cb6d8b46fdaeb..58652948fdd0569f95d2160f2cced217fe483f8e 100644 --- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss +++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.scss @@ -1,6 +1,6 @@ p { color: var(--on-surface); - margin: 10px 0 10px 0; + margin-right: 30px; } .delete-icon { @@ -20,3 +20,11 @@ p { background-color: var(--alt-dialog); } } + +.mat-stroked-button { + margin-left: 30px +} + +.selected { + color: var(--red); +} diff --git a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts index 10885592bbd733d41bf94ea12938efba87417401..ce5f9ed8ee4d5725f8fa2fb353e1133e8310b6fb 100644 --- a/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts +++ b/src/app/components/creator/_dialogs/bonus-token/bonus-token.component.ts @@ -1,4 +1,4 @@ -import {Component, OnDestroy, OnInit, QueryList, ViewChild, ViewChildren} from '@angular/core'; +import { Component, OnDestroy, OnInit } from '@angular/core'; import { BonusTokenService } from '../../../../services/http/bonus-token.service'; import { BonusToken } from '../../../../models/bonus-token'; import { Room } from '../../../../models/room'; @@ -11,6 +11,7 @@ import { Router } from '@angular/router'; import { Subject, Subscription } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { isNumeric } from 'rxjs/internal-compatibility'; +import { EventService } from '../../../../services/util/event.service'; @Component({ selector: 'app-bonus-token', @@ -18,6 +19,8 @@ import { isNumeric } from 'rxjs/internal-compatibility'; styleUrls: ['./bonus-token.component.scss'] }) export class BonusTokenComponent implements OnInit, OnDestroy { + value: any = ''; + valid = false; room: Room; bonusTokens: BonusToken[] = []; lang: string; @@ -27,6 +30,7 @@ export class BonusTokenComponent implements OnInit, OnDestroy { constructor(private bonusTokenService: BonusTokenService, public dialog: MatDialog, + public eventService: EventService, protected router: Router, private dialogRef: MatDialogRef<RoomCreatorPageComponent>, private translationService: TranslateService, @@ -42,8 +46,8 @@ export class BonusTokenComponent implements OnInit, OnDestroy { .pipe( debounceTime(this.debounceTime), ) - .subscribe(value => { - this.inputToken(value); + .subscribe(_ => { + this.inputToken(); }); } @@ -100,6 +104,20 @@ export class BonusTokenComponent implements OnInit, OnDestroy { this.router.navigate([commentURL]); } + navToCommentByValue() { + if(this.valid) { + this.bonusTokens.map(b => { + if(b.token === this.value) { + this.navToComment(b.commentId); + } + }); + } else { + this.translationService.get('token-validator.cant-find-comment').subscribe(msg => { + this.notificationService.show(msg); + }); + } + } + /** * Returns a lambda which closes the dialog on call. */ @@ -107,34 +125,39 @@ export class BonusTokenComponent implements OnInit, OnDestroy { return () => this.dialogRef.close(); } - inputToken(input: any) { - const index = this.validateTokenInput(input); - if(index !== -1) { + inputChanged(event: any) { + event.cancelBubble = true; + this.value = event.target.value; + this.modelChanged.next(event); + } + + inputToken() { + const index = this.validateTokenInput(this.value); + if(index) { this.translationService.get('token-validator.valid').subscribe(msg => { this.notificationService.show(msg); }); + this.valid = true; } else { this.translationService.get('token-validator.invalid').subscribe(msg => { this.notificationService.show(msg); }); + this.valid = false; } } validateTokenInput(input: any) { - let ind = -1; if(input.length === 8 && isNumeric(input)) { - this.bonusTokens.map((c, index) => { + return this.bonusTokens.map((c, index) => { if (c.token === input) { - ind = index; + return index; } }); } - return ind; } - inputChanged(event: any) { - event.cancelBubble = true; - this.modelChanged.next(event.target.value); + valueEqual(token: string) { + return token.trim() === this.value; } ngOnDestroy(): void { diff --git a/src/app/components/creator/creator.module.ts b/src/app/components/creator/creator.module.ts index b876aea134afe3d6bebcb146b45e339e0cf7881c..6d5670cf1401e205997d36e95f3c918beb64e785 100644 --- a/src/app/components/creator/creator.module.ts +++ b/src/app/components/creator/creator.module.ts @@ -25,6 +25,7 @@ import { ArsModule } from '../../../../projects/ars/src/lib/ars.module'; import { MatRippleModule } from '@angular/material/core'; import { ProfanitySettingsComponent } from './_dialogs/profanity-settings/profanity-settings.component'; import { RoomDescriptionSettingsComponent } from './_dialogs/room-description-settings/room-description-settings.component'; +import { ScrollIntoViewDirective } from '../../directives/scroll-into-view.directive'; @NgModule({ imports: [ @@ -60,7 +61,8 @@ import { RoomDescriptionSettingsComponent } from './_dialogs/room-description-se DeleteAnswerComponent, QuestionWallComponent, ProfanitySettingsComponent, - RoomDescriptionSettingsComponent + RoomDescriptionSettingsComponent, + ScrollIntoViewDirective ], exports: [] }) diff --git a/src/app/directives/scroll-into-view.directive.spec.ts b/src/app/directives/scroll-into-view.directive.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..361f509a76fbcbb3d4eccd568c3c478cf131dd84 --- /dev/null +++ b/src/app/directives/scroll-into-view.directive.spec.ts @@ -0,0 +1,9 @@ +/*import { ScrollIntoViewDirective } from './scroll-into-view.directive'; + +describe('ScrollIntoViewDirective', () => { + it('should create an instance', () => { + const directive = new ScrollIntoViewDirective(); + expect(directive).toBeTruthy(); + }); +}); + */ diff --git a/src/app/directives/scroll-into-view.directive.ts b/src/app/directives/scroll-into-view.directive.ts new file mode 100644 index 0000000000000000000000000000000000000000..642b24a339ea6861019136102f8b3b930359a0de --- /dev/null +++ b/src/app/directives/scroll-into-view.directive.ts @@ -0,0 +1,18 @@ +import { Directive, ElementRef, Input } from '@angular/core'; + +@Directive({ + selector: '[appScrollIntoView]' +}) +export class ScrollIntoViewDirective { + + @Input('appScrollIntoView') + set active(value: boolean) { + if (value) { + this.element.nativeElement.scrollIntoView({ behavior: 'smooth' }); + } + } + + constructor(private element: ElementRef) { + } + +} diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json index 9dc90c65725f5e63b0059cfe5d8d87770a257574..ea5bb193961e54e42bad387305e85997b06f591c 100644 --- a/src/assets/i18n/creator/de.json +++ b/src/assets/i18n/creator/de.json @@ -513,6 +513,7 @@ }, "token-validator": { "valid": "VALID", - "invalid": "INVALID" + "invalid": "INVALID", + "cant-find-comment": "Die Frage kann nicht gefunden werden" } } diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json index ca7f32f17bd20fccef5c1eefaed36ce99a1da9dd..21fd59cc129b39ea370eafeeb50ca520b46d40c8 100644 --- a/src/assets/i18n/creator/en.json +++ b/src/assets/i18n/creator/en.json @@ -511,6 +511,7 @@ }, "token-validator": { "valid": "VALID", - "invalid": "INVALID" + "invalid": "INVALID", + "cant-find-comment": "Can't find comment" } }