Skip to content
Snippets Groups Projects
question-wall.component.ts 12.8 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 { WsCommentService } from '../../../../services/websockets/ws-comment.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 { MatSliderChange } from '@angular/material/slider';
import { RoomDataService } from '../../../../services/util/room-data.service';
import { Period } from '../../comment-list/comment-list.filter';
import { User } from '../../../../models/user';

@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;
  @ViewChild('sidelist') sidelist: ColComponent;
  qrCodeExpanded: boolean = false;
  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;
  isLoading = true;
  user: User;
    private authenticationService: AuthenticationService,
    private commentService: CommentService,
    private wsCommentService: WsCommentService,
    private langService: LanguageService,
    private translateService: TranslateService,
    private roomDataService: RoomDataService
    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);
    });
  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();
    }
  }

  toggleSideList(){
    this.sidelistExpanded=!this.sidelistExpanded;
    if(this.sidelistExpanded){
      this.sidelist.setPx(450);
    }
    else{
      this.sidelist.setPx(0);
    }
  }

  getURL(){
    if(!this.room)return '';
    return `${window.location.protocol}//${window.location.hostname}/participant/room/${this.room.shortId}`;
  }

  toggleQRCode(){
    this.qrCodeExpanded=!this.qrCodeExpanded;
  }

    QuestionWallComment.updateTimeFormat(localStorage.getItem('currentLang'));
    this.translateService.use(localStorage.getItem('currentLang'));
    this.authenticationService.watchUser.subscribe(newUser => {
      if (newUser) {
        this.user = newUser;
      }
    });
    this.roomDataService.getRoomData(this.roomId).subscribe(e => {
Ruben Bimberg's avatar
Ruben Bimberg committed
      if (e === null) {
        return;
      }
Lukas Haase's avatar
Lukas Haase committed
      e.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
      this.isLoading = false;
        const comment = new QuestionWallComment(c, true);
        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.subscribeCommentStream();
    this.initKeySupport();
  }

  subscribeCommentStream() {
    this.roomDataService.receiveUpdates([
      { type: 'CommentCreated', finished: true},
      { type: 'CommentPatched', finished: true, updates: ['upvotes'] },
      { type: 'CommentPatched', finished: true, updates: ['downvotes'] },
      {finished: true}
    ]).subscribe(update => {
      if (update.type === 'CommentCreated') {
        this.wrap(this.pushIncommingComment(update.comment), qwComment => {
          if (this.focusIncommingComments) {
            setTimeout(() => this.focusComment(qwComment), 5);
          }
      } else if (update.type === 'CommentPatched') {
        const qwComment = this.comments.find(f => f.comment.id === update.comment.id);
        qwComment.comment = update.comment;
      }
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 => {
Lukas Haase's avatar
Lukas Haase committed
      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 {
    this.roomDataService.checkProfanity(comment);
    console.log(comment);
    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) {
    this.commentService.voteUp(comment.comment, this.user.id).subscribe();
  dislikeComment(comment: QuestionWallComment) {
    this.commentService.voteDown(comment.comment, this.user.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) {
        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;
        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();