From be2818aaaa26e6f086241e686ae553d65db90dd2 Mon Sep 17 00:00:00 2001 From: Lukas Haase <lukas.haase@mni.thm.de> Date: Mon, 4 May 2020 15:40:33 +0200 Subject: [PATCH] Questionwall improve sort --- .../content/menu/ButtonWrapper.directive.ts | 14 +- .../material-btn/material-btn.component.scss | 5 + src/app/components/creator/creator.module.ts | 4 +- .../question-wall.component.html | 152 +++++++++++------- .../question-wall.component.scss | 19 ++- .../question-wall/question-wall.component.ts | 81 ++++++++-- 6 files changed, 199 insertions(+), 76 deletions(-) diff --git a/projects/ars/src/lib/components/content/menu/ButtonWrapper.directive.ts b/projects/ars/src/lib/components/content/menu/ButtonWrapper.directive.ts index e377f9918..d6cdd57cf 100644 --- a/projects/ars/src/lib/components/content/menu/ButtonWrapper.directive.ts +++ b/projects/ars/src/lib/components/content/menu/ButtonWrapper.directive.ts @@ -57,11 +57,15 @@ export class ButtonWrapperDirective implements OnInit, AfterViewInit { // init padding for each button if (this.ft.isCol()) { this.btn.forEach(e => e.setPadding(this.xs / 2, this.xe / 2, 0, 0)); - if (this.extraStart) { - this.btn.first.setPaddingLeft(this.xs); - } - if (this.extraEnd) { - this.btn.last.setPaddingRight(this.xe); + if (this.extraStart && this.extraEnd && this.btn.length == 1) { + this.btn.first.setPadding(this.xs, this.xe, 0, 0); + } else { + if (this.extraStart) { + this.btn.first.setPaddingLeft(this.xs); + } + if (this.extraEnd) { + this.btn.last.setPaddingRight(this.xe); + } } } else { this.btn.forEach(e => e.setPadding(this.xs / 2, this.xe / 2, this.ys / 2, this.ye / 2)); 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 779e84f28..cc483305c 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 @@ -38,6 +38,11 @@ font-weight:500; font-size:14px; line-height:14px; + color:var(--ars-button-color); + } + + ars-row > button > *:nth-child(2){ + float:right; } button > *:nth-child(2){ diff --git a/src/app/components/creator/creator.module.ts b/src/app/components/creator/creator.module.ts index 1ec004568..10b0706bd 100644 --- a/src/app/components/creator/creator.module.ts +++ b/src/app/components/creator/creator.module.ts @@ -22,6 +22,7 @@ import { MarkdownModule } from 'ngx-markdown'; import { DeleteAnswerComponent } from './_dialogs/delete-answer/delete-answer.component'; import { QuestionWallComponent } from '../shared/questionwall/question-wall/question-wall.component'; import { ArsModule } from '../../../../projects/ars/src/lib/ars.module'; +import { MatRippleModule } from '@angular/material/core'; @NgModule({ imports: [ @@ -39,7 +40,8 @@ import { ArsModule } from '../../../../projects/ars/src/lib/ars.module'; isolate: true }), MarkdownModule, - ArsModule + ArsModule, + MatRippleModule ], declarations: [ RoomCreatorPageComponent, 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 c1850e961..3fb4cbe7a 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 @@ -3,7 +3,7 @@ <ars-style-btn-material *ngIf="room" style="width:100%;height:100%;" ars-flex-box> <ars-fill ars-flex-box> <ars-col ars-btn-wrp [xp]="16" [yp]="0" [extra]="true"> - <button ars-btn (click)="leave()"><i>arrow_back</i></button> + <button ars-btn (click)="leave()" matRipple><i>arrow_back</i></button> </ars-col> </ars-fill> <ars-col> @@ -12,11 +12,28 @@ <ars-fill ars-flex-box> <ars-fill></ars-fill> <ars-col ars-btn-wrp [xp]="16" [extra]="true"> - <button ars-btn (click)="sortTime()"><p>{{'question-wall.sort-time' | translate}}</p><i>expand_less</i></button> - <button ars-btn (click)="sortTime(true)"><i>expand_more</i></button> - <button ars-btn (click)="sortScore()"><p>{{'question-wall.sort-score' | translate}}</p><i>expand_less</i></button> - <button ars-btn (click)="sortScore(true)"><i>expand_more</i></button> - <button ars-btn (click)="filterFavorites()"><i>star</i><p>{{'question-wall.filter-favorite' | translate}}</p></button> + <mat-menu #sortMenu> + <button mat-menu-item (click)="sortTime(true)">Newest</button> + <button mat-menu-item (click)="sortTime()">Oldest</button> + <button mat-menu-item (click)="sortScore(true)">Score</button> + </mat-menu> + <mat-menu #filterMenu> + <button mat-menu-item (click)="filterFavorites()"> + <mat-icon>star</mat-icon> + <span>Favorite</span> + </button> + <button mat-menu-item (click)="filterFavorites()"> + <mat-icon>check_circle</mat-icon> + <span>approved</span> + </button> + <button mat-menu-item (click)="filterFavorites()"> + <mat-icon>block</mat-icon> + <span>disapproved</span> + </button> + </mat-menu> + <button ars-btn [mat-menu-trigger-for]="sortMenu" matRipple><i>sort</i><p>Sort</p></button> + <button ars-btn [mat-menu-trigger-for]="filterMenu" matRipple><i>filter_list</i><p>Filter</p></button> + <button ars-btn (click)="openUserMap()" matRipple><i>person</i><p>user</p></button> </ars-col> </ars-fill> </ars-style-btn-material> @@ -46,65 +63,86 @@ <ars-fill> </ars-fill> </ars-fill> - <ars-col [width]="450" [overflow]="'auto'" class="questionwall-list" #colComponent> - <ars-row *ngIf="hasFilter" class="questionwall-list-filter" [height]="45"> - <ars-style-btn-material style="width:100%;height:100%;" ars-flex-box> - <ars-col ars-btn-wrp [xp]="48"> - <button ars-btn><p>{{filterTitle | translate}} {{filterDesc}}</p></button> - </ars-col> - <ars-fill></ars-fill> - <ars-col ars-btn-wrp [xp]="48"> - <button ars-btn (click)="deactivateFilter()"><i>remove_circle</i><p>remove filter</p></button> - </ars-col> - </ars-style-btn-material> + <ars-col ars-flex-box [width]="450" class="questionwall-list" #colComponent> + + <ars-row> + <ars-row *ngIf="hasFilter" class="questionwall-list-border-bottom" [height]="45"> + <ars-style-btn-material style="width:100%;height:100%;" ars-flex-box> + <ars-col ars-btn-wrp [xp]="48"> + <button ars-btn matRipple><i>{{filterIcon}}</i><p>{{filterTitle | translate}} {{filterDesc}}</p></button> + </ars-col> + <ars-fill></ars-fill> + <ars-col ars-btn-wrp [xp]="48"> + <button ars-btn (click)="deactivateFilter()" matRipple><i>remove_circle</i><p>remove filter</p></button> + </ars-col> + </ars-style-btn-material> + </ars-row> </ars-row> - <ars-row *ngFor="let comment of hasFilter?commentsFilter:comments" class="questionwall-comment-anchor"> - <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 class="questionwall-comment-meta"> - <i class="questionwall-icon">person</i> - <p (click)="filterUser(comment);" class="questionwall-comment-user">{{comment.comment.userNumber}}</p> - <p class="questionwall-comment-timestamp">{{comment.timeAgo}}</p> - </ars-col> - <ars-col> - <p class="questionwall-comment-notification">{{comment.old?'':'NEW'}}</p> - </ars-col> - <ars-col> -<!-- <ars-style-btn-material>--> -<!-- <ars-col ars-btn-wrp [xp]="16" [extraStart]="true" class="questionwall-comment-btn">--> -<!-- <button ars-btn><i>{{comment.comment.favorite?'star':'star_border'}}</i></button>--> -<!-- </ars-col>--> -<!-- </ars-style-btn-material>--> - </ars-col> + + <ars-fill class="questionwall-list-comments"> + + <ars-row *ngIf="!userSelection"> + + <ars-row *ngFor="let comment of hasFilter?commentsFilter:comments" class="questionwall-comment-anchor" style="float:left;"> + <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 class="questionwall-comment-meta"> + <i class="questionwall-icon">person</i> + <p (click)="filterUser(comment);" class="questionwall-comment-user" matRipple>{{comment.comment.userNumber}}</p> + <p class="questionwall-comment-timestamp">{{comment.timeAgo}}</p> + </ars-col> + <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" class="questionwall-comment-btn"> + <button ars-btn (click)="likeComment(comment)" matRipple><i>thumb_up</i><p>{{comment.comment.score}}</p></button> + <button ars-btn (click)="dislikeComment(comment)" matRipple><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 - (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> + + <ars-row *ngIf="userSelection"> + <ars-style-btn-material style="width:100%"> + <ars-row [height]="50" ars-flex-box class="questionwall-list-border-bottom"> + <ars-col ars-btn-wrp [xp]="24" [extra]="true"> + <button ars-btn (click)="cancelUserMap()" matRipple><i>arrow_back</i></button> + </ars-col> </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" class="questionwall-comment-btn"> - <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-btn-wrp [xp]="48" [yp]="32"> + <button ars-btn mat-ripple *ngFor="let user of userList" (click)="applyUserMap(user[1])"> + <p>{{user[1]}}</p><p>{{user[0]}}</p> + </button> </ars-row> - </ars-row> + </ars-style-btn-material> </ars-row> - </ars-row> + + </ars-fill> + </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)="toggleFocusIncommingComments()"> + <button ars-btn (click)="toggleFocusIncommingComments()" matRipple> <ng-container *ngIf="focusIncommingComments"> <i>{{'question-wall.auto-renew-off-icon' | translate}}</i> <p>{{'question-wall.auto-renew-off' | translate}}</p> @@ -120,11 +158,11 @@ <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)="prevComment()"> + <button ars-btn (click)="prevComment()" matRipple> <i>{{'question-wall.prev-comment-icon' | translate}}</i> <p>{{'question-wall.prev-comment' | translate}}</p> </button> - <button ars-btn (click)="nextComment()"> + <button ars-btn (click)="nextComment()" matRipple> <i>{{'question-wall.next-comment-icon' | translate}}</i> <p>{{'question-wall.next-comment' | translate}}</p> </button> 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 67e0dae7e..864b6ca85 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 @@ -5,6 +5,12 @@ margin:0; } + .test{ + width:100%; + height:250px; + box-shadow:inset 0 0 0 1px black; + } + .questionwall{ &-icon{ font-family:'Material Icons', serif; @@ -81,12 +87,23 @@ } &-list{ box-sizing:border-box; - padding:16px 0px; border-left:solid 1px var(--ars-border-color); &-filter{ border-top:solid 1px var(--ars-border-color); border-bottom:solid 1px var(--ars-border-color); } + &-border-bottom{ + border-bottom:solid 1px var(--ars-border-color); + } + &-comments{ + } + &-scroll{ + width:100%; + height:100%; + display:flex; + flex-direction:column; + background-color:orange; + } } &-present{ font-size:45px; 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 0fc83046e..39d77a44f 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 @@ -1,5 +1,4 @@ import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { StyleDebug } from '../../../../../../projects/ars/src/lib/models/debug/StyleDebug'; import { CommentService } from '../../../../services/http/comment.service'; import { Comment } from '../../../../models/comment'; import { RoomService } from '../../../../services/http/room.service'; @@ -13,6 +12,7 @@ import { LanguageService } from '../../../../services/util/language.service'; import { TranslateService } from '@ngx-translate/core'; import { Rescale } from '../../../../models/rescale'; import { QuestionWallKeyEventSupport } from '../QuestionWallKeyEventSupport'; +import { CorrectWrong } from '../../../../models/correct-wrong.enum'; @Component({ selector: 'app-question-wall', @@ -33,8 +33,12 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { timeUpdateInterval; keySupport: QuestionWallKeyEventSupport; hasFilter = false; - filterTitle = 'Test'; - filterDesc = 'test'; + filterTitle = ''; + filterDesc = ''; + filterIcon = ''; + userMap: Map<number, number> = new Map<number, number>(); + userList = []; + userSelection = false; public wrap<E>(e: E, action: (e: E) => void) { action(e); @@ -69,7 +73,7 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { QuestionWallComment.updateTimeFormat(localStorage.getItem('currentLang')); this.translateService.use(localStorage.getItem('currentLang')); this.commentService.getAckComments(this.roomId).subscribe(e => { - e.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); + e.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()); e.forEach(c => { const comment = new QuestionWallComment(c, true); this.comments.push(comment); @@ -175,6 +179,34 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { this.focusIncommingComments = !this.focusIncommingComments; } + createUserMap() { + this.userMap = new Map(); + this.comments.forEach(c => { + if (!this.userMap.has(c.comment.userNumber)) { + this.userMap.set(c.comment.userNumber, 0); + } + this.userMap.set(c.comment.userNumber, this.userMap.get(c.comment.userNumber) + 1); + }); + this.userList = []; + this.userMap.forEach((num, user) => { + this.userList.push([num, user]); + }); + } + + applyUserMap(user: number) { + this.userSelection = false; + this.filterUserByNumber(user); + } + + openUserMap() { + this.createUserMap(); + this.userSelection = true; + } + + cancelUserMap() { + this.userSelection = false; + } + leave() { document.getElementById('back-button').click(); } @@ -204,7 +236,7 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { } setTimeout(() => { if (commentList.length > 1) { - this.focusComment(commentList[commentList.length - 1]); + this.focusComment(commentList[0]); } }, 0); } @@ -222,17 +254,42 @@ export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy { } filterFavorites() { - this.filterTitle = 'question-wall.filter-favorite'; - this.filterDesc = ''; - this.commentsFilter = this.comments.filter(x => x.comment.favorite); - this.hasFilter = true; + this.filter('star', 'question-wall.filter-favorite', '', + x => x.comment.favorite); } filterUser(comment: QuestionWallComment) { - this.filterTitle = 'question-wall.filter-user'; - this.filterDesc = comment.comment.userNumber + ''; - this.commentsFilter = this.comments.filter(x => x.comment.userNumber === comment.comment.userNumber); + this.filterUserByNumber(comment.comment.userNumber); + } + + filterUserByNumber(user: number) { + this.filter('person', 'question-wall.filter-user', user + '', + x => x.comment.userNumber === user); + } + + filterApproved() { + this.filter('check_circle', 'question-wall.filter-disapproved', '', + x => x.comment.correct === CorrectWrong.CORRECT); + } + + filterDisapproved() { + this.filter('block', 'question-wall.filter-disapproved', '', + x => x.comment.correct === CorrectWrong.WRONG); + } + + filter(icon: string, title: string, desc: string, filter: (x: QuestionWallComment) => boolean) { + this.filterIcon = icon; + this.filterTitle = title; + this.filterDesc = desc; + this.commentsFilter = this.comments.filter(filter); this.hasFilter = true; + setTimeout(() => this.focusFirstComment(), 0); + } + + focusFirstComment() { + if (this.getCurrentCommentList().length > 0) { + this.commentFocus = this.getCurrentCommentList()[0]; + } } deactivateFilter() { -- GitLab