Cloud-CV/EvalAI

View on GitHub
frontend_v2/src/app/components/publiclists/challengelist/challengelist.component.ts

Summary

Maintainability
C
1 day
Test Coverage
import { Component, HostListener, Inject, OnInit } from '@angular/core';
import { ApiService } from '../../../services/api.service';
import { GlobalService } from '../../../services/global.service';
import { AuthService } from '../../../services/auth.service';
import { EndpointsService } from '../../../services/endpoints.service';
import { Router } from '@angular/router';
import { DOCUMENT } from '@angular/common';

/**
 * Component Class
 */
@Component({
  selector: 'app-challengelist',
  templateUrl: './challengelist.component.html',
  styleUrls: ['./challengelist.component.scss'],
})
export class ChallengelistComponent implements OnInit {
  /**
   * Filter toggle flag
   */
  isUpcomingChecked = true;

  /**
   * Filter toggle flag
   */
  isOngoingChecked = true;

  /**
   * Filter toggle flag
   */
  isPastChecked = true;

  /**
   * Upcoming challenges list
   */
  upcomingChallenges = [];

  /**
   * Ongoing challenges list
   */
  ongoingChallenges = [];

  /**
   * Past challeges list
   */
  pastChallenges = [];

  /**
   * Unapproved challeges list
   */
  unapprovedChallengeList = [];

  /**
   * API common path
   */
  apiPathCommon = 'challenges/challenge/';

  /**
   * participated challenges API common path
   */
  newApiPathCommon = 'challenges/challenges/';

  /**
   * Host teams API common path
   */
  hostTeamsapiPathCommon = 'hosts/challenge_host_team';

  /**
   * API path mapping
   */
  apiPathMapping = {
    isUpcomingChecked: this.apiPathCommon + 'future',
    isOngoingChecked: this.apiPathCommon + 'present',
    isPastChecked: this.apiPathCommon + 'past',
  };

  /**
   * API path mapping
   */
  newApiPathMapping = {
    isOngoingChecked: this.newApiPathCommon + 'participated/' + 'present/',
    isPastChecked: this.newApiPathCommon + 'participated/' + 'past/',
  };

  /**
   * List of filtered challenges
   */
  filteredChallenges = [];

  /**
   * List of filtered ongoing challenges
   */
  filteredOngoingChallenges = [];

  /**
   * List of filtered upcoming challenges
   */
  filteredUpcomingChallenges = [];

  /**
   * List of filtered past challenges
   */
  filteredPastChallenges = [];

  /**
   * List of filtered-further challenges
   */
  filteredChallengesView = [];

  /**
   * Team list
   */
  allTeams = [];

  /**
   * Display more frames of teams
   */
  seeMore = 1;

  /**
   * Frame size
   */
  windowSize = 10;

  /**
   * Auth service public instance
   */
  authServicePublic: AuthService;

  /**
   * Router public instance
   */
  routerPublic: Router;

  /**
   * Is user Logged in
   */
  isLoggedIn: any = false;

  /**
   * Is scroll button visible
   */
  isScrollbtnVisible = false;

  /**
   * Authentication Service subscription
   */
  authServiceSubscription: any;

  /**
   * All challenges common route path
   */
  allChallengesRoutePathCommon = '/challenges/all';

  /**
   * My challenges common route path
   */
  myChallengesRoutePathCommon = '/challenges/me';

  /**
   * My participated challenges common route path
   */
  myParticipatedChallengesRoutePathCommon = '/challenges/participated';

  /**
   * Host teams common route path
   */
  hostTeamsRoutePathCommon = '/teams/hosts';

  /**
   * Challenge common path
   */
  challengeRoutePathCommon = '/challenge';

  /**
   * Auth common route path
   */
  authRoutePathCommon = '/auth/';

  /**
   * Constructor.
   * @param apiService  ApiService Injection.
   * @param authService  AuthService Injection.
   * @param globalService  GlobalService Injection.
   * @param endpointsService  EndpointsService Injection.
   * @param router  Router Injection.
   * @param document
   */
  constructor(
    private apiService: ApiService,
    private authService: AuthService,
    private globalService: GlobalService,
    private endpointsService: EndpointsService,
    private router: Router,
    @Inject(DOCUMENT) private document
  ) {}

