Skip to content
Snippets Groups Projects
question-wall.component.ts 11.7 KiB
Newer Older
import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { CommentService } from '../../../../services/http/comment.service';
import { Comment } from '../../../../models/comment';
import { RoomService } from '../../../../services/http/room.service';
import { Room } from '../../../../models/room';
import { WsCommentServiceService } from '../../../../services/websockets/ws-comment-service.service';
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';
import { LanguageService } from '../../../../services/util/language.service';
import { TranslateService } from '@ngx-translate/core';
import { Rescale } from '../../../../models/rescale';
import { QuestionWallKeyEventSupport } from '../QuestionWallKeyEventSupport';
Lukas Haase's avatar
Lukas Haase committed
import { CorrectWrong } from '../../../../models/correct-wrong.enum';
Lukas Haase's avatar
Lukas Haase committed
import { MatSliderChange } from '@angular/material/slider';
Davut Beyazit's avatar
Davut Beyazit committed
import { Period } from '../../../../utils/filter-options';

@Component({
  selector: 'app-question-wall',
  templateUrl: './question-wall.component.html',
  styleUrls: ['./question-wall.component.scss']
})
export class QuestionWallComponent implements OnInit, AfterViewInit, OnDestroy {

Ruben Bimberg's avatar
Ruben Bimberg committed
  @ViewChild(ColComponent) colComponent: ColComponent;
  roomId: string;
  room: Room;
  commentsFilteredByTime: QuestionWallComment[] = [];
  commentsFilter: QuestionWallComment[] = [];
Ruben Bimberg's avatar
Ruben Bimberg committed
  commentsCountQuestions = 0;
  commentsCountUsers = 0;
  focusIncommingComments = true;
  keySupport: QuestionWallKeyEventSupport;
Lukas Haase's avatar
Lukas Haase committed
  filterTitle = '';
  filterDesc = '';
  filterIcon = '';
  isSvgIcon = false;
  filterFunction: (x: QuestionWallComment) => boolean;
Lukas Haase's avatar
Lukas Haase committed
  userMap: Map<number, number> = new Map<number, number>();
  userList = [];
  userSelection = false;
  periodsList = Object.values(Period);
  period: Period = Period.ALL;
  public wrap<E>(e: E, action: (e: E) => void) {
  public notUndefined<E>(e: E, action: (e: E) => void, elsePart?: () => void) {
Ruben Bimberg's avatar
Ruben Bimberg committed
    if (e) {
      action(e);
    } else if (elsePart) {
      elsePart();
    }
    private authenticationService: AuthenticationService,
    private commentService: CommentService,
    private wsCommentService: WsCommentServiceService,
    private langService: LanguageService,
    private translateService: TranslateService
    this.keySupport = new QuestionWallKeyEventSupport();
    this.roomId = localStorage.getItem('roomId');
    this.timeUpdateInterval = setInterval(() => {
      this.comments.forEach(e => e.updateTimeAgo());
    }, 15000);
    this.langService.langEmitter.subscribe(lang => {
      this.translateService.use(lang);
      QuestionWallComment.updateTimeFormat(lang);
    });
    QuestionWallComment.updateTimeFormat(localStorage.getItem('currentLang'));
    this.translateService.use(localStorage.getItem('currentLang'));
    this.commentService.getAckComments(this.roomId).subscribe(e => {
Lukas Haase's avatar
Lukas Haase committed
      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);
        this.setTimePeriod(this.period);
Ruben Bimberg's avatar
Ruben Bimberg committed
      this.updateCommentsCountOverview();
    });
    this.roomService.getRoom(this.roomId).subscribe(e => {
      this.room = e;
      this.tags = e.tags;
    this.wsCommentService.getCommentStream(this.roomId).subscribe(e => {
      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);
            }
          });
        });
