diff --git a/src/app/api/models/task-definition.ts b/src/app/api/models/task-definition.ts index 1b49a2e85..8e9ed910b 100644 --- a/src/app/api/models/task-definition.ts +++ b/src/app/api/models/task-definition.ts @@ -1,14 +1,20 @@ -import { HttpClient } from '@angular/common/http'; -import { Entity, EntityMapping } from 'ngx-entity-service'; -import { Observable, tap } from 'rxjs'; -import { AppInjector } from 'src/app/app-injector'; -import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; -import { Grade, GroupSet, TutorialStream, Unit } from './doubtfire-model'; -import { TaskDefinitionService } from '../services/task-definition.service'; - -export type UploadRequirement = { key: string; name: string; type: string; tiiCheck?: boolean; tiiPct?: number }; +import {HttpClient, HttpResponse} from '@angular/common/http'; +import {Entity, EntityMapping} from 'ngx-entity-service'; +import {firstValueFrom, Observable, tap} from 'rxjs'; +import {AppInjector} from 'src/app/app-injector'; +import {DoubtfireConstants} from 'src/app/config/constants/doubtfire-constants'; +import {Grade, GroupSet, TutorialStream, Unit} from './doubtfire-model'; +import {TaskDefinitionService} from '../services/task-definition.service'; + +export type UploadRequirement = { + key: string; + name: string; + type: string; + tiiCheck?: boolean; + tiiPct?: number; +}; -export type SimilarityCheck = { key: string; type: string; pattern: string }; +export type SimilarityCheck = {key: string; type: string; pattern: string}; export class TaskDefinition extends Entity { id: number; @@ -36,7 +42,7 @@ export class TaskDefinition extends Entity { maxQualityPts: number; overseerImageId: number; assessmentEnabled: boolean; - mossLanguage: string = 'moss c'; + jplagLanguage: string = 'c'; readonly unit: Unit; @@ -67,7 +73,7 @@ export class TaskDefinition extends Entity { entity: this, cache: this.unit.taskDefinitionCache, constructorParams: this.unit, - } + }, ); } else { return svc.update( @@ -75,7 +81,7 @@ export class TaskDefinition extends Entity { unitId: this.unit.id, id: this.id, }, - { entity: this } + {entity: this}, ); } } @@ -122,7 +128,10 @@ export class TaskDefinition extends Entity { } public matches(text: string): boolean { - return this.abbreviation.toLowerCase().indexOf(text) !== -1 || this.name.toLowerCase().indexOf(text) !== -1; + return ( + this.abbreviation.toLowerCase().indexOf(text) !== -1 || + this.name.toLowerCase().indexOf(text) !== -1 + ); } /** @@ -160,7 +169,7 @@ export class TaskDefinition extends Entity { return this.plagiarismChecks?.length > 0; } - public get needsMoss(): boolean { + public get needsJplag(): boolean { return this.uploadRequirements.some((upreq) => upreq.type === 'code' && upreq.tiiCheck); } @@ -188,6 +197,19 @@ export class TaskDefinition extends Entity { }/task_assessment_resources.json`; } + public async hasJplagReport(): Promise { + const url = `${AppInjector.get(DoubtfireConstants).API_URL}/units/${this.unit.id}/task_definitions/${this.id}/has_jplag_report`; + //console.log(url); + try { + const response = await fetch(url); + const result = await response.json(); + return result === 'true'; + } catch (error) { + console.error('Error fetching JPLAG report:', error); + return false; + } + } + public deleteTaskSheet(): Observable { const httpClient = AppInjector.get(HttpClient); return httpClient.delete(this.taskSheetUploadUrl).pipe(tap(() => (this.hasTaskSheet = false))); @@ -195,7 +217,9 @@ export class TaskDefinition extends Entity { public deleteTaskResources(): Observable { const httpClient = AppInjector.get(HttpClient); - return httpClient.delete(this.taskResourcesUploadUrl).pipe(tap(() => (this.hasTaskResources = false))); + return httpClient + .delete(this.taskResourcesUploadUrl) + .pipe(tap(() => (this.hasTaskResources = false))); } public deleteTaskAssessmentResources(): Observable { diff --git a/src/app/api/models/task-similarity.ts b/src/app/api/models/task-similarity.ts index c3a72e556..be8b3d9b0 100644 --- a/src/app/api/models/task-similarity.ts +++ b/src/app/api/models/task-similarity.ts @@ -5,7 +5,7 @@ import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants import { Observable } from 'rxjs'; export enum TaskSimilarityType { - Moss = 'MossTaskSimilarity', + Jplag = 'JplagTaskSimilarity', TurnItIn = 'TiiTaskSimilarity', } @@ -62,8 +62,8 @@ export class TaskSimilarity extends Entity { public get friendlyTypeName(): string { switch (this.type) { - case TaskSimilarityType.Moss: - return 'MOSS'; + case TaskSimilarityType.Jplag: + return 'JPLAG'; case TaskSimilarityType.TurnItIn: return 'TurnItIn'; } diff --git a/src/app/api/services/task-definition.service.ts b/src/app/api/services/task-definition.service.ts index 13a1dd279..e0b685c20 100644 --- a/src/app/api/services/task-definition.service.ts +++ b/src/app/api/services/task-definition.service.ts @@ -21,7 +21,7 @@ export class TaskDefinitionService extends CachedEntityService { 'description', 'weighting', 'targetGrade', - 'mossLanguage', + 'jplagLanguage', { keys: 'targetDate', toEntityFn: MappingFunctions.mapDateToEndOfDay, diff --git a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html index f068cb609..2f42a7974 100644 --- a/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html +++ b/src/app/projects/states/dashboard/directives/task-dashboard/directives/task-similarity-view/task-similarity-view.component.html @@ -23,14 +23,25 @@

{{ part.description }} @if (similarity.readyForViewer) { - + @if (similarity.type === 'JplagTaskSimilarity') { + + } @else { + + } } @if (i === 0) { - } @if (!isTaskDefMode) { - - } @if (isTaskDefMode) { - + + } + @if (!isTaskDefMode) { + + } + @if (isTaskDefMode) { + } + + @@ -93,16 +103,20 @@ name="taskDefID" (selectionChange)="taskDefinitionIdChanged()" > - All Task Definitions + All Task Definitions @for (td of unit.taskDefinitionCache.values | async; track td) { - - {{ td.abbreviation + ' - ' + td.name }} - + + {{ td.abbreviation + ' - ' + td.name }} + } @@ -140,14 +159,19 @@ - +
-
+
@if (!isNarrow) { -
- -
+
+ +
}
@@ -170,44 +196,45 @@ @if (filteredTasks) { - - - - @if (task) { -
+ + -
- - -
-

{{ task.project.student.name }}

-
- {{ task.definition.abbreviation }} - - {{ task.definition.name }} -
- -
- @if (task.hasGrade()) { -
- {{ task.gradeDesc() }} -
- } - - @if (!isTaskDefMode) { -
- - - - - + + @if (!isTaskDefMode) { +
+ + + + + +
+ } +
+
- } -
- -
- } - + } + - - - + + + }
diff --git a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts index 95b498af2..2b2c03286 100644 --- a/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts +++ b/src/app/units/states/tasks/inbox/directives/staff-task-list/staff-task-list.component.ts @@ -77,6 +77,8 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { tasks: any[] = null; + hasJplagReport: boolean; + watchingTaskKey: any; panelOpenState = false; @@ -206,6 +208,20 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { return this.taskData.taskDefMode; } + // TODO: Get this to return correct value from the API + public async taskHasJplagReport(): Promise { + const taskDef = this.filters.taskDefinition; + return taskDef + .hasJplagReport() + .then((hasReport) => { + return hasReport ?? false; + }) + .catch((error) => { + console.error(error); + return false; + }); + } + downloadSubmissionPdfs() { const taskDef = this.filters.taskDefinition; this.fileDownloaderService.downloadFile( @@ -226,6 +242,18 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { ); } + downloadJPLAGReport() { + const taskDef = this.filters.taskDefinition; + this.fileDownloaderService.downloadFile( + //this.taskData.selectedTask.jplagReportUrl() + `${AppInjector.get(DoubtfireConstants).API_URL}/units/${ + this.unit.id + }/task_definitions/${taskDef.id}/jplag_report`, + `${this.unit.code}-${taskDef.abbreviation}-jplag-report.zip`, + ); + window.open('https://jplag.github.io/JPlag/', '_blank'); + } + openDialog() { const dialogRef = this.dialog.open(this.searchDialog); @@ -349,6 +377,10 @@ export class StaffTaskListComponent implements OnInit, OnChanges, OnDestroy { this.alertService.error(message, 6000); }, }); + this.taskHasJplagReport().then((hasReport) => { + this.hasJplagReport = hasReport; + }); + console.log('HAS JPLAG REPORT:', this.hasJplagReport); } setSelectedTask(task: Task) {