diff --git a/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.html b/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.html index 6dbc74306383aaa6efc4216ee6c449c3b38ceaa9..4245e8f80c31ded7808253d5c733860f2aa7cd51 100644 --- a/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.html +++ b/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.html @@ -1 +1,3 @@ +<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> +<link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap" rel="stylesheet"> <ng-content></ng-content> diff --git a/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.scss b/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.scss index 78bec6c4e8a37495630dc6b64d81277160eab4ad..b004ebb98a542a31d5c5e7ad0b21bf0c0a349875 100644 --- a/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.scss +++ b/projects/ars/src/lib/components/style/menu/material-btn/material-btn.component.scss @@ -1,39 +1,57 @@ +:host ::ng-deep { -:host ::ng-deep{ - - p,h1,h2,h3,h4,h5{ - padding:0; - margin:0; + p, h1, h2, h3, h4, h5 { + padding: 0; + margin: 0; + font-family:Roboto, 'sans-serif'; } button{ - padding:0; - margin:0; background-color:transparent; border:none; outline:none; cursor:pointer; + float:left; + } + + button > *{ + float:left; + cursor:pointer; + } + + button:focus-visible > *:first-child{ + outline:red 2px solid; + outline-offset:2px; } - button:focus-visible>*{ - outline:2px solid red; - outline-offset:5px; + ars-col > button > p{ + text-transform:uppercase; + font-weight:500; + font-size:14px; + line-height:18px; + padding-top:1px; + padding-bottom:3px; + color:var(--ars-button-color); } - ars-col>button p{ - text-transform: uppercase; + ars-row > button > p{ + font-weight:500; + font-size:14px; + line-height:14px; } - ars-row>button p{ + button > *:nth-child(2){ + margin-left:12px; } - button p{ - font-family: Roboto, 'sans-serif'; - font-weight: 500; - text-decoration: none; - color: var(--ars-button-color); - text-align: left; + button > i{ + font-family:'Material Icons', serif; + font-weight:normal; + font-style:normal; + font-size:18px; + line-height:18px; + color:var(--ars-button-color); } } diff --git a/projects/ars/src/lib/style/style.const.ts b/projects/ars/src/lib/style/style.const.ts index 8b955aec33ffb630c600c2c6351656e352bd0aec..411ba85e62351b000ddf2642cd1ff0ac70387473 100644 --- a/projects/ars/src/lib/style/style.const.ts +++ b/projects/ars/src/lib/style/style.const.ts @@ -1,6 +1,6 @@ export const light = { 'ars-header-color': '#212121', - 'ars-paragraph-color': '#616161', + 'ars-paragraph-color': '#3f3f3f', 'ars-button-color': '#000000', 'ars-background-color': '#fcfcfc', 'ars-foreground-color': '#FFFFFF', diff --git a/src/app/components/shared/header/header.component.html b/src/app/components/shared/header/header.component.html index 1a3e6f2aaf49bb32db6d9aac2b641bb36ca4adec..51e6f2ef593c2f40746d05d28ab158219bfcf793 100644 --- a/src/app/components/shared/header/header.component.html +++ b/src/app/components/shared/header/header.component.html @@ -14,7 +14,7 @@ {{cTime}} </h2> <span class="fill-remaining-space"></span> - <button *ngIf="router.url.includes('comments')" mat-button routerLink="participant/room/{{shortId}}/questionwall"> + <button *ngIf="router.url.includes('comments')" mat-button routerLink="participant/room/{{shortId}}/comments/questionwall"> <span>Presentation</span> </button> <span class="fill-remaining-space" diff --git a/src/app/components/shared/questionwall/QuestionWallComment.ts b/src/app/components/shared/questionwall/QuestionWallComment.ts index 62e739f448b910b664107b3db070354e14e57514..71241b5a936a9583a2fc77e73ccde844316d94db 100644 --- a/src/app/components/shared/questionwall/QuestionWallComment.ts +++ b/src/app/components/shared/questionwall/QuestionWallComment.ts @@ -2,9 +2,48 @@ import { Comment } from '../../../models/comment'; export class QuestionWallComment { + public date: Date; + public timeAgo: string; + constructor( public comment: Comment, public old: boolean - ) {} + ) { + this.date = new Date(comment.timestamp); + this.updateTimeAgo(); + } + + public update() { + console.log('update'); + } + + public updateTimeAgo() { + const seconds = Math.floor((new Date().getTime() - this.date.getTime()) / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + const months = Math.floor(days / 30); + const years = Math.floor(months / 12); + if (this.setTimeAgo(years, 'year')) {return; } + if (this.setTimeAgo(months, 'month')) {return; } + if (this.setTimeAgo(days, 'day')) {return; } + if (this.setTimeAgo(hours, 'hour')) {return; } + if (this.setTimeAgo(minutes, 'minute')) {return; } + if (this.setTimeAgo(seconds, 'second')) {return; } + this.timeAgo = '1 second ago'; + } + + private setTimeAgo(time: number, name: string): boolean { + if (time > 0) { + if (time === 1) { + this.timeAgo = time + ' ' + name + ' ago'; + } else { + this.timeAgo = time + ' ' + name + 's ago'; + } + return true; + } else { + return false; + } + } } diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.html b/src/app/components/shared/questionwall/question-wall/question-wall.component.html index 7f5008400f2754839d558ca2bfec5b7008cc0ec6..c5c89f3c4a79f397108b14116d3d4e2749d29b81 100644 --- a/src/app/components/shared/questionwall/question-wall/question-wall.component.html +++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.html @@ -1,9 +1,10 @@ <ars-screen ars-flex-box class="questionwall-screen"> <ars-row [height]="50" class="questionwall-header"> <ars-style-btn-material *ngIf="room" style="width:100%;height:100%;" ars-flex-box> - <ars-col ars-btn-wrp [xp]="16" [extra]="true"> - <button ars-btn routerLink="/participant/room/{{room.shortId}}/comments"><p>BACK</p></button> + <ars-col ars-btn-wrp [xp]="16" [yp]="0" [extra]="true"> + <button ars-btn (click)="leave()"><i>arrow_back</i></button> </ars-col> + <ars-fill></ars-fill> </ars-style-btn-material> </ars-row> <ars-fill ars-flex-box> @@ -13,34 +14,61 @@ <p class="questionwall-present" *ngIf="!commentFocus">Questionwall. Click on a comment.</p> </ars-row> </ars-fill> - <ars-col [width]="450" [overflow]="'auto'" class="questionwall-comment-list" #colComponent> + <ars-col [width]="450" [overflow]="'auto'" class="questionwall-list" #colComponent> <ars-row *ngFor="let comment of comments" class="questionwall-comment-anchor"> - <div class="questionwall-comment"> - <div class="questionwall-comment-box" (click)="focusComment(comment)" - [style.box-shadow]="commentFocus===comment?'inset 0px 0px 0px 1px var(--ars-paragraph-color)':null"> - <p class="questionwall-comment-box-user">User: {{comment.comment.creatorId.substring(0,4)}}</p> - <p class="questionwall-comment-box-time">Time: {{comment.comment.timestamp}}</p> - <p class="questionwall-comment-box-time" [style.color]="comment.old?null:'RED'">{{comment.old?'OLD':'NEW'}}</p> - <br> - <p class="questionwall-comment-box-body">{{comment.comment.body}}</p> - </div> - </div> + <ars-row style="box-sizing:border-box;padding:8px;"> + <ars-row + [ngClass]="comment===commentFocus?'questionwall-comment-border-on':'questionwall-comment-border-off'" + style="border-radius:5px"> + <ars-row ars-flex-box + (click)="focusComment(comment)" + style="box-sizing:border-box;padding:16px;cursor:pointer"> + <ars-col> + <p class="questionwall-comment-timestamp">{{comment.timeAgo}}</p> + </ars-col> + <ars-fill></ars-fill> + <ars-col> + <p class="questionwall-comment-notification">{{comment.old?'':'NEW'}}</p> + </ars-col> + </ars-row> + <ars-row + (click)="focusComment(comment)" + style="box-sizing:border-box;padding:0 16px;cursor:pointer"> + <p class="questionwall-comment-body">{{comment.comment.body}}</p> + </ars-row> + <ars-row [height]="50"> + <ars-style-btn-material style="width:100%;height:100%;" ars-flex-box> + <ars-col ars-btn-wrp [xp]="16" [extra]="true"> + <button ars-btn (click)="likeComment(comment)"><i>thumb_up</i><p>{{comment.comment.score}}</p></button> + <button ars-btn (click)="dislikeComment(comment)"><i>thumb_down</i></button> + </ars-col> + <ars-fill (click)="focusComment(comment)" style="cursor:pointer"></ars-fill> + </ars-style-btn-material> + </ars-row> + </ars-row> + </ars-row> </ars-row> </ars-col> </ars-fill> <ars-row [height]="50" class="questionwall-footer"> <ars-style-btn-material style="width:100%;" ars-flex-box> <ars-col ars-btn-wrp [xp]="16" [extra]="true"> - <button ars-btn (click)="prevComment()"><p>PREVIOUS</p></button> - <button ars-btn (click)="nextComment()"><p>NEXT</p></button> - </ars-col> - <ars-col> - <p style="padding:15px 5px;box-sizing:border-box;" class="questionwall-text-color">new Comments: {{unreadComments}}</p> + <button ars-btn (click)="toggleFocusIncommingComments()"> + <ng-container *ngIf="focusIncommingComments"> + <i>pause</i><p>Pause</p> + </ng-container> + <ng-container *ngIf="!focusIncommingComments"> + <i>play_arrow</i><p>Autofocus</p> + </ng-container> + </button> </ars-col> <ars-fill></ars-fill> + <ars-col style="display:flex;flex-direction:column;justify-content:center"> + <p *ngIf="unreadComments" style="line-height:18px;" class="questionwall-text-color">{{unreadComments}}</p> + </ars-col> <ars-col ars-btn-wrp [xp]="16" [extra]="true"> - <button ars-btn (click)="stop()"><p [style.color]="focusIncommingComments?'RED':null">PAUSE</p></button> - <button ars-btn (click)="play()"><p [style.color]="focusIncommingComments?null:'RED'">PLAY</p></button> + <button ars-btn (click)="prevComment()"><i>skip_previous</i><p>PREVIOUS</p></button> + <button ars-btn (click)="nextComment()"><i>skip_next</i><p>NEXT</p></button> </ars-col> </ars-style-btn-material> </ars-row> diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.scss b/src/app/components/shared/questionwall/question-wall/question-wall.component.scss index 444697e8f4117a1b91f33e4ccc87c0214c9edd0a..083b9c76d573c1c59e2da547d4dd629ffce4ec0c 100644 --- a/src/app/components/shared/questionwall/question-wall/question-wall.component.scss +++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.scss @@ -21,34 +21,34 @@ } } &-comment{ - width:100%; - padding:16px; - box-sizing:border-box; - &-box{ - background-color:var(--ars-foreground-color); - border-radius:2px; - box-shadow:0px 2px 2px rgba(0,0,0,0.3); - box-sizing:border-box; - padding:16px; - cursor:pointer; - &-user{ - color:var(--ars-header-color); - } - &-body{ - color:var(--ars-paragraph-color); + &-border{ + &-on{ + box-shadow:inset 0px 0px 0px 1px var(--ars-paragraph-color); } - &-time{ - color:var(--ars-header-color); - padding-top:8px; - font-size:12px; + &-off{ + box-shadow:inset 0px 0px 0px 0px var(--ars-paragraph-color); } } - &-list{ - box-sizing:border-box; - padding:16px 0px; - border-left:solid 1px var(--ars-border-color); + &-timestamp{ + color:var(--ars-paragraph-color); + } + &-body{ + hyphens:auto; + color:var(--ars-paragraph-color); + } + &-notification{ + font-size:12px; + text-transform:uppercase; + letter-spacing:2px; + font-weight:600; + color: #cc4244; } } + &-list{ + box-sizing:border-box; + padding:16px 0px; + border-left:solid 1px var(--ars-border-color); + } &-present{ font-size:45px; padding:32px; diff --git a/src/app/components/shared/questionwall/question-wall/question-wall.component.ts b/src/app/components/shared/questionwall/question-wall/question-wall.component.ts index ae24bd92191fd02ee9c0b97343d4afe303171e8f..9e194826c756046fd00ca8bb38d084525ad386a0 100644 --- a/src/app/components/shared/questionwall/question-wall/question-wall.component.ts +++ b/src/app/components/shared/questionwall/question-wall/question-wall.component.ts @@ -8,6 +8,7 @@ import { WsCommentServiceService } from '../../../../services/websockets/ws-comm import { QuestionWallComment } from '../QuestionWallComment'; import { ColComponent } from '../../../../../../projects/ars/src/lib/components/layout/frame/col/col.component'; import { Router } from '@angular/router'; +import { AuthenticationService } from '../../../../services/http/authentication.service'; @Component({ selector: 'app-question-wall', @@ -24,39 +25,49 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { commentFocus: QuestionWallComment; unreadComments = 0; focusIncommingComments = false; + timeUpdateInterval; - static wrap<E>(e: E, action: (e: E) => void) { + public wrap<E>(e: E, action: (e: E) => void) { action(e); } + public notUndefined<E>(e: E, action: (e: E) => void, elsePart?: () => void) { + if (e) {action(e); } else if (elsePart) {elsePart(); } + } + constructor( + private authenticationService: AuthenticationService, private router: Router, private commentService: CommentService, private roomService: RoomService, private wsCommentService: WsCommentServiceService ) { this.roomId = localStorage.getItem('roomId'); + this.timeUpdateInterval = setInterval(() => { + this.comments.forEach(e => e.updateTimeAgo()); + }, 15000); } ngOnInit(): void { // StyleDebug.border('c'); this.commentService.getAckComments(this.roomId).subscribe(e => { e.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); - e.forEach(c => { - this.comments.push(new QuestionWallComment(c, true)); - }); + e.forEach(c => this.comments.push(new QuestionWallComment(c, true))); }); this.roomService.getRoom(this.roomId).subscribe(e => { this.room = e; }); this.wsCommentService.getCommentStream(this.roomId).subscribe(e => { - this.commentService.getComment(JSON.parse(e.body).payload.id).subscribe(c => { - const qwComment = this.pushIncommingComment(c); - if (this.focusIncommingComments) { - setTimeout(() => { - this.focusComment(qwComment); - }, 2); - } + this.commentService.getComment(JSON.parse(e.body).payload.id).subscribe(comment => { + this.notUndefined(this.comments.find(f => f.comment.id === comment.id), qwComment => { + qwComment.comment = comment; + }, () => { + this.wrap(this.pushIncommingComment(comment), qwComment => { + if (this.focusIncommingComments) { + setTimeout(() => this.focusComment(qwComment), 5); + } + }); + }); }); }); } @@ -67,6 +78,7 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { } ngOnDestroy(): void { + window.clearInterval(this.timeUpdateInterval); document.getElementById('header_rescale').style.display = 'block'; document.getElementById('footer_rescale').style.display = 'block'; } @@ -125,12 +137,20 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { }); } - play() { - this.focusIncommingComments = true; + toggleFocusIncommingComments() { + this.focusIncommingComments = !this.focusIncommingComments; + } + + leave() { + document.getElementById('back-button').click(); + } + + likeComment(comment: QuestionWallComment) { + this.wsCommentService.voteUp(comment.comment, this.authenticationService.getUser().id); } - stop() { - this.focusIncommingComments = false; + dislikeComment(comment: QuestionWallComment) { + this.wsCommentService.voteDown(comment.comment, this.authenticationService.getUser().id); } } diff --git a/src/app/components/shared/shared-routing.module.ts b/src/app/components/shared/shared-routing.module.ts index 67a4b6a985d141be1173b4799f7fd30c48535708..22e98b3b61b8b2b930372ed689e6db0a22e37045 100644 --- a/src/app/components/shared/shared-routing.module.ts +++ b/src/app/components/shared/shared-routing.module.ts @@ -6,7 +6,7 @@ import { UserRole } from '../../models/user-roles.enum'; const routes: Routes = [ { - path: 'room/:shortId/questionwall', + path: 'room/:shortId/comments/questionwall', component: QuestionWallComponent, canActivate: [AuthenticationGuard], data: { roles: [UserRole.CREATOR,