Ruben Bimberg's avatar
Ruben Bimberg committed
  updateCommentsCountOverview(): void {
    const tempUserSet = new Set();
    const comments = this.getCurrentCommentList();
    comments.forEach((wallComment) => tempUserSet.add(wallComment.comment.userNumber));
    this.commentsCountQuestions = comments.length;
    this.commentsCountUsers = tempUserSet.size;
  }

  initKeySupport() {
    this.wrap(this.keySupport, key => {
      key.addKeyEvent('ArrowRight', () => this.nextComment());
      key.addKeyEvent('ArrowLeft', () => this.prevComment());
      key.addKeyEvent(' ', () => this.nextComment());
    });
  }

  ngAfterViewInit(): void {
    document.getElementById('header_rescale').style.display = 'none';
    document.getElementById('footer_rescale').style.display = 'none';
    setTimeout(() => {
      Rescale.requestFullscreen();
    }, 10);
    window.clearInterval(this.timeUpdateInterval);
    document.getElementById('header_rescale').style.display = 'block';
    document.getElementById('footer_rescale').style.display = 'block';
    Rescale.exitFullscreen();
  nextComment() {
    this.moveComment(1);
  }

  prevComment() {
    this.moveComment(-1);
  }

  getDOMComments() {
    return Array.from(document.getElementsByClassName('questionwall-comment-anchor'));
  }

  getDOMCommentFocus() {
    return this.getDOMComments()[this.getCommentFocusIndex()];
  }

  getCommentFocusIndex() {
    return this.getCurrentCommentList().indexOf(this.commentFocus);
    if (this.commentsFilteredByTime.length === 0) {
      this.focusComment(this.commentsFilteredByTime[0]);
      const cursor = this.getCommentFocusIndex();
      if (cursor + fx >= this.commentsFilteredByTime.length || cursor + fx < 0) {
        this.focusComment(this.commentsFilteredByTime[cursor + fx]);
      }
    }
  }

  pushIncommingComment(comment: Comment): QuestionWallComment {
    const qwComment = new QuestionWallComment(comment, false);
Lukas Haase's avatar
Lukas Haase committed
    this.comments = [qwComment, ...this.comments];
    this.setTimePeriod(this.period);
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
    return qwComment;
  }

  focusComment(comment: QuestionWallComment) {
    this.commentFocus = comment;
    if (!comment.old) {
      comment.old = true;
      this.unreadComments--;
    }
    this.getDOMCommentFocus().scrollIntoView({
      behavior: 'smooth',
      block: 'center'
    });
  toggleFocusIncommingComments() {
    this.focusIncommingComments = !this.focusIncommingComments;
  }

Lukas Haase's avatar
Lukas Haase committed
  createUserMap() {
    this.userMap = new Map();
    this.commentsFilteredByTime.forEach(c => {
Lukas Haase's avatar
Lukas Haase committed
      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() {
Ruben Bimberg's avatar
Ruben Bimberg committed
    if (this.userSelection) {
      return;
    }
Lukas Haase's avatar
Lukas Haase committed
    this.hasFilter = false;
Lukas Haase's avatar
Lukas Haase committed
    this.createUserMap();
    this.userSelection = true;
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
Lukas Haase's avatar
Lukas Haase committed
  }

  cancelUserMap() {
    this.userSelection = false;
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
  leave() {
    document.getElementById('back-button').click();
  }

  likeComment(comment: QuestionWallComment) {
Tom Käsler's avatar
Tom Käsler committed
    this.commentService.voteUp(comment.comment, this.authenticationService.getUser().id).subscribe();
  dislikeComment(comment: QuestionWallComment) {
Tom Käsler's avatar
Tom Käsler committed
    this.commentService.voteDown(comment.comment, this.authenticationService.getUser().id).subscribe();
  sortScore(reverse?: boolean) {
    this.sort((a, b) => a.comment.score - b.comment.score, reverse);
  }

  sortTime(reverse?: boolean) {
    this.sort((a, b) => new Date(a.comment.timestamp).getTime() - new Date(b.comment.timestamp).getTime(), reverse);
  }

  sort(fun: (a, b) => number, reverse: boolean) {
    const commentList = this.getCurrentCommentList();
      commentList.sort(this.reverse(fun));
      if (commentList.length > 1) {
Lukas Haase's avatar
Lukas Haase committed
        this.focusComment(commentList[0]);
  getCurrentCommentList() {
    if (this.hasFilter) {
      return this.commentsFilter;
    } else {
      return this.commentsFilteredByTime;
  reverse(fun: (a, b) => number): (a, b) => number {
    return (a, b) => fun(b, a);
  }

Klaus-Dieter Quibeldey-Cirkel's avatar
Klaus-Dieter Quibeldey-Cirkel committed
    this.filter('grade', false, 'question-wall.filter-favorite', '',
Ruben Bimberg's avatar
Ruben Bimberg committed
      x => x.comment.favorite);
  }

  filterUser(comment: QuestionWallComment) {
Lukas Haase's avatar
Lukas Haase committed
    this.filterUserByNumber(comment.comment.userNumber);
  }

  filterUserByNumber(user: number) {
    this.filter('person_pin_circle', false, 'question-wall.filter-user', user + '',
Lukas Haase's avatar
Lukas Haase committed
      x => x.comment.userNumber === user);
  }

Philipp Sautner's avatar
Philipp Sautner committed
  filterBookmark() {
    this.filter('bookmark', false, 'question-wall.filter-bookmark', '',
Ruben Bimberg's avatar
Ruben Bimberg committed
      x => x.comment.bookmark);
  filterTag(tag: string) {
    this.filter('comment_tag', true, '', tag, x => x.comment.tag === tag);
  }

  filter(icon: string, isSvgIcon: boolean, title: string, desc: string, filter: (x: QuestionWallComment) => boolean) {
    this.cancelUserMap();
Lukas Haase's avatar
Lukas Haase committed
    this.filterIcon = icon;
    this.isSvgIcon = isSvgIcon;
Lukas Haase's avatar
Lukas Haase committed
    this.filterTitle = title;
    this.filterDesc = desc;
    this.filterFunction = filter;
    this.commentsFilter = this.commentsFilteredByTime.filter(this.filterFunction);
    setTimeout(() => {
      if (this.commentsFilter.length <= 0) {
        this.commentFocus = null;
      } else {
        this.focusFirstComment();
      }
    }, 0);
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
Lukas Haase's avatar
Lukas Haase committed
  }

  focusFirstComment() {
    if (this.getCurrentCommentList().length > 0) {
      this.commentFocus = this.getCurrentCommentList()[0];
    }
  }

  deactivateFilter() {
    this.hasFilter = false;
    this.filterFunction = null;
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
  }

  toggleFilter() {
    this.hasFilter = !this.hasFilter;
Ruben Bimberg's avatar
Ruben Bimberg committed
    this.updateCommentsCountOverview();
Lukas Haase's avatar
Lukas Haase committed
  sliderChange(evt: MatSliderChange) {
    this.fontSize = evt.value;
  }

  setTimePeriod(period: Period) {
    this.period = period;
    const currentTime = new Date();
    const hourInSeconds = 3600000;
    let periodInSeconds;
    if (period !== Period.ALL) {
      switch (period) {
        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.date).getTime() >= (currentTime.getTime() - periodInSeconds));
    } else {
      this.commentsFilteredByTime = this.comments;
    }
    if (this.filterFunction) {
      this.filter(this.filterIcon, this.isSvgIcon, this.filterTitle, this.filterDesc, this.filterFunction);
Ruben Bimberg's avatar
Ruben Bimberg committed
    } else {
      this.updateCommentsCountOverview();