diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.html b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.html index 7b52aea060be2052e558992e4682f0bc588f1ea8..7ddb061eab8432234218c8e9c89f1a1aa35d7774 100644 --- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.html +++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.html @@ -55,7 +55,7 @@ aria-labelledby="time_settings" *ngIf="!searchBox.value && comments && comments.length > 0 && !search" [matMenuTriggerFor]="timeMenu" - [ngClass]="{'active-filter': period !== 'time-all'}" + [ngClass]="{'active-filter': filter.period !== 'time-all'}" matTooltip="{{ 'comment-list.select-time' | translate }}"> <mat-icon class="searchBarIcon">history</mat-icon> </button> @@ -73,25 +73,25 @@ xPosition="before"> <button mat-menu-item matTooltip="{{ 'comment-list.time' | translate }}" - (click)="sortComments(time)" + (click)="sortCommentsByKey('time')" aria-labelledby="access_time"> - <mat-icon [ngClass]="{time: 'unread-icon'}[currentSort]">update</mat-icon> - <span>{{ 'comment-list.sort-list-time' | translate }}</span> + <mat-icon [ngClass]="{time: 'timesort'}[filter.sortType]">update</mat-icon> + <span [ngClass]="{time: 'timesort'}[filter.sortType]">{{ 'comment-list.sort-list-time' | translate }}</span> </button> <button mat-menu-item matTooltip="{{ 'comment-list.vote-asc' | translate }}" - (click)="sortComments(votedesc)" + (click)="sortCommentsByKey('votedesc')" aria-labelledby="keyboard_arrow_up"> - <mat-icon [ngClass]="{votedesc: 'up'}[currentSort]">thumb_up</mat-icon> + <mat-icon [ngClass]="{votedesc: 'up'}[filter.sortType]">thumb_up</mat-icon> <span>{{ 'comment-list.sort-vote-asc' | translate }}</span> </button> <button mat-menu-item matTooltip="{{ 'comment-list.vote-desc' | translate }}" - (click)="sortComments(voteasc)" + (click)="sortCommentsByKey('voteasc')" aria-labelledby="keyboard_arrow_down"> - <mat-icon [ngClass]="{voteasc: 'down'}[currentSort]">thumb_down</mat-icon> + <mat-icon [ngClass]="{voteasc: 'down'}[filter.sortType]">thumb_down</mat-icon> <span>{{ 'comment-list.sort-vote-desc' | translate }}</span> </button> </mat-menu> @@ -99,7 +99,7 @@ <mat-menu #timeMenu="matMenu" xPosition="before"> <div *ngFor="let periodItem of periodsList"> <button mat-menu-item (click)="setTimePeriod(periodItem)" class="period" - [ngClass]="{'selected': periodItem === period}" + [ngClass]="{'selected': periodItem === filter.period}" aria-labelledby="{{periodItem}}"> <span>{{ ('comment-list.select-' + periodItem) | translate }}</span> </button> @@ -136,7 +136,7 @@ <ars-row [height]="64"> </ars-row> -<div *ngIf="comments && (commentsFilteredByTime.length < 1 && period === 'time-all' || comments.length === 0) && !isLoading" +<div *ngIf="comments && (commentsFilteredByTime.length < 1 && filter.period === 'time-all' || comments.length === 0) && !isLoading" fxLayout="row" fxLayoutAlign="center center" class="no-comments"> @@ -145,7 +145,7 @@ </div> <div *ngIf="(filteredComments && filteredComments.length === 0 && hideCommentsList) - || (comments && commentsFilteredByTime.length === 0 && period !== 'time-all') && !isLoading && comments.length > 0" + || (comments && commentsFilteredByTime.length === 0 && filter.period !== 'time-all') && !isLoading && comments.length > 0" fxLayout="row" fxLayoutAlign="center center" class="no-comments"> diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.scss b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.scss index 34b3f2feb31cf55bd7c878a39d808a1c3ddd54da..b39d91b167a734eccd46af85f5c1475478ee931f 100644 --- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.scss +++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.scss @@ -101,6 +101,10 @@ h3 { margin: 10px; } +.timesort { + color: var(--primary); +} + .up { color: var(--green); } diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts index 96ad723dc770ba147dde5249889d7451553a3202..b7b5531037900895e35325aa5e24a93d9620be12 100644 --- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts +++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts @@ -23,6 +23,8 @@ import { NotificationService } from '../../../services/util/notification.service import { BonusTokenService } from '../../../services/http/bonus-token.service'; import { CommentFilter, Period } from '../../../utils/filter-options'; import { PageEvent } from '@angular/material/paginator'; +import { CommentListFilter, FilterType, SortType, SortTypeKey } from '../../shared/comment-list/comment-list.filter'; +import { ModeratorService } from '../../../services/http/moderator.service'; @Component({ @@ -47,7 +49,6 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { voteasc = 'voteasc'; votedesc = 'votedesc'; time = 'time'; - currentSort: string; read = 'read'; unread = 'unread'; favorite = 'favorite'; @@ -56,7 +57,6 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { ack = 'ack'; bookmark = 'bookmark'; userNumber = 'userNumber'; - currentFilter = ''; commentVoteMap = new Map<string, Vote>(); scroll = false; scrollExtended = false; @@ -64,13 +64,12 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { search = false; searchPlaceholder = ''; periodsList = Object.values(Period); - period: Period = Period.twoWeeks; - fromNow: number; headerInterface = null; pageIndex = 0; pageSize = 10; pageSizeOptions = [5, 10, 25]; showFirstLastButtons = true; + filter: CommentListFilter; constructor( private commentService: CommentService, @@ -83,12 +82,14 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { private router: Router, private notificationService: NotificationService, private translationService: TranslateService, - private bonusTokenService: BonusTokenService + private bonusTokenService: BonusTokenService, + private moderationService: ModeratorService ) { langService.langEmitter.subscribe(lang => translateService.use(lang)); + this.filter = CommentListFilter.loadCurrentFilter(); } - handlePageEvent(e:PageEvent){ + handlePageEvent(e: PageEvent) { this.pageIndex = e.pageIndex; this.pageSize = e.pageSize; } @@ -113,25 +114,25 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { } dialogRef.componentInstance.tags = tags; dialogRef.afterClosed() - .subscribe(result => { - if (!result || result === 'abort') { - return; - } else { - updRoom.tags = result; - this.roomService.updateRoom(updRoom) - .subscribe((room) => { - this.room = room; - this.translateService.get('room-page.changes-successful').subscribe(msg => { - this.notificationService.show(msg); - }); - }, - error => { - this.translateService.get('room-page.changes-gone-wrong').subscribe(msg => { - this.notificationService.show(msg); - }); - }); - } - }); + .subscribe(result => { + if (!result || result === 'abort') { + return; + } else { + updRoom.tags = result; + this.roomService.updateRoom(updRoom) + .subscribe((room) => { + this.room = room; + this.translateService.get('room-page.changes-successful').subscribe(msg => { + this.notificationService.show(msg); + }); + }, + error => { + this.translateService.get('room-page.changes-gone-wrong').subscribe(msg => { + this.notificationService.show(msg); + }); + }); + } + }); }); nav('deleteQuestions', () => { const dialogRef = this.dialog.open(DeleteCommentsComponent, { @@ -139,14 +140,14 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { }); dialogRef.componentInstance.roomId = this.roomId; dialogRef.afterClosed() - .subscribe(result => { - if (result === 'delete') { - this.translationService.get('room-page.comments-deleted').subscribe(msg => { - this.notificationService.show(msg); - }); - this.commentService.deleteCommentsByRoomId(this.roomId).subscribe(); - } - }); + .subscribe(result => { + if (result === 'delete') { + this.translationService.get('room-page.comments-deleted').subscribe(msg => { + this.notificationService.show(msg); + }); + this.commentService.deleteCommentsByRoomId(this.roomId).subscribe(); + } + }); }); nav('exportQuestions', () => { const exp: Export = new Export( @@ -166,6 +167,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { } ngOnDestroy() { + this.filter.save(); if (this.headerInterface) { this.headerInterface.unsubscribe(); } @@ -175,8 +177,12 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { this.initNavigation(); this.roomId = localStorage.getItem(`roomId`); const userId = this.user.id; + this.filter.updateUserId(userId); this.userRole = this.user.role; - this.roomService.getRoom(this.roomId).subscribe(room => this.room = room); + this.roomService.getRoom(this.roomId).subscribe(room => { + this.room = room; + this.filter.updateRoom(room); + }); this.hideCommentsList = false; this.wsCommentService.getModeratorCommentStream(this.roomId).subscribe((message: Message) => { this.parseIncomingModeratorMessage(message); @@ -187,30 +193,23 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { this.translateService.use(localStorage.getItem('currentLang')); this.deviceType = localStorage.getItem('deviceType'); this.isSafari = localStorage.getItem('isSafari'); - this.currentSort = this.votedesc; - this.commentService.getRejectedComments(this.roomId) - .subscribe(comments => { - this.comments = comments; - this.setTimePeriod(this.period); - this.isLoading = false; + this.filter.sortType = SortType.votedesc; + this.moderationService.get(this.roomId) + .subscribe((mods) => { + this.filter.updateModerators(mods.map(mod => mod.accountId)); + + this.commentService.getRejectedComments(this.roomId) + .subscribe(comments => { + this.comments = comments; + this.setTimePeriod(this.filter.period); + this.isLoading = false; + }); }); this.translateService.get('comment-list.search').subscribe(msg => { this.searchPlaceholder = msg; }); } - private getCurrentFilter() { - const filter = new CommentFilter(); - filter.filterSelected = this.currentFilter; - filter.periodSet = this.period; - - if (filter.periodSet === Period.fromNow) { - filter.timeStampNow = new Date().getTime(); - } - - CommentFilter.currentFilter = filter; - } - checkScroll(): void { const currentScroll = document.documentElement.scrollTop; this.scroll = currentScroll >= 65; @@ -254,7 +253,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { this.comments = this.comments.filter(x => x.score >= commentThreshold); } } - this.setTimePeriod(this.period); + this.setTimePeriod(this.filter.period); } getVote(comment: Comment): Vote { @@ -278,7 +277,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { this.comments = this.comments.filter(function (el) { return el.id !== payload.id; }); - this.setTimePeriod(this.period); + this.setTimePeriod(this.filter.period); } switch (key) { case this.read: @@ -318,7 +317,7 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { } break; } - this.setTimePeriod(this.period); + this.setTimePeriod(this.filter.period); if (this.hideCommentsList) { this.searchComments(); } @@ -336,70 +335,51 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { c.timestamp = payload.timestamp; c.creatorId = payload.creatorId; c.keywordsFromQuestioner = payload.keywordsFromQuestioner ? - JSON.parse(payload.keywordsFromQuestioner as unknown as string) : null; + JSON.parse(payload.keywordsFromQuestioner as unknown as string) : null; c.userNumber = this.commentService.hashCode(c.creatorId); this.comments = this.comments.concat(c); break; } - this.setTimePeriod(this.period); + this.setTimePeriod(this.filter.period); if (this.hideCommentsList) { this.searchComments(); } } - filterComments(type: string, compare?: any): void { - this.currentFilter = type; - if (type === '') { + filterComments(type: FilterType, compare?: any): void { + this.pageIndex = 0; + this.filter.filterType = type; + this.filter.filterCompare = compare; + if (!type) { this.filteredComments = this.commentsFilteredByTime; + this.hideCommentsList = false; + this.sortComments(this.filter.sortType); return; } - this.filteredComments = this.commentsFilteredByTime.filter(c => { - switch (type) { - case this.correct: - return c.correct === CorrectWrong.CORRECT ? 1 : 0; - case this.wrong: - return c.correct === CorrectWrong.WRONG ? 1 : 0; - case this.favorite: - return c.favorite; - case this.bookmark: - return c.bookmark; - case this.read: - return c.read; - case this.unread: - return !c.read; - case this.userNumber: - return c.userNumber === compare; - } - }); + this.filteredComments = this.filter.filterCommentsByType(this.commentsFilteredByTime); this.hideCommentsList = true; - this.sortComments(this.currentSort); + this.sortComments(this.filter.sortType); } clickedUserNumber(usrNumber: number): void { - this.filterComments(this.userNumber, usrNumber); + this.filterComments(FilterType.userNumber, usrNumber); } - sort(array: any[], type: string): void { - array.sort((a, b) => { - if (type === this.voteasc) { - return (a.score > b.score) ? 1 : (b.score > a.score) ? -1 : 0; - } else if (type === this.votedesc) { - return (b.score > a.score) ? 1 : (a.score > b.score) ? -1 : 0; - } - const dateA = new Date(a.timestamp), dateB = new Date(b.timestamp); - if (type === this.time) { - return (+dateB > +dateA) ? 1 : (+dateA > +dateB) ? -1 : 0; - } - }); + sort(array: Comment[], type: SortType): void { + this.filter.sortType = type; + this.filter.sortCommentsBySortType(array); + } + + sortCommentsByKey(type: SortTypeKey) { + this.sortComments(SortType[type]); } - sortComments(type: string): void { + sortComments(type: SortType): void { if (this.hideCommentsList === true) { this.sort(this.filteredComments, type); } else { this.sort(this.commentsFilteredByTime, type); } - this.currentSort = type; } switchToCommentList(): void { @@ -411,44 +391,25 @@ export class ModeratorCommentListComponent implements OnInit, OnDestroy { } this.router.navigate([`/${role}/room/${this.room.shortId}/comments`]); } + setTimePeriod(period?: Period) { if (period) { - this.period = period; - this.fromNow = null; + this.filter.period = period; + this.filter.fromNow = null; } - const currentTime = new Date(); - const hourInSeconds = 3600000; - let periodInSeconds; - if (this.period !== Period.all) { - switch (this.period) { - case Period.fromNow: - if (!this.fromNow) { - this.fromNow = new Date().getTime(); - } - break; - case Period.oneHour: - periodInSeconds = hourInSeconds; - break; - case Period.threeHours: - periodInSeconds = hourInSeconds * 2; - break; - case Period.oneDay: - periodInSeconds = hourInSeconds * 24; - break; - case Period.oneWeek: - periodInSeconds = hourInSeconds * 168; - break; - case Period.twoWeeks: - periodInSeconds = hourInSeconds * 336; - break; - } - this.commentsFilteredByTime = this.comments - .filter(c => new Date(c.timestamp).getTime() >= - (this.period === Period.fromNow ? this.fromNow : (currentTime.getTime() - periodInSeconds))); - } else { - this.commentsFilteredByTime = this.comments; + this.commentsFilteredByTime = this.filter.filterCommentsByTime(this.comments, true); + this.filterComments(this.filter.filterType, this.filter.filterCompare); + } + + private getCurrentFilter() { + const filter = new CommentFilter(); + filter.filterSelected = this.filter.filterType; + filter.periodSet = this.filter.period; + + if (filter.periodSet === Period.fromNow) { + filter.timeStampNow = new Date().getTime(); } - this.filterComments(this.currentFilter); + CommentFilter.currentFilter = filter; } } diff --git a/src/app/components/shared/comment-list/comment-list.component.html b/src/app/components/shared/comment-list/comment-list.component.html index 28de46839e532382f486ef32f0646a69d7e1ff1f..7f6b41f49310bf8df2d055e088b02becd21d3e01 100644 --- a/src/app/components/shared/comment-list/comment-list.component.html +++ b/src/app/components/shared/comment-list/comment-list.component.html @@ -7,8 +7,8 @@ <button id="filter-close-button" mat-icon-button class="searchBarButton" - *ngIf="currentFilter !== ''" - (click)="filterComments('');" + *ngIf="filter.filterType" + (click)="filterCommentsByKey(null)" aria-labelledby="close_filter"> <mat-icon class="searchBarIcon red">close</mat-icon> </button> @@ -22,14 +22,14 @@ [ngClass]="{'desktop-input': deviceType === 'desktop', 'mobile-input': deviceType === 'mobile' && !search, 'mobile-input-2': deviceType === 'mobile' && search }" (input)="searchComments()" - [(ngModel)]="searchInput" + [(ngModel)]="filter.currentSearch" [placeholder]="searchPlaceholder" aria-labelledby="search-box-input-description"> <button id="search_close-button" mat-icon-button class="searchBarButton close red" - *ngIf="searchInput !== '' || search" - (click)="hideCommentsList=false; searchInput = ''; search = false;" + *ngIf="filter.currentSearch || search" + (click)="abortSearch()" aria-labelledby="close_search"> <mat-icon>close</mat-icon> </button> @@ -49,7 +49,7 @@ <button mat-icon-button class="searchBarButton" - (click)="activateSearch(); filterComments('')" + (click)="activateSearch(); filterCommentsByKey(null)" *ngIf="deviceType === 'mobile' && !search && comments && comments.length > 0"> <mat-icon class="searchBarIcon">search</mat-icon> </button> @@ -81,7 +81,7 @@ aria-labelledby="time_settings" *ngIf="!searchBox.value && comments && comments.length > 0 && !search" [matMenuTriggerFor]="timeMenu" - [ngClass]="{'active-filter': period !== 'time-all'}" + [ngClass]="{'active-filter': filter.period !== 'time-all'}" matTooltip="{{ 'comment-list.select-time' | translate }}"> <mat-icon class="searchBarIcon">history</mat-icon> </button> @@ -91,7 +91,7 @@ aria-labelledby="pause" class="freezeButton" *ngIf="!searchBox.value && !search && !freeze && comments.length > 2" - (click)="pauseCommentStream()" + (click)="activateCommentStream(true)" matTooltip="{{ 'comment-list.pause-comments' | translate }}"> <mat-icon class="freezeIcon">pause</mat-icon> </button> @@ -101,7 +101,7 @@ aria-labelledby="play" class="freezeButton" *ngIf="!searchBox.value && !search && freeze" - (click)="playCommentStream()" + (click)="activateCommentStream(false)" matTooltip="{{ 'comment-list.play-comments' | translate }}"> <mat-icon class="playIcon">play_arrow</mat-icon> </button> @@ -114,7 +114,7 @@ <button mat-menu-item (click)="setTimePeriod(periodItem)" class="period" - [ngClass]="{'selected': periodItem === period}" + [ngClass]="{'selected': periodItem === filter.period}" aria-labelledby="{{periodItem}}"> <span>{{ ('comment-list.select-' + periodItem) | translate }}</span> </button> @@ -125,24 +125,24 @@ xPosition="before"> <button mat-menu-item - (click)="sortComments(time)" + (click)="sortCommentsByKey('time')" aria-labelledby="access_time"> - <mat-icon [ngClass]="{time: 'timesort'}[currentSort]">update</mat-icon> - <span [ngClass]="{time: 'timesort'}[currentSort]">{{ 'comment-list.sort-list-time' | translate }}</span> + <mat-icon [ngClass]="{time: 'timesort'}[filter.sortType]">update</mat-icon> + <span [ngClass]="{time: 'timesort'}[filter.sortType]">{{ 'comment-list.sort-list-time' | translate }}</span> </button> <button mat-menu-item - (click)="sortComments(votedesc)" + (click)="sortCommentsByKey('votedesc')" aria-labelledby="keyboard_arrow_up"> - <mat-icon [ngClass]="{votedesc: 'up'}[currentSort]">thumb_up</mat-icon> - <span [ngClass]="{votedesc: 'up'}[currentSort]">{{ 'comment-list.sort-vote-asc' | translate }}</span> + <mat-icon [ngClass]="{votedesc: 'up'}[filter.sortType]">thumb_up</mat-icon> + <span [ngClass]="{votedesc: 'up'}[filter.sortType]">{{ 'comment-list.sort-vote-asc' | translate }}</span> </button> <button mat-menu-item - (click)="sortComments(voteasc)" + (click)="sortCommentsByKey('voteasc')" aria-labelledby="keyboard_arrow_down"> - <mat-icon [ngClass]="{voteasc: 'down'}[currentSort]">thumb_down</mat-icon> - <span [ngClass]="{voteasc: 'down'}[currentSort]">{{ 'comment-list.sort-vote-desc' | translate }}</span> + <mat-icon [ngClass]="{voteasc: 'down'}[filter.sortType]">thumb_down</mat-icon> + <span [ngClass]="{voteasc: 'down'}[filter.sortType]">{{ 'comment-list.sort-vote-desc' | translate }}</span> </button> </mat-menu> @@ -152,53 +152,53 @@ <div> <button mat-menu-item - (click)="filterComments(favorite)" + (click)="filterCommentsByKey('favorite')" aria-labelledby="grade"> <mat-icon class="star" - [ngClass]="{favorite: 'favorite-icon'}[currentFilter]">grade + [ngClass]="{favorite: 'favorite-icon'}[filter.filterType]">grade </mat-icon> <span - [ngClass]="{favorite: 'favorite-icon'}[currentFilter]">{{ 'comment-list.filter-favorite' | translate }}</span> + [ngClass]="{favorite: 'favorite-icon'}[filter.filterType]">{{ 'comment-list.filter-favorite' | translate }}</span> </button> <button mat-menu-item - (click)="filterComments(bookmark)" + (click)="filterCommentsByKey('bookmark')" aria-labelledby="bookmark"> <mat-icon class="bookmark" - [ngClass]="{bookmark: 'bookmark-icon'}[currentFilter]">bookmark + [ngClass]="{bookmark: 'bookmark-icon'}[filter.filterType]">bookmark </mat-icon> <span - [ngClass]="{bookmark: 'bookmark-icon'}[currentFilter]">{{ 'comment-list.filter-bookmark' | translate }}</span> + [ngClass]="{bookmark: 'bookmark-icon'}[filter.filterType]">{{ 'comment-list.filter-bookmark' | translate }}</span> </button> <button mat-menu-item (focus)="hideCommentsList=true" - (click)="filterComments(answer)" + (click)="filterCommentsByKey('answer')" aria-labelledby="comment"> <mat-icon class="answer" - [ngClass]="{answer: 'answered-icon'}[currentFilter]">comment + [ngClass]="{answer: 'answered-icon'}[filter.filterType]">comment </mat-icon> <span - [ngClass]="{answer: 'answered-icon'}[currentFilter]">{{ 'comment-list.filter-answered' | translate }}</span> + [ngClass]="{answer: 'answered-icon'}[filter.filterType]">{{ 'comment-list.filter-answered' | translate }}</span> </button> <button mat-menu-item (focus)="hideCommentsList=true" - (click)="filterComments(unanswered)" + (click)="filterCommentsByKey('unanswered')" aria-labelledby="comment"> <mat-icon class="unanswered" - [ngClass]="{unanswered: 'unanswered-icon'}[currentFilter]">comment + [ngClass]="{unanswered: 'unanswered-icon'}[filter.filterType]">comment </mat-icon> <span - [ngClass]="{unanswered: 'unanswered-icon'}[currentFilter]">{{ 'comment-list.filter-unanswered' | translate }}</span> + [ngClass]="{unanswered: 'unanswered-icon'}[filter.filterType]">{{ 'comment-list.filter-unanswered' | translate }}</span> </button> <button mat-menu-item (focus)="hideCommentsList=true" - (click)="filterComments(owner)" + (click)="filterCommentsByKey('owner')" aria-labelledby="comment"> - <mat-icon [ngClass]="{owner: 'owner-icon'}[currentFilter]">person_pin_circle</mat-icon> - <span [ngClass]="{owner: 'owner-icon'}[currentFilter]">{{ 'comment-list.filter-owner' | translate }}</span> + <mat-icon [ngClass]="{owner: 'owner-icon'}[filter.filterType]">person_pin_circle</mat-icon> + <span [ngClass]="{owner: 'owner-icon'}[filter.filterType]">{{ 'comment-list.filter-owner' | translate }}</span> </button> <!-- @@ -227,7 +227,7 @@ <button mat-menu-item (focus)="hideCommentsList=false" - (click)="sortComments(currentSort); filterComments('')" + (click)="sortComments(this.filter.sortType); filterCommentsByKey(null)" aria-labelledby="close"> <mat-icon>close</mat-icon> <span>{{ 'comment-list.filter-reset' | translate }}</span> @@ -297,7 +297,7 @@ <!-- No Questions Present --> <div - *ngIf="comments && (commentsFilteredByTime.length < 1 && period === 'time-all' || comments.length === 0) && !isLoading" + *ngIf="comments && (commentsFilteredByTime.length < 1 && filter.period === 'time-all' || comments.length === 0) && !isLoading" fxLayout="row" fxLayoutAlign="center center" class="no-comments"> @@ -305,7 +305,7 @@ </div> <div *ngIf="(filteredComments && filteredComments.length === 0 && hideCommentsList) - || (comments && commentsFilteredByTime.length === 0 && period !== 'time-all') && !isLoading && comments.length > 0" + || (comments && commentsFilteredByTime.length === 0 && filter.period !== 'time-all') && !isLoading && comments.length > 0" fxLayout="row" fxLayoutAlign="center center" class="no-comments"> diff --git a/src/app/components/shared/comment-list/comment-list.component.ts b/src/app/components/shared/comment-list/comment-list.component.ts index 1e73a75e1abb5c8ba331c4848ea5ded383b1c393..94929a3f82c91dabaf66d07846ddd5a85b836080 100644 --- a/src/app/components/shared/comment-list/comment-list.component.ts +++ b/src/app/components/shared/comment-list/comment-list.component.ts @@ -11,7 +11,6 @@ import { Room } from '../../../models/room'; import { RoomService } from '../../../services/http/room.service'; import { VoteService } from '../../../services/http/vote.service'; import { NotificationService } from '../../../services/util/notification.service'; -import { CorrectWrong } from '../../../models/correct-wrong.enum'; import { LiveAnnouncer } from '@angular/cdk/a11y'; import { EventService } from '../../../services/util/event.service'; import { Subscription } from 'rxjs'; @@ -34,6 +33,7 @@ import { ActiveUserService } from '../../../services/http/active-user.service'; import { OnboardingService } from '../../../services/util/onboarding.service'; import { WorkerDialogComponent } from '../_dialogs/worker-dialog/worker-dialog.component'; import { PageEvent } from '@angular/material/paginator'; +import { CommentListFilter, FilterType, FilterTypeKey, SortType, SortTypeKey } from './comment-list.filter'; export interface CommentListData { currentFilter: CommentFilter; @@ -60,33 +60,9 @@ export class CommentListComponent implements OnInit, OnDestroy { deviceType: string; isSafari: string; isLoading = true; - voteasc = 'voteasc'; - votedesc = 'votedesc'; - time = 'time'; - currentSort: string; - read = 'read'; - unread = 'unread'; - favorite = 'favorite'; - correct = 'correct'; - wrong = 'wrong'; - ack = 'ack'; - bookmark = 'bookmark'; - moderator = 'moderator'; - lecturer = 'lecturer'; - tag = 'tag'; - selectedTag = ''; - userNumber = 'userNumber'; - keyword = 'keyword'; - selectedKeyword = ''; - answer = 'answer'; - unanswered = 'unanswered'; - owner = 'owner'; - currentFilter = ''; - currentFilterCompare: any = null; commentVoteMap = new Map<string, Vote>(); scroll = false; scrollExtended = false; - searchInput = ''; search = false; searchPlaceholder = ''; moderationEnabled = true; @@ -97,16 +73,13 @@ export class CommentListComponent implements OnInit, OnDestroy { commentStream: Subscription; periodsList = Object.values(Period); headerInterface = null; - period: Period = Period.twoWeeks; - fromNow: number; - moderatorIds: string[]; commentsEnabled: boolean; - userNumberSelection = 0; createCommentWrapper: CreateCommentWrapper = null; isJoyrideActive = false; focusCommentId = ''; activeUsers = 0; commentsWrittenByUsers: Map<string, Set<string>> = new Map<string, Set<string>>(); + filter: CommentListFilter; private _subscriptionEventServiceTagConfig = null; private _subscriptionEventServiceRoomData = null; private _subscriptionRoomService = null; @@ -144,9 +117,10 @@ export class CommentListComponent implements OnInit, OnDestroy { this.searchPlaceholder = msg; }); }); + this.filter = CommentListFilter.loadCurrentFilter(); } - handlePageEvent(e:PageEvent){ + handlePageEvent(e: PageEvent) { this.pageIndex = e.pageIndex; this.pageSize = e.pageSize; } @@ -239,6 +213,7 @@ export class CommentListComponent implements OnInit, OnDestroy { this.authenticationService.watchUser.subscribe(newUser => { if (newUser) { this.user = newUser; + this.filter.updateUserId(this.user.id); if (this.userRole === UserRole.PARTICIPANT) { this.voteService.getByRoomIdAndUserID(this.roomId, this.user.id).subscribe(votes => { for (const v of votes) { @@ -254,21 +229,13 @@ export class CommentListComponent implements OnInit, OnDestroy { this.authenticationService.checkAccess(this.shortId); this.authenticationService.guestLogin(UserRole.PARTICIPANT).subscribe(r => { this.roomService.getRoomByShortId(this.shortId).subscribe(room => { - this.room = room; - this.roomId = room.id; + this.receiveRoom(room); this._subscriptionRoomService = this.wsRoomService.getRoomStream(this.roomId).subscribe(msg => { const message = JSON.parse(msg.body); if (message.type === 'RoomPatched') { - this.room = message.payload.changes; - this.roomId = this.room.id; - this.moderationEnabled = this.room.moderated; - this.directSend = this.room.directSend; - this.commentsEnabled = (this.userRole > UserRole.PARTICIPANT) || !this.room.questionsBlocked; + this.receiveRoom(message.payload.changes); } }); - this.moderationEnabled = this.room.moderated; - this.directSend = this.room.directSend; - this.commentsEnabled = (this.userRole > UserRole.PARTICIPANT) || !this.room.questionsBlocked; this.createCommentWrapper = new CreateCommentWrapper(this.translateService, this.notificationService, this.commentService, this.dialog, this.room); localStorage.setItem('moderationEnabled', JSON.stringify(this.moderationEnabled)); @@ -277,8 +244,7 @@ export class CommentListComponent implements OnInit, OnDestroy { this.authenticationService.setAccess(this.shortId, UserRole.PARTICIPANT); } this.moderatorService.get(this.roomId).subscribe(list => { - this.moderatorIds = list.map(m => m.accountId); - this.moderatorIds.push(this.room.ownerId); + this.filter.updateModerators(list.map(m => m.accountId)); this.roomDataService.getRoomData(this.room.id).subscribe(comments => { if (comments === null) { @@ -295,7 +261,6 @@ export class CommentListComponent implements OnInit, OnDestroy { }); }); }); - this.currentSort = this.votedesc; this.hideCommentsList = false; this.translateService.use(localStorage.getItem('currentLang')); this.deviceType = localStorage.getItem('deviceType'); @@ -306,6 +271,7 @@ export class CommentListComponent implements OnInit, OnDestroy { } ngOnDestroy() { + this.filter.save(); if (!this.freeze && this.commentStream) { this.commentStream.unsubscribe(); } @@ -336,27 +302,26 @@ export class CommentListComponent implements OnInit, OnDestroy { searchComments(): void { this.search = true; - if (this.searchInput) { - if (this.searchInput.length > 1) { - this.hideCommentsList = true; - this.filteredComments = this.comments - .filter(c => this.checkIfIncludesKeyWord(c.body, this.searchInput) - || (!!c.answer ? this.checkIfIncludesKeyWord(c.answer, this.searchInput) : false)); - } - } else if (this.searchInput.length === 0 && this.currentFilter === '') { + if (this.filter.currentSearch) { + this.hideCommentsList = true; + this.filteredComments = this.filter.filterCommentsBySearch(this.comments); + } else if (!this.filter.filterType) { this.hideCommentsList = false; } } - checkIfIncludesKeyWord(body: string, keyword: string) { - return body.toLowerCase().includes(keyword.toLowerCase()); - } - activateSearch() { this.search = true; this.searchField.nativeElement.focus(); } + abortSearch() { + this.hideCommentsList = false; + this.filter.currentSearch = ''; + this.search = false; + this.filterComments(this.filter.filterType, this.filter.filterCompare); + } + getComments(): void { this.thresholdEnabled = !!this.room.threshold; this.isLoading = false; @@ -373,115 +338,53 @@ export class CommentListComponent implements OnInit, OnDestroy { this.dialog.closeAll(); } - filterComments(type: string, compare?: any): void { - this.pageIndex=0; - this.currentFilter = type; - this.currentFilterCompare = compare; - if (type === '') { + filterCommentsByKey(type: FilterTypeKey, compare?: any): void { + this.filterComments(FilterType[type], compare); + } + + filterComments(type: FilterType, compare?: any): void { + this.pageIndex = 0; + this.filter.filterType = type; + this.filter.filterCompare = compare; + if (!type) { this.filteredComments = this.commentsFilteredByTime; this.hideCommentsList = false; - this.currentFilter = ''; - this.selectedTag = ''; - this.selectedKeyword = ''; - this.userNumberSelection = 0; - this.sortComments(this.currentSort); + this.sortComments(this.filter.sortType); return; } - this.filteredComments = this.commentsFilteredByTime.filter(c => { - switch (type) { - case this.correct: - return c.correct === CorrectWrong.CORRECT ? 1 : 0; - case this.wrong: - return c.correct === CorrectWrong.WRONG ? 1 : 0; - case this.favorite: - return c.favorite; - case this.bookmark: - return c.bookmark; - case this.read: - return c.read; - case this.unread: - return !c.read; - case this.tag: - this.selectedTag = compare; - return c.tag === compare; - case this.userNumber: - return c.userNumber === compare; - case this.keyword: - this.selectedKeyword = compare; - const isInQuestioner = c.keywordsFromQuestioner ? c.keywordsFromQuestioner.findIndex(k => k.text === compare) >= 0 : false; - const isInSpacy = c.keywordsFromSpacy ? c.keywordsFromSpacy.findIndex(k => k.text === compare) >= 0 : false; - return isInQuestioner || isInSpacy; - case this.answer: - return c.answer; - case this.unanswered: - return !c.answer; - case this.owner: - return c.creatorId === this.user.id; - case this.moderator: - return this.moderatorIds.includes(c.creatorId); - case this.lecturer: - return c.createdFromLecturer; - } - }); - const testForModerator = () => { - this.comments.forEach(e => { - this.commentService.role(e).subscribe(i => { - console.log(e, i); - }); - }); - }; - if (type === 'moderator') { - console.log( - 'TEST moderator', - this.moderatorIds, - this.user, - this.room - ); - testForModerator(); - } + this.filteredComments = this.filter.filterCommentsByType(this.commentsFilteredByTime); this.hideCommentsList = true; - this.sortComments(this.currentSort); - } - - sort(array: any[], type: string): any[] { - const sortedArray = array.sort((a, b) => { - if (type === this.voteasc) { - return (a.score > b.score) ? 1 : (b.score > a.score) ? -1 : 0; - } else if (type === this.votedesc) { - return (b.score > a.score) ? 1 : (a.score > b.score) ? -1 : 0; - } else if (type === this.time) { - const dateA = new Date(a.timestamp); - const dateB = new Date(b.timestamp); - return (+dateB > +dateA) ? 1 : (+dateA > +dateB) ? -1 : 0; - } - }); - return sortedArray.sort((a, b) => this.isCreatedByModeratorOrCreator(a) ? -1 : this.isCreatedByModeratorOrCreator(b) ? 1 : 0); + this.sortComments(this.filter.sortType); + } + + sort(array: Comment[], type: SortType): any[] { + this.filter.sortType = type; + this.filter.sortCommentsBySortType(array); + return array; } - isCreatedByModeratorOrCreator(comment: Comment): boolean { - return this.moderatorIds.indexOf(comment.creatorId) > -1; + sortCommentsByKey(type: SortTypeKey) { + this.sortComments(SortType[type]); } - sortComments(type: string): void { + sortComments(type: SortType): void { if (this.hideCommentsList === true) { this.filteredComments = this.sort(this.filteredComments, type); } else { this.setComments(this.sort(this.commentsFilteredByTime, type)); } - this.currentSort = type; } clickedOnTag(tag: string): void { - this.filterComments(this.tag, tag); + this.filterComments(FilterType.tag, tag); } clickedOnKeyword(keyword: string): void { - this.filterComments(this.keyword, keyword); + this.filterComments(FilterType.keyword, keyword); } clickedUserNumber(usrNumber: number): void { - this.userNumberSelection = usrNumber; - this.filterComments(this.userNumber, usrNumber); + this.filterComments(FilterType.userNumber, usrNumber); } votedComment(voteInfo: string) { @@ -489,25 +392,9 @@ export class CommentListComponent implements OnInit, OnDestroy { setTimeout(() => this.focusCommentId = voteInfo, 100); } - pauseCommentStream() { - this.freeze = true; - this.roomDataService.getRoomData(this.roomId, true).subscribe(comments => { - if (comments === null) { - return; - } - this.comments = comments; - this.setComments(comments); - this.getComments(); - }); - this.commentStream.unsubscribe(); - this.translateService.get('comment-list.comment-stream-stopped').subscribe(msg => { - this.notificationService.show(msg); - }); - } - - playCommentStream() { - this.freeze = false; - this.roomDataService.getRoomData(this.roomId).subscribe(comments => { + activateCommentStream(freezed: boolean) { + this.freeze = freezed; + this.roomDataService.getRoomData(this.roomId, freezed).subscribe(comments => { if (comments === null) { return; } @@ -515,8 +402,15 @@ export class CommentListComponent implements OnInit, OnDestroy { this.setComments(comments); this.getComments(); }); - this.subscribeCommentStream(); - this.translateService.get('comment-list.comment-stream-started').subscribe(msg => { + let message: string; + if (freezed) { + this.commentStream?.unsubscribe(); + message = 'comment-list.comment-stream-stopped'; + } else { + this.subscribeCommentStream(); + message = 'comment-list.comment-stream-started'; + } + this.translateService.get(message).subscribe(msg => { this.notificationService.show(msg); }); } @@ -524,7 +418,7 @@ export class CommentListComponent implements OnInit, OnDestroy { subscribeCommentStream() { this.commentStream = this.roomDataService.receiveUpdates([ { type: 'CommentCreated', finished: true }, - { type: 'CommentPatched', subtype: this.favorite }, + { type: 'CommentPatched', subtype: 'favorite' }, { type: 'CommentPatched', subtype: 'score' }, { finished: true } ]).subscribe(update => { @@ -534,7 +428,7 @@ export class CommentListComponent implements OnInit, OnDestroy { } else if (update.type === 'CommentPatched') { if (update.subtype === 'score') { this.getComments(); - } else if (update.subtype === this.favorite) { + } else if (update.subtype === 'favorite') { if (this.user.id === update.comment.creatorId && update.comment.favorite) { this.translateService.get('comment-list.comment-got-favorited').subscribe(ret => { this.notificationService.show(ret); @@ -594,57 +488,34 @@ export class CommentListComponent implements OnInit, OnDestroy { }, 450); } - public setTimePeriod(period?: Period) { + setTimePeriod(period?: Period) { if (period) { - this.period = period; - this.fromNow = null; - } - const comments = this.thresholdEnabled ? this.comments.filter(x => x.score >= this.room.threshold) : this.comments; - const currentTime = new Date(); - const hourInSeconds = 3600000; - let periodInSeconds; - if (this.period !== Period.all) { - switch (this.period) { - case Period.fromNow: - if (!this.fromNow) { - this.fromNow = new Date().getTime(); - } - break; - case Period.oneHour: - periodInSeconds = hourInSeconds; - break; - case Period.threeHours: - periodInSeconds = hourInSeconds * 2; - break; - case Period.oneDay: - periodInSeconds = hourInSeconds * 24; - break; - case Period.oneWeek: - periodInSeconds = hourInSeconds * 168; - break; - case Period.twoWeeks: - periodInSeconds = hourInSeconds * 336; - break; - } - this.commentsFilteredByTime = comments - .filter(c => new Date(c.timestamp).getTime() >= - (this.period === Period.fromNow ? this.fromNow : (currentTime.getTime() - periodInSeconds))); - } else { - this.commentsFilteredByTime = comments; + this.filter.period = period; + this.filter.fromNow = null; } + this.commentsFilteredByTime = this.filter.filterCommentsByTime(this.comments); - this.filterComments(this.currentFilter, this.currentFilterCompare); + this.filterComments(this.filter.filterType, this.filter.filterCompare); this.titleService.attachTitle('(' + this.commentsFilteredByTime.length + ')'); } + private receiveRoom(room: Room) { + this.room = room; + this.filter.updateRoom(room); + this.roomId = room.id; + this.moderationEnabled = room.moderated; + this.directSend = room.directSend; + this.commentsEnabled = (this.userRole > UserRole.PARTICIPANT) || !room.questionsBlocked; + } + private getCurrentFilter(): CommentFilter { const filter = new CommentFilter(); - filter.filterSelected = this.currentFilter; + filter.filterSelected = this.filter.filterType; filter.paused = this.freeze; - filter.periodSet = this.period; - filter.keywordSelected = this.selectedKeyword; - filter.tagSelected = this.selectedTag; - filter.userNumberSelected = this.userNumberSelection; + filter.periodSet = this.filter.period; + filter.keywordSelected = this.filter.filterCompare; + filter.tagSelected = this.filter.filterCompare; + filter.userNumberSelected = this.filter.filterCompare; if (filter.periodSet === Period.fromNow) { filter.timeStampNow = new Date().getTime(); diff --git a/src/app/components/shared/comment-list/comment-list.filter.ts b/src/app/components/shared/comment-list/comment-list.filter.ts new file mode 100644 index 0000000000000000000000000000000000000000..20892f98b9c203758dd46d0efa6f6041260f5b9d --- /dev/null +++ b/src/app/components/shared/comment-list/comment-list.filter.ts @@ -0,0 +1,247 @@ +import { Period } from '../../../utils/filter-options'; +import { Comment } from '../../../models/comment'; +import { CorrectWrong } from '../../../models/correct-wrong.enum'; +import { Room } from '../../../models/room'; + +export enum FilterType { + voteasc = 'voteasc', + votedesc = 'votedesc', + time = 'time', + read = 'read', + unread = 'unread', + favorite = 'favorite', + correct = 'correct', + wrong = 'wrong', + ack = 'ack', + bookmark = 'bookmark', + moderator = 'moderator', + lecturer = 'lecturer', + tag = 'tag', + userNumber = 'userNumber', + keyword = 'keyword', + answer = 'answer', + unanswered = 'unanswered', + owner = 'owner', +} + +export type FilterTypeKey = keyof typeof FilterType; + +export enum SortType { + voteasc = 'voteasc', + votedesc = 'votedesc', + time = 'time' +} + +export type SortTypeKey = keyof typeof SortType; + +const DEFAULT_PERIOD = Period.all; +const DEFAULT_SORT = SortType.time; + +export class CommentListFilter { + //own properties + period: Period; + fromNow: number; + filterType: FilterType; + filterCompare: any; + sortType: SortType; + currentSearch: string; + //dependencies to other values + private userId: string; + private moderatorIds: Set<string>; + private threshold: number; + private ownerId: string; + private lastRoomId: string; + + constructor(obj) { + if (!obj) { + this.resetToDefault(); + return; + } + this.period = obj.period; + this.fromNow = obj.fromNow; + this.filterType = obj.filterType; + this.filterCompare = obj.filterCompare; + this.sortType = obj.sortType; + this.currentSearch = obj.currentSearch; + } + + static loadCurrentFilter(): CommentListFilter { + return new CommentListFilter(JSON.parse(localStorage.getItem('currentFilter'))); + } + + resetToDefault() { + this.period = DEFAULT_PERIOD; + this.fromNow = null; + this.filterType = null; + this.filterCompare = null; + this.sortType = DEFAULT_SORT; + this.currentSearch = ''; + } + + updateRoom(room: Room) { + if (room.id !== this.lastRoomId) { + this.resetToDefault(); + } + this.ownerId = room.ownerId; + this.lastRoomId = room.id; + this.threshold = room.threshold; + } + + updateUserId(userId: string) { + this.userId = userId; + } + + updateModerators(moderators: string[]) { + this.moderatorIds = new Set<string>([...moderators]); + } + + save() { + const ownerId = this.ownerId; + const threshold = this.threshold; + const userId = this.userId; + const moderatorIds = this.moderatorIds; + this.ownerId = this.threshold = this.userId = this.moderatorIds = undefined; + localStorage.setItem('currentFilter', JSON.stringify(this)); + this.ownerId = ownerId; + this.threshold = threshold; + this.userId = userId; + this.moderatorIds = moderatorIds; + } + + get thresholdEnabled() { + return !!this.threshold; + } + + filterCommentsBySearch(comments: Comment[]): Comment[] { + const search = this.currentSearch.toLowerCase(); + return comments + .filter(c => + c.body.toLowerCase().includes(search) || + c.answer?.toLowerCase().includes(search) || + c.keywordsFromSpacy?.some(e => e.text.toLowerCase().includes(search)) || + c.keywordsFromQuestioner?.some(e => e.text.toLowerCase().includes(search)) || + c.questionerName?.toLowerCase().includes(search) + ); + } + + filterCommentsByTime(comments: Comment[], moderation = false): Comment[] { + const thresholdComments = + this.thresholdEnabled && !moderation ? comments.filter(comment => comment.score >= this.threshold) : comments; + if (this.period === null || this.period === undefined) { + this.period = DEFAULT_PERIOD; + } + if (this.period === Period.all) { + return thresholdComments; + } + const currentTime = new Date().getTime(); + let periodInSeconds; + const hourInSeconds = 3_600_000; + switch (this.period) { + case Period.fromNow: + if (!this.fromNow) { + this.fromNow = currentTime; + } + break; + case Period.oneHour: + periodInSeconds = hourInSeconds; + break; + case Period.threeHours: + periodInSeconds = hourInSeconds * 3; + break; + case Period.oneDay: + periodInSeconds = hourInSeconds * 24; + break; + case Period.oneWeek: + periodInSeconds = hourInSeconds * 168; + break; + case Period.twoWeeks: + periodInSeconds = hourInSeconds * 336; + break; + default: + throw new Error('Time period is invalid.'); + } + const filterTime = (this.period === Period.fromNow ? this.fromNow : currentTime - periodInSeconds); + return thresholdComments.filter(c => new Date(c.timestamp).getTime() >= filterTime); + } + + filterCommentsByType(comment: Comment[]): Comment[] { + let filterFunc: (c: Comment) => boolean; + switch (this.filterType) { + case FilterType.correct: + filterFunc = (c) => c.correct === CorrectWrong.CORRECT; + break; + case FilterType.wrong: + filterFunc = (c) => c.correct === CorrectWrong.WRONG; + break; + case FilterType.favorite: + filterFunc = (c) => c.favorite; + break; + case FilterType.bookmark: + filterFunc = (c) => c.bookmark; + break; + case FilterType.read: + filterFunc = (c) => c.read; + break; + case FilterType.unread: + filterFunc = (c) => !c.read; + break; + case FilterType.tag: + filterFunc = (c) => c.tag === this.filterCompare; + break; + case FilterType.userNumber: + filterFunc = (c) => c.userNumber === this.filterCompare; + break; + case FilterType.keyword: + filterFunc = (c) => !!(c.keywordsFromQuestioner?.find(k => k.text === this.filterCompare) || + c.keywordsFromSpacy?.find(k => k.text === this.filterCompare)); + break; + case FilterType.answer: + filterFunc = (c) => !!c.answer; + break; + case FilterType.unanswered: + filterFunc = (c) => !c.answer; + break; + case FilterType.owner: + filterFunc = (c) => c.creatorId === this.userId; + break; + case FilterType.moderator: + filterFunc = (c) => this.moderatorIds.has(c.creatorId); + break; + case FilterType.lecturer: + filterFunc = (c) => c.creatorId === this.ownerId; + break; + default: + return comment; + } + return comment.filter(filterFunc); + } + + sortCommentsBySortType(comments: Comment[]): Comment[] { + let sortFunc: (a: Comment, b: Comment) => number; + switch (this.sortType) { + case SortType.voteasc: + sortFunc = (a, b) => a.score - b.score; + break; + case SortType.votedesc: + sortFunc = (a, b) => b.score - a.score; + break; + case SortType.time: + sortFunc = (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(); + break; + } + if (sortFunc) { + comments.sort(sortFunc); + } + comments.sort((a, b) => this.getCommentRoleValue(b) - this.getCommentRoleValue(a)); + return comments; + } + + private getCommentRoleValue(comment: Comment): number { + if (comment.creatorId === this.ownerId) { + return 2; + } else if (this.moderatorIds.has(comment.creatorId)) { + return 1; + } + return 0; + } +} diff --git a/src/app/services/util/room-data.service.ts b/src/app/services/util/room-data.service.ts index 6465af45aae2340bb87019aba083f63e19e2a12f..59271f5523ba2450994f66340ef43aba778927cd 100644 --- a/src/app/services/util/room-data.service.ts +++ b/src/app/services/util/room-data.service.ts @@ -13,7 +13,7 @@ import { SpacyKeyword } from '../http/spacy.service'; export interface UpdateInformation { type: 'CommentCreated' | 'CommentPatched' | 'CommentHighlighted' | 'CommentDeleted'; - subtype?: string; + subtype?: (keyof Comment); comment: Comment; finished?: boolean; updates?: (keyof Comment)[]; @@ -100,7 +100,7 @@ export class RoomDataService { private _currentSubscriptions: RoomDataUpdateSubscription[] = []; private _currentComments: Comment[] = null; - private _commentUpdates: BehaviorSubject<Comment[]> = new BehaviorSubject<Comment[]>(null); + private _currentRoomComments: BehaviorSubject<Comment[]> = new BehaviorSubject<Comment[]>(null); private _fastCommentAccess: FastRoomAccessObject = null; private _wsCommentServiceSubscription: Subscription = null; private _currentRoomId: string = null; @@ -140,10 +140,10 @@ export class RoomDataService { getRoomData(roomId: string, freezed: boolean = false): Observable<Comment[]> { const tempSubject = new BehaviorSubject<Comment[]>(null); if (this._currentRoomId !== roomId) { - this._commentUpdates.next(null); + this._currentRoomComments.next(null); } let subscription: Subscription = null; - subscription = this._commentUpdates.subscribe(comments => { + subscription = this._currentRoomComments.subscribe(comments => { if (comments === null) { return; } @@ -287,7 +287,7 @@ export class RoomDataService { private triggerUpdate(type: UpdateType, additionalInformation: UpdateInformation) { if (type === UpdateType.force) { - this._commentUpdates.next(this._currentComments); + this._currentRoomComments.next(this._currentComments); } else if (type === UpdateType.commentStream) { for (const subscription of this._currentSubscriptions) { subscription.onUpdate(additionalInformation); diff --git a/src/app/utils/create-comment-keywords.ts b/src/app/utils/create-comment-keywords.ts index 9ba833a870ee2d266fa01a7abe411d47f1c6060c..26cc24f06f3c2928e1fa1a81aac54a39dbe5d477 100644 --- a/src/app/utils/create-comment-keywords.ts +++ b/src/app/utils/create-comment-keywords.ts @@ -91,7 +91,6 @@ export class CreateCommentKeywords { const wordCount = text.trim().split(' ').length; const hasConfidence = selectedLanguage === 'auto' ? result.language.detectedLanguage.confidence >= 0.5 : true; const errorQuotient = (result.matches.length * 100) / wordCount; - console.log(errorQuotient); if (!hasConfidence || errorQuotient > ERROR_QUOTIENT_USE_DEEPL || (!useDeepl && errorQuotient > ERROR_QUOTIENT_WELL_SPELLED)) {