Skip to content

Commit

Permalink
#337: Added support for import of templates, runs
Browse files Browse the repository at this point in the history
  • Loading branch information
sauterl committed Oct 11, 2023
1 parent 7a7e39a commit 062cece
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 26 deletions.
1 change: 1 addition & 0 deletions backend/src/main/kotlin/dev/dres/api/rest/RestApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ object RestApi {
ListAllTeamsHandler(store),
CreateTeamHandler(store),
UpdateTeamHandler(store),
GetEvaluationHandler(store),

// Judgement
DequeueJudgementHandler(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import jetbrains.exodus.database.TransientEntityStore
* @author Loris Sauter
* @version 2.0.0
*/
class ForceViewerHandler : AbstractEvaluationAdminHandler(), PostRestHandler<SuccessStatus> {
class ForceViewerHandler() : AbstractEvaluationAdminHandler(), PostRestHandler<SuccessStatus> {
override val route: String = "evaluation/admin/{evaluationId}/viewer/list/{viewerId}/force"

@OpenApi(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dev.dres.api.rest.handler.evaluation.admin

import dev.dres.api.rest.handler.GetRestHandler
import dev.dres.api.rest.types.evaluation.ApiEvaluation
import dev.dres.api.rest.types.evaluation.ApiEvaluationOverview
import dev.dres.api.rest.types.status.ErrorStatus
import dev.dres.api.rest.types.status.ErrorStatusException
import dev.dres.data.model.run.DbEvaluation
import dev.dres.utilities.extensions.evaluationId
import io.javalin.http.Context
import io.javalin.openapi.*
import jetbrains.exodus.database.TransientEntityStore
import kotlinx.dnq.query.eq
import kotlinx.dnq.query.firstOrNull
import kotlinx.dnq.query.query

class GetEvaluationHandler(private val store: TransientEntityStore): AbstractEvaluationAdminHandler(),
GetRestHandler<ApiEvaluation> {
override val route = "evaluation/admin/{evaluationId}"

@OpenApi(
summary = "Provides the evaluation.",
path = "/api/v2/evaluation/admin/{evaluationId}",
operationId = OpenApiOperation.AUTO_GENERATE,
methods = [HttpMethod.GET],
pathParams = [
OpenApiParam("evaluationId", String::class, "The evaluation ID", required = true, allowEmptyValue = false),
],
tags = ["Evaluation Administrator"],
responses = [
OpenApiResponse("200", [OpenApiContent(ApiEvaluation::class)]),
OpenApiResponse("400", [OpenApiContent(ErrorStatus::class)]),
OpenApiResponse("401", [OpenApiContent(ErrorStatus::class)]),
OpenApiResponse("404", [OpenApiContent(ErrorStatus::class)])
]
)
override fun doGet(ctx: Context): ApiEvaluation {
/* Obtain run id and run. */
val evaluationId = ctx.pathParamMap().getOrElse("evaluationId") { throw ErrorStatusException(400, "Parameter 'evaluationId' is missing!'", ctx) }
return this.store.transactional(true) {
DbEvaluation.query(DbEvaluation::id eq evaluationId).firstOrNull()?.toApi()
?: throw ErrorStatusException(404, "Run $evaluationId not found", ctx)
}

}
}
67 changes: 64 additions & 3 deletions doc/oas-client.json
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,43 @@
"type" : "string",
"enum" : [ "FRAME_NUMBER", "SECONDS", "MILLISECONDS", "TIMECODE" ]
},
"ApiEvaluation" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"evaluationId" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
"type" : {
"$ref" : "#/components/schemas/ApiEvaluationType"
},
"template" : {
"$ref" : "#/components/schemas/ApiEvaluationTemplate"
},
"created" : {
"type" : "integer",
"format" : "int64"
},
"started" : {
"type" : "integer",
"format" : "int64"
},
"ended" : {
"type" : "integer",
"format" : "int64"
},
"tasks" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ApiTask"
}
}
},
"required" : [ "evaluationId", "name", "type", "template", "created", "tasks" ]
},
"ApiEvaluationInfo" : {
"type" : "object",
"additionalProperties" : false,
Expand Down Expand Up @@ -1351,6 +1388,33 @@
},
"required" : [ "evaluationId", "taskId", "submissions" ]
},
"ApiTask" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"taskId" : {
"type" : "string"
},
"templateId" : {
"type" : "string"
},
"started" : {
"type" : "integer",
"format" : "int64"
},
"ended" : {
"type" : "integer",
"format" : "int64"
},
"submissions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ApiAnswerSet"
}
}
},
"required" : [ "taskId", "templateId", "submissions" ]
},
"ApiTaskOverview" : {
"type" : "object",
"additionalProperties" : false,
Expand Down Expand Up @@ -2150,9 +2214,6 @@
"type" : "object",
"additionalProperties" : false,
"properties" : {
"id" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
Expand Down
129 changes: 126 additions & 3 deletions doc/oas.json
Original file line number Diff line number Diff line change
Expand Up @@ -957,6 +957,68 @@
"security" : [ ]
}
},
"/api/v2/evaluation/admin/{evaluationId}" : {
"get" : {
"tags" : [ "Evaluation Administrator" ],
"summary" : "Provides the evaluation.",
"operationId" : "getApiV2EvaluationAdminByEvaluationId",
"parameters" : [ {
"name" : "evaluationId",
"in" : "path",
"description" : "The evaluation ID",
"required" : true,
"deprecated" : false,
"allowEmptyValue" : false,
"schema" : {
"type" : "string"
}
} ],
"responses" : {
"200" : {
"description" : "OK",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/ApiEvaluation"
}
}
}
},
"400" : {
"description" : "Bad Request",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/ErrorStatus"
}
}
}
},
"401" : {
"description" : "Unauthorized",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/ErrorStatus"
}
}
}
},
"404" : {
"description" : "Not Found",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/ErrorStatus"
}
}
}
}
},
"deprecated" : false,
"security" : [ ]
}
},
"/api/v2/evaluation/admin/{evaluationId}/adjust/{duration}" : {
"patch" : {
"tags" : [ "Evaluation Administrator" ],
Expand Down Expand Up @@ -5580,6 +5642,43 @@
"type" : "string",
"enum" : [ "FRAME_NUMBER", "SECONDS", "MILLISECONDS", "TIMECODE" ]
},
"ApiEvaluation" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"evaluationId" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
"type" : {
"$ref" : "#/components/schemas/ApiEvaluationType"
},
"template" : {
"$ref" : "#/components/schemas/ApiEvaluationTemplate"
},
"created" : {
"type" : "integer",
"format" : "int64"
},
"started" : {
"type" : "integer",
"format" : "int64"
},
"ended" : {
"type" : "integer",
"format" : "int64"
},
"tasks" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ApiTask"
}
}
},
"required" : [ "evaluationId", "name", "type", "template", "created", "tasks" ]
},
"ApiEvaluationInfo" : {
"type" : "object",
"additionalProperties" : false,
Expand Down Expand Up @@ -5703,6 +5802,33 @@
},
"required" : [ "evaluationId", "taskId", "submissions" ]
},
"ApiTask" : {
"type" : "object",
"additionalProperties" : false,
"properties" : {
"taskId" : {
"type" : "string"
},
"templateId" : {
"type" : "string"
},
"started" : {
"type" : "integer",
"format" : "int64"
},
"ended" : {
"type" : "integer",
"format" : "int64"
},
"submissions" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ApiAnswerSet"
}
}
},
"required" : [ "taskId", "templateId", "submissions" ]
},
"ApiTaskOverview" : {
"type" : "object",
"additionalProperties" : false,
Expand Down Expand Up @@ -6502,9 +6628,6 @@
"type" : "object",
"additionalProperties" : false,
"properties" : {
"id" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<mat-icon style="vertical-align: middle">cloud_upload</mat-icon> {{ name }}
</button>

<button *ngIf="inline" mat-button (click)="fileInput.click()">
<button *ngIf="inline" mat-icon-button (click)="fileInput.click()">
<mat-icon>cloud_upload</mat-icon> {{ name }}
</button>
<input type="file" hidden #fileInput id="fileInput" name="fileInput" (change)="onFileSelected()" />
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class UploadJsonButtonComponent {
/** If multi-select files are enabled. Defaults to false (only single file) */
@Input() multi = false; // Currently only single file upload handled
/** The handler to process the uploaded thing */
@Input() handler: (contents: string) => void;
@Input() handler: (contents: any) => void;

@ViewChild('fileInput', { static: false }) fileUpload: HTMLInputElement;

Expand All @@ -34,7 +34,7 @@ export class UploadJsonButtonComponent {
const reader = new FileReader();

reader.onload = (e: any) => {
this.handler(e.target.result);
this.handler(JSON.parse(e.target.result));
};
if (this.multi) {
// TODO multi file upload
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ <h1>Edit evaluation template {{(builderService.templateAsObservable() | async)?.
matTooltip="Download the entire evaluation template as JSON"></app-download-button>
</div>
<div>
<app-upload-json-button [name]="''" [multi]="false" [handler]="onUpload" [inline]="true" matTooltip="Upload an evaluation template as JSON to import from"></app-upload-json-button>
<app-upload-json-button #jsonUpload [name]="''"
[multi]="false"
[inline]="true"
matTooltip="Upload an evaluation template as JSON to import from"></app-upload-json-button>
</div>
<div>
<button mat-icon-button
Expand Down
Loading

0 comments on commit 062cece

Please sign in to comment.