  /**
   * Component on intialized.
   */
  ngOnInit() {
    if (this.authService.isLoggedIn()) {
      this.isLoggedIn = true;
    }

    this.authServiceSubscription = this.authService.change.subscribe((authState) => {
      this.isLoggedIn = authState.isLoggedIn;
      if (!authState.isLoggedIn && this.router.url === this.myChallengesRoutePathCommon) {
        this.router.navigate([`${this.authRoutePathCommon}login`]);
      } else if (!authState.isLoggedIn && this.router.url === this.myParticipatedChallengesRoutePathCommon) {
        this.router.navigate([`${this.authRoutePathCommon}login`]);
      }
    });

    if (this.router.url === this.allChallengesRoutePathCommon) {
      this.fetchChallenges();
    } else if (this.router.url === this.myChallengesRoutePathCommon && this.authService.isLoggedIn()) {
      this.fetchMyTeams();
    } else if (this.router.url === this.myParticipatedChallengesRoutePathCommon && this.authService.isLoggedIn()) {
      this.fetchMyParticipatedChallenges();
    }

    this.authServicePublic = this.authService;
    this.routerPublic = this.router;
  }

  /**
   * Listener for page scroll event
   */
  @HostListener('window:scroll', [])
  onWindowScroll(): void {
    if (this.document.getElementById('ongoing-challenges')) {
      const RECT = this.document.getElementById('ongoing-challenges').getBoundingClientRect();
      this.isScrollbtnVisible = RECT.top < 0;
    }
  }

  /**
   * Fetch teams function.
   */
  fetchMyTeams() {
    this.fetchTeams(this.hostTeamsapiPathCommon);
  }

  /**
   * Fetch participated challenges function.
   * @param filter  selected filter
   * @param callback  callback function
   */
  fetchMyParticipatedChallenges(filter = null, callback = null) {
    const SELF = this;
    if (!filter) {
      const ALL_PATHS = Object.values(SELF.newApiPathMapping);
      const ALL_KEYS = Object.keys(SELF.newApiPathMapping);
      for (let i = 0; i < ALL_PATHS.length; i++) {
        if (SELF[ALL_KEYS[i]]) {
          SELF.fetchParticipatedChallengesFromApi(ALL_PATHS[i], callback);
        }
      }
    } else {
      SELF.fetchParticipatedChallengesFromApi(SELF.newApiPathMapping[filter], callback);
    }
  }

  /**
   * Toggle upcoming/past/ongoing filters.
   * @param filter  selected filter
   */
  toggleFilter(filter) {
    this[filter] = !this[filter];
    if (this[filter]) {
      this.fetchChallenges(filter);
    } else {
      this.upcomingChallenges = filter === 'isUpcomingChecked' ? [] : this.upcomingChallenges;
      this.ongoingChallenges = filter === 'isOngoingChecked' ? [] : this.ongoingChallenges;
      this.pastChallenges = filter === 'isPastChecked' ? [] : this.pastChallenges;
      this.filteredChallenges = this.upcomingChallenges.concat(this.ongoingChallenges, this.pastChallenges);
      this.filteredOngoingChallenges = this.ongoingChallenges;
      this.filteredUpcomingChallenges = this.upcomingChallenges;
      this.filteredPastChallenges = this.pastChallenges;
      this.updateChallengesView(true);
    }
  }

  /**
   * Show more results.
   */
  seeMoreClicked() {
    this.seeMore = this.seeMore + 1;
    this.updateChallengesView(false);
  }

  /**
   * Update challenges view (called after fetching challenges from API).
   * @param reset  reset flag for hiding/showing more results
   */
  updateChallengesView(reset) {
    if (reset) {
      this.seeMore = 1;
    }
    this.filterChallengesByTeams();
    this.filteredChallengesView = this.filteredChallenges.slice(0, this.seeMore * this.windowSize);
  }

  /**
   * Filtering challenges by teams
   */
  filterChallengesByTeams() {
    if (this.router.url === this.myChallengesRoutePathCommon && this.authService.isLoggedIn()) {
      this.filteredChallenges = this.filteredChallenges.filter(
        (v, i, a) => this.allTeams.indexOf(v['creator']['id']) > -1
      );
      this.filteredOngoingChallenges = this.filteredOngoingChallenges.filter(
        (v, i, a) => this.allTeams.indexOf(v['creator']['id']) > -1
      );
      this.filteredUpcomingChallenges = this.filteredUpcomingChallenges.filter(
        (v, i, a) => this.allTeams.indexOf(v['creator']['id']) > -1
      );
      this.filteredPastChallenges = this.filteredPastChallenges.filter(
        (v, i, a) => this.allTeams.indexOf(v['creator']['id']) > -1
      );
    }
  }

