Newer
Older

Eduard Frankford
committed
import { HttpResponse } from '@angular/common/http';
import { AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';

Eduard Frankford
committed
import { Router } from '@angular/router';
import { faArrowRight, faFolderOpen } from '@fortawesome/free-solid-svg-icons';
import { ReviewManagementService } from 'app/admin/review-management/review-management.service';
import { ApplicationInfoService } from 'app/core/application/applicationInfo.service';
import { Account } from 'app/core/auth/account.model';
import { AccountService } from 'app/core/auth/account.service';
import { AlertService } from 'app/core/util/alert.service';

Eduard Frankford
committed
import { LikesService } from 'app/entities/likes/likes.service';
import { ExerciseService } from 'app/exercise/service/exercise.service';

Eduard Frankford
committed
import { SearchService } from 'app/search/service/search-service';

Eduard Frankford
committed
import { ShoppingBasketInfo, ShoppingBasketRedirectInfoDTO } from 'app/shared/model/basket/shopping-basket-info.model';
import { Person } from 'app/shared/model/person.model';
import {
ChildInfo,
ExtendedSearchResultDTO,
hasChildren,
PluginActionInfo,
SearchResultDTO,
} from 'app/shared/model/search/search-result-dto.model';

Eduard Frankford
committed
import { PluginService } from 'app/shared/service/plugin-service';
import { WatchlistManager } from 'app/shared/watchlist/watchlist-manager';

Eduard Frankford
committed
import { Subscription } from 'rxjs';
selector: 'jhi-exercise-modal-details',
templateUrl: './exercise-details-modal.component.html',
export class ExerciseDetailsModalComponent {
@Output() exerciseChangedEvent = new EventEmitter<SearchResultDTO>();
@Input() get referencedExercise(): SearchResultDTO | undefined {
return this.exercise;
}
set referencedExercise(exercise: SearchResultDTO | undefined) {
this.exercise = exercise as ExtendedSearchResultDTO;
}
exercise: ExtendedSearchResultDTO | undefined;
constructor(private watchlistManager: WatchlistManager) {}
handleExerciseChangedEvent(exercise: SearchResultDTO): void {
@Component({
selector: 'jhi-exercise-nonmodal-details',
templateUrl: './exercise-details-nonmodal.component.html',
})
export class ExerciseDetailsNonModalComponent {
@Input() exercise: ExtendedSearchResultDTO | undefined;
@Component({
selector: 'jhi-exercise-header',
templateUrl: './exerciseComponents/exercise-header.component.html',
styleUrls: ['./exerciseComponents/exercise-header.component.scss'],
})
export class ExerciseHeaderComponent {
@Input() exercise: ExtendedSearchResultDTO | undefined;
/**
* correct missing image urls
*/
correctImageURL(event: Event): void {
const srcElement = event.target as HTMLImageElement;
if (srcElement) {
srcElement.src = '/content/images/Logo_codeAbility_4c_300dpi_RGB3.gif';
}
}
}
@Component({
selector: 'jhi-exercise-body',
templateUrl: './exerciseComponents/exercise-body.component.html',
styleUrls: ['./exerciseComponents/exercise-body.component.scss'],
})
export class ExerciseBodyComponent implements OnInit, OnDestroy, AfterViewInit {
@Output() exerciseChangedEvent = new EventEmitter<SearchResultDTO>();
@Input() get referencedExercise(): SearchResultDTO | undefined {
return this.exercise;
}
set referencedExercise(exercise: SearchResultDTO | undefined) {
this.exercise = exercise as ExtendedSearchResultDTO;
}
exercise: ExtendedSearchResultDTO | undefined;
markDownExercise: SearchResultDTO | undefined;
account: Account | null = null;
authSubscription?: Subscription;
hasLiked: boolean | null = null;
likeSubscription?: Subscription;
authenticated = false;
treeIcon = faFolderOpen;
faArrowRight = faArrowRight;
oerLink?: string;
oerExerciseMatch = /([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})$/;
private reviewManagementService: ReviewManagementService,
private accountService: AccountService,
protected pluginService: PluginService,
private searchService: SearchService,
private likesService: LikesService,
private jhiAlertService: AlertService,
private watchlistManager: WatchlistManager,
private exerciseService: ExerciseService,
private applicationInfoService: ApplicationInfoService,
private router: Router
) {}
toggleWithChildren() {
this.downloadWithChildren = !this.downloadWithChildren;
}
selectREADME(): void {
this.markDownExercise = this.exercise;
}
hasChildren(): boolean {
getChildrenInfos(): ChildInfo[] {
if (this.exercise?.childInfos) {
return this.exercise?.childInfos;
} else {
this.loadChildrenInfoDisplayString();
return [];
}
}
loadChildrenInfoDisplayString(): string {
if (!this.exercise?.childInfos) {
this.exercise!.childInfos = [];
this.exerciseService.populateExerciseWithChildrenInfo(this.exercise!).subscribe({
next: () => {
// nothing to do
},
error: () => console.warn('Could not load children info'),
});
}
return '';
}
public startAction(action: PluginActionInfo, exercise: SearchResultDTO): void {
const basketInfo: ShoppingBasketInfo = {
plugin: action.plugin,
action: action.action,
this.pluginService.getRedirectLink(basketInfo).subscribe({
next: (redirectInfo: ShoppingBasketRedirectInfoDTO) => {
window.open(redirectInfo.redirectURL, action.action);
},
error: () => alert('Search failed'),
});
this.exportProject(this.exercise!.exerciseId);
}
exportProject(exerciseId: string) {
const recursion = this.downloadWithChildren ? 'WITH_DESCENDANTS' : 'JUST_PROJECT';
return this.searchService.exportProject(exerciseId, recursion).subscribe({
next: (response: HttpResponse<Blob>) => {
this.jhiAlertService.addAlert({
type: 'success',
translationKey: '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);
}
},
error: () => alert('Unable to export exercise. Please log in to export, or check your git lab permissions.'),
});

Michael Breu
committed
getGitLabUrl(): string {
return this.reviewManagementService.getGitLabUrl(this.exercise!);

Michael Breu
committed
}
openLink(link: string): void {
window.open(link);
}
searchChildren(parentId: string): void {
this.router.navigate(['/search'], { queryParams: { p: parentId } });
}
toParent(parentId: string): void {
this.toExercise(parentId);
}
toExercise(exerciseId: string): void {
this.exerciseService.loadExercise(exerciseId).subscribe({
next: searchResult => {
this.exercise = this.exerciseService.populateExerciseWithData(searchResult);
this.exerciseChangedEvent.emit(this.exercise);
alert(`exercise ${exerciseId} cannot be loaded`);
isLoggedIn(): boolean {
return this.accountService.isAuthenticated();
}
public isEditable(): boolean {
if (!this.exercise) return false;
if (!this.exercise.project.url) return false;
const matchGroups = this.exercise.project.url.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 = potentialEditors.concat(this.exercise.metadata.creator);
potentialEditors = potentialEditors.concat(this.exercise.metadata.publisher);
for (const pE of potentialEditors) {
if (pE.email.localeCompare(email, undefined, { sensitivity: 'base' }) === 0) return true;
}
return false;
}
public getOEResourceLink(): string {
if (this.oerLink) {
const matchGroups = this.exercise!.project.url.match(this.oerExerciseMatch);
if (!matchGroups) return '';
const guid = matchGroups[1];
return this.oerLink.toString() + '/en/update/1/' + guid;
}
return '';
}
likeAction(): void {
// to do call like service
this.likesService.likeExercise(this.exercise!.exerciseId).subscribe(() =>
console.log('Liked post' + this.exercise!.exerciseId)
);
this.exercise!.numberOfLikes = this.exercise!.numberOfLikes + 1;
this.exercise!.userHasLiked = true;
}
unlikeAction(): void {
// to do call like service
this.likesService.unlikeExercise(this.exercise!.exerciseId);
this.exercise!.numberOfLikes = this.exercise!.numberOfLikes - 1;
this.exercise!.userHasLiked = false;
}
public isAuthenticated(): boolean {
return this.accountService.isAuthenticated();
}
ngOnInit(): void {
this.bookmarked = this.watchlistManager.isExerciseOnCurrentWatchlist(this.exercise!);
this.authSubscription = this.accountService.getAuthenticationState().subscribe(account => (this.account = account));
this.applicationInfoService.loadOerLink().subscribe({
next: (res: string) => {
console.error(error),
});
ngAfterViewInit(): void {
this.updateParent(this.exercise!);
}
updateParent(exercise: ExtendedSearchResultDTO): void {
if (this.exercise!.file.parentId) {
this.exerciseService.loadExercise(this.exercise!.file.parentId).subscribe({
next: searchResult => {
this.parent = searchResult;
},
error: () => {
alert(`exercise ${this.exercise!.file.parentId} cannot be loaded`);
},
});
}
}
ngOnDestroy(): void {
if (this.authSubscription) {
this.authSubscription.unsubscribe();
}
}