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

Skip to content
Snippets Groups Projects
exercise.service.ts 4.79 KiB
Newer Older
Philipp Gritsch's avatar
Philipp Gritsch committed
import { HttpClient, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
Michael Breu's avatar
Michael Breu committed
import { Injectable } from '@angular/core';
Michael Breu's avatar
Michael Breu committed
import { ApplicationConfigService } from 'app/core/config/application-config.service';
import { LikesService } from 'app/entities/likes/likes.service';
import { StatisticsService } from 'app/entities/statistics/statistics.service';
import { SearchService } from 'app/search/service/search-service';
import { ArtemisExerciseInfo } from 'app/shared/model/artemis-exercise-info.model';
import { ExtendedSearchResultDTO, SearchResultDTO } from 'app/shared/model/search/search-result-dto.model';
Philipp Gritsch's avatar
Philipp Gritsch committed
import { Observable, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
Michael Breu's avatar
Michael Breu committed

@Injectable({ providedIn: 'root' })
export class ExerciseService {
Michael Breu's avatar
Michael Breu committed
  public resourceUrl = this.applicationConfigService.getEndpointFor('api/exerciseFile/');
  public exerciseUrl: string = this.applicationConfigService.getEndpointFor('api/exercise/');
Michael Breu's avatar
Michael Breu committed

  constructor(
    private http: HttpClient,
    private likesService: LikesService,
    private searchService: SearchService,
Michael Breu's avatar
Michael Breu committed
    private statisticsService: StatisticsService,
    private applicationConfigService: ApplicationConfigService
Michael Breu's avatar
Michael Breu committed

  public loadExerciseFile(exerciseId: string, filePath: string): Observable<string> {
    const headers = new HttpHeaders(); // .set('Content-Type', 'text/plain; charset=utf-8');
    const options: HttpParams = new HttpParams();
    options.append('filePath', filePath);
Michael Breu's avatar
Michael Breu committed

    return this.http.get<string>(this.resourceUrl + encodeURIforExerciseId(exerciseId), {
      headers,
      params: new HttpParams().set('filePath', filePath),
      responseType: 'text' as 'json',
    });
  }

Philipp Gritsch's avatar
Philipp Gritsch committed
  public hasUserAccessToGitlabRepo(exerciseId: string): Observable<boolean> {
    const endpoint: string = this.applicationConfigService.getEndpointFor(
      SERVER_API_URL + 'api/exercises/' + encodeURIforExerciseId(exerciseId) + '/source-authorization'
    );
    return this.http.get<any>(endpoint, { observe: 'response' }).pipe(
      map((response: HttpResponse<any>) => {
        return response.status === 200;
      }),
      catchError(() => {
        return of(false);
      })
    );
  }

  public loadExercise(exerciseId: string): Observable<SearchResultDTO> {
    return this.http.get<SearchResultDTO>(this.exerciseUrl + encodeURIforExerciseId(exerciseId));
  populateExerciseWithData(exercise: SearchResultDTO): ExtendedSearchResultDTO {
    const result: ExtendedSearchResultDTO = {
      ...exercise,
      numberOfWatchlistEntries: 0,
      numberOfLikes: 0,
      userHasLiked: false,
    };
      this.likesService.getLikesForexerciseID(exercise.exerciseId).subscribe({
        next: (data: number) => {
          result.numberOfLikes = data;
        error: () => console.warn('Could not load number of likes'),
      });
      this.statisticsService.getNumberOfWatchListEntriesForExerciseID(result.exerciseId).subscribe({
        next: (data: number) => {
          result.numberOfWatchlistEntries = data;
        error: () => console.warn('Could not load number of watchlists'),
      });
      this.likesService.hasLiked(exercise.exerciseId).subscribe({
        next: (data: boolean) => {
          result.userHasLiked = data;
        error: () => console.warn('Could not load if user has liked or not'),
      });
  /**
   * Used on init of import page, this function passes the retrieved (from Artemis)
   * exerciseUrl to the server
   * @param exerciseUrl
   */
  public importExerciseInfoFromArtemis(exerciseToken: string): Observable<ArtemisExerciseInfo> {
    return this.http.get<ArtemisExerciseInfo>(`${this.exerciseUrl}imported-exercise-info/${exerciseToken}`);
  }

  /**
   * Submits an ArtemisExerciseInfo object to server and triggers its import
   * @param exerciseInfo to submit and import
   */
  public submitExerciseInfoForImport(
    exerciseInfo: ArtemisExerciseInfo,
    exerciseToken: string,
    gitlabGroupId: number
  ): Observable<ArtemisExerciseInfo> {
    return this.http.post<ArtemisExerciseInfo>(`${this.exerciseUrl}import-exercise/${exerciseToken}/${gitlabGroupId}`, exerciseInfo);

  /**
   * POST request validating the ExerciseInfo provided on the server side
   * @param exerciseInfo to validate
   */
  public validateExerciseInfo(exerciseInfo: ArtemisExerciseInfo): Observable<string> {
    return this.http.post<string>(`${this.exerciseUrl}validate-exercise-info`, exerciseInfo);
  }
Michael Breu's avatar
Michael Breu committed
}

/*
 * behind the apache reverse proxy, encoded slashes are not working.
 * I have not found a good way to repair this. So we unencode the slashes here.
 */
export function encodeURIforExerciseId(exerciseId: string): string {
  const encodedURL = encodeURIComponent(exerciseId);
  return encodedURL.replace('%2F', '/').replace('%2f', '/');