This is the codeAbility Sharing Platform! Learn more about the codeAbility Sharing Platform.

Skip to content
Snippets Groups Projects
exercise-details.component.ts 8.7 KiB
Newer Older
import { HttpResponse } from '@angular/common/http';
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { Router } from '@angular/router';
import { faFolder } from '@fortawesome/free-solid-svg-icons';
Daniel Rainer's avatar
Daniel Rainer committed
import { ApplicationInfoService } from 'app/core/application/applicationInfo.service';
import { Account } from 'app/core/auth/account.model';
Daniel Rainer's avatar
Daniel Rainer committed
import { AccountService } from 'app/core/auth/account.service';
import { AlertService } from 'app/core/util/alert.service';
import { LikesService } from 'app/entities/likes/likes.service';
import { ExerciseService } from 'app/exercise/service/exercise.service';
import { SearchService } from 'app/search/service/search-service';
import { ShoppingBasketInfo, ShoppingBasketRedirectInfoDTO } from 'app/shared/model/basket/shopping-basket-info.model';
import { Exercise, searchResultToExercise } from 'app/shared/model/exercise.model';
import { Person } from 'app/shared/model/person.model';
import { PluginActionInfo } from 'app/shared/model/search/search-result-dto.model';
import { PluginService } from 'app/shared/service/plugin-service';
import { WatchlistManager } from 'app/shared/watchlist/watchlist-manager';
  selector: 'jhi-exercise-details',
  templateUrl: './exercise-details.component.html',
  styleUrls: ['./exercise-details.component.scss'],