  /**
   * Fetch teams function.
   * @param path  teams fetch URL
   */
  fetchTeams(path) {
    const SELF = this;
    SELF.filteredChallenges = [];
    this.apiService.getUrl(path, true, false).subscribe(
      (data) => {
        if (data['results']) {
          const TEAMS = data['results'].map((item) => item['id']);
          SELF.allTeams = SELF.allTeams.concat(TEAMS);
          SELF.allTeams = SELF.allTeams.filter((v, i, a) => a.indexOf(v) === i);
          SELF.allTeams.forEach((team) => {
            SELF.fetchUnapprovedChallengesFromApi(team);
          });
          SELF.fetchChallenges(null, null, "approved", "all");
        }
      },
      (err) => {
        if (err.status === 403) {
          this.router.navigate(['permission-denied']);
        }
        SELF.globalService.handleApiError(err, false);
      },
      () => {}
    );
  }

  /**
   * Append visibility to challenge API
   * @param approved_status 
   * @param visibility 
   */
  getFetchChallengeApiPathWithVisibility(path, approved_status = "approved", visibility = "public") {
    return path + "/" + approved_status + "/" + visibility;
  }

  /**
   * Fetch Challenges function.
   * @param filter  selected filter
   * @param callback  callback function
   */
  fetchChallenges(filter = null, callback = null, approved_status = "approved", visibility = "public") {
    if (!filter) {
      const ALL_PATHS = Object.values(this.apiPathMapping);
      const ALL_KEYS = Object.keys(this.apiPathMapping);
      for (let i = 0; i < ALL_PATHS.length; i++) {
        if (this[ALL_KEYS[i]]) {
          let apiPath = this.getFetchChallengeApiPathWithVisibility(ALL_PATHS[i], approved_status, visibility);
          this.fetchChallengesFromApi(apiPath, callback);
        }
      }
    } else {
      let apiPath = this.getFetchChallengeApiPathWithVisibility(this.apiPathMapping[filter], approved_status, visibility);
      this.fetchChallengesFromApi(apiPath, callback);
    }
  }

  /**
   * Fetch challenges from backend.
   * @param path  Challenge fetch URL
   * @param callback  Callback Function.
   */
  fetchChallengesFromApi(path, callback = null) {
    const SELF = this;
    SELF.apiService.getUrl(path, true, false).subscribe(
      (data) => {
        if (path.includes('future')) {
          SELF.upcomingChallenges = data['results'];
        } else if (path.includes('present')) {
          SELF.ongoingChallenges = data['results'];
        } else if (path.includes('past')) {
          SELF.pastChallenges = data['results'];
        }
        SELF.filteredChallenges = SELF.upcomingChallenges.concat(SELF.ongoingChallenges, SELF.pastChallenges);
        SELF.filteredOngoingChallenges = SELF.ongoingChallenges;
        SELF.filteredUpcomingChallenges = SELF.upcomingChallenges;
        SELF.filteredPastChallenges = SELF.pastChallenges;
        this.updateChallengesView(true);
      },
      (err) => {
        SELF.globalService.handleApiError(err);
      },
      () => {}
    );
  }

  /**
   * Fetch participated challenges from backend.
   * @param path  Challenge fetch URL
   * @param callback  Callback Function.
   */
  fetchParticipatedChallengesFromApi(path, callback = null) {
    const SELF = this;
    SELF.apiService.getUrl(path, true, false).subscribe(
      (data) => {
        if (path.endsWith('present/')) {
          SELF.ongoingChallenges = data['results'];
        } else if (path.endsWith('past/')) {
          SELF.pastChallenges = data['results'];
        }
        SELF.filteredChallenges = SELF.upcomingChallenges.concat(SELF.ongoingChallenges, SELF.pastChallenges);
        SELF.filteredOngoingChallenges = SELF.ongoingChallenges;
        SELF.filteredPastChallenges = SELF.pastChallenges;
      },
      (err) => {
        if (err.status === 403) {
          this.router.navigate(['permission-denied']);
        }
      },
      () => {}
    );
  }

  fetchUnapprovedChallengesFromApi(id) {
    const path = this.endpointsService.allUnapprovedChallengesURL(id);
    const SELF = this;
    SELF.apiService.getUrl(path, true, false).subscribe(
      (data) => {
        const datas = data['results'];
        if (datas) {
          datas.forEach((challenge) => {
            if (challenge['approved_by_admin'] === false) {
              SELF.unapprovedChallengeList.push(challenge);
            }
          });
        }
      },
      (err) => {
        SELF.globalService.handleApiError(err);
      },
      () => {}
    );
  }
}