export class ExerciseDetailsComponent implements OnInit, OnDestroy {
  @Input() exercise: Exercise | undefined;
  @Output() exerciseChangedEvent = new EventEmitter<Exercise>();
Michael Breu's avatar
Michael Breu committed
  markDownExercise: Exercise | undefined;
  account: Account | null = null;
  authSubscription?: Subscription;
  hasLiked: Boolean | null = null;
  likeSubscription?: Subscription;
  downloadWithChildren = false;
Michael Breu's avatar
Michael Breu committed
  treeIcon = faFolder;
  oerLink?: String;
  oerExerciseMatch = new RegExp('/([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$');
  constructor(
    private accountService: AccountService,
    protected pluginService: PluginService,
    private searchService: SearchService,
    private jhiAlertService: AlertService,
    private watchlistManager: WatchlistManager,
    private exerciseService: ExerciseService,
    private applicationInfoService: ApplicationInfoService,
  ngOnInit(): void {
    this.authSubscription = this.accountService.getAuthenticationState().subscribe(account => (this.account = account));
    this.applicationInfoService.loadOerLink().subscribe(
      (res: string) => {
        this.oerLink = res;
      },
      error =>
        // eslint-disable-next-line no-console
        console.error(error)
    );
  public isAuthenticated(): boolean {
    return this.accountService.isAuthenticated();
  }
Michael Breu's avatar
Michael Breu committed

  isOnCurrentWatchlist(e: Exercise): boolean {
    return this.watchlistManager.isExerciseOnCurrentWatchlist(e);
  }
  handleForCurrentWatchlist(e: Exercise): void {
    if (this.watchlistManager.isExerciseOnCurrentWatchlist(e)) {
      e.numberOfWatchlistEntries = e.numberOfWatchlistEntries - 1;
    } else {
      e.numberOfWatchlistEntries = e.numberOfWatchlistEntries + 1;
    }
    this.watchlistManager.handleCheckForCurrentWatchlist(e);
  }
Michael Breu's avatar
Michael Breu committed

Daniel Rainer's avatar
Daniel Rainer committed
  public startAction(action: PluginActionInfo, exercise: Exercise): void {
    const basketInfo: ShoppingBasketInfo = {
      plugin: action.plugin,
      action: action.action,
      itemInfos: [exercise.originalResult],
    };
    this.pluginService.getRedirectLink(basketInfo).subscribe(
      (redirectInfo: ShoppingBasketRedirectInfoDTO) => {
        // alert('redirecting to ' + redirectInfo.redirectURL);
        // location.href = redirectInfo.redirectURL;
        window.open(redirectInfo.redirectURL, action.action);
      },
      () => alert('Search failed')
    );
  }
  public isEditable(): boolean {
    if (!this.exercise) return false;
    if (!this.exercise.gitlabURL) return false;
    const matchGroups = this.exercise.gitlabURL.match(this.oerExerciseMatch);
    if (!matchGroups) return false;

    // Just for Testing: allow every edit
    if (this.oerLink) return true;

    const email = this.accountService.getUserEMail();
    if (!email || email == '') return false;

    // test all: creator, publisher
    let potentialEditors: Person[] = [];

    // potentialEditors.concat(this.exercise.contributor);
    potentialEditors = potentialEditors.concat(this.exercise.creator);
    potentialEditors = potentialEditors.concat(this.exercise.publisher);

    for (let i = 0; i < potentialEditors.length; i++) {
      if (potentialEditors[i].email.localeCompare(email, undefined, { sensitivity: 'base' }) === 0) return true;
    }
    return false;
  }

  public getOEResourceLink(): string {
    if (this.oerLink) {
      const matchGroups = this.exercise!.gitlabURL.match(this.oerExerciseMatch);
      if (!matchGroups) return '';

      const guid = matchGroups[1];

      return this.oerLink.toString() + '/en/update/1/' + guid;
    }
    return '';
  }

Michael Breu's avatar
Michael Breu committed
    this.exportProject(this.exercise!.originalResult.exerciseId);
Michael Breu's avatar
Michael Breu committed
  exportProject(exerciseId: string) {
    const recursion = this.downloadWithChildren ? 'WITH_DESCENDANTS' : 'JUST_PROJECT';
    return this.searchService.exportProject(exerciseId, recursion).subscribe(
Daniel Rainer's avatar
Daniel Rainer committed
        this.jhiAlertService.addAlert({
          type: 'success',
          translationKey: 'artemisApp.programmingExercise.export.successMessage',
        });
Michael Breu's avatar
Michael Breu committed
        // success('artemisApp.programmingExercise.export.successMessage');
        if (response.body) {
          const zipFile = new Blob([response.body], { type: 'application/zip' });
          const url = window.URL.createObjectURL(zipFile);
          const link = document.createElement('a');
          link.setAttribute('href', url);
          link.setAttribute('download', response.headers.get('filename')!);
          document.body.appendChild(link); // Required for FF
          link.click();
          window.URL.revokeObjectURL(url);
Michael Breu's avatar
Michael Breu committed
        }
      () => alert('Unable to export exercise. Please log in to export, or check your git lab permissions.')
  hasChildren(): boolean {
    return (
      this.exercise !== undefined &&
Daniel Rainer's avatar
Daniel Rainer committed
      this.exercise !== null &&
      this.exercise.originalResult !== undefined &&
Daniel Rainer's avatar
Daniel Rainer committed
      this.exercise.originalResult !== null &&
      this.exercise.originalResult.file !== undefined &&
Daniel Rainer's avatar
Daniel Rainer committed
      this.exercise.originalResult.file !== null &&
      this.exercise.originalResult.file.children !== undefined &&
Daniel Rainer's avatar
Daniel Rainer committed
      this.exercise.originalResult.file.children !== null &&
      this.exercise.originalResult.file.children.length > 0
    );
  }

  searchChildren(parentId: string): void {
    this.router.navigate(['/search'], { queryParams: { p: parentId } });
  }
  toParent(parentId: string): void {
    this.exerciseService.loadExercise(parentId).subscribe(searchResult => {
      this.exercise = searchResultToExercise(searchResult);
      this.exercise = this.exerciseService.populateExerciseWithData(this.exercise);
      this.exerciseChangedEvent.emit(this.exercise);
      () => {
        alert('parent cannot be loaded');
      };
  }

  ngOnDestroy(): void {
    if (this.authSubscription) {
      this.authSubscription.unsubscribe();
  /**
   * correct missing image urls
   */
  correctImageURL(event: Event): void {
    const srcElement = event.srcElement as HTMLImageElement;
    if (srcElement) {
      srcElement.src = '/content/images/Logo_codeAbility_4c_300dpi_RGB3.gif';
    this.likesService.likeExercise(this.exercise!.originalResult.exerciseId).subscribe(() =>
      console.log('Liked post' + this.exercise!.originalResult.exerciseId)
    this.exercise!.numberOfLikes = this.exercise!.numberOfLikes + 1;
    this.exercise!.userHasLiked = true;

    // eslint-disable-next-line no-console
    console.log(`Reloaded number of likes is ${this.exercise!.numberOfLikes}`);
    this.likesService.unlikeExercise(this.exercise!.originalResult.exerciseId).subscribe(() =>
      console.log('Unliked post ' + this.exercise!.originalResult.exerciseId)
    );

    this.exercise!.numberOfLikes = this.exercise!.numberOfLikes - 1;
    this.exercise!.userHasLiked = false;

    // eslint-disable-next-line no-console
    console.log(`Reloaded number of likes is ${this.exercise!.numberOfLikes}`);
  toggleWithChildren() {
    this.downloadWithChildren = !this.downloadWithChildren;
  }
Michael Breu's avatar
Michael Breu committed
  selectREADME(): void {
    this.markDownExercise = this.exercise;
  }