diff --git a/src/app/app.module.ts b/src/app/app.module.ts index f46b5269..04f217f2 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -43,6 +43,7 @@ import { ContextService } from './services/context.service'; import { VerificationService } from './services/verification.service'; import { TaskProgressComponent } from './scenario/task-progress/task-progress.component'; import { TaskModalComponent } from './scenario/task-modal/task-modal.component'; +import { SingleTaskVerificationMarkdownComponent } from './hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component'; export function tokenGetter() { return localStorage.getItem('hobbyfarm_token'); @@ -93,6 +94,7 @@ export function jwtOptionsFactory() { IdeWindowComponent, TaskProgressComponent, TaskModalComponent, + SingleTaskVerificationMarkdownComponent, ], imports: [ BrowserModule, @@ -111,7 +113,7 @@ export function jwtOptionsFactory() { sanitize: false, convertHTMLEntities: false, }, - globalParsers: [{ component: CtrComponent }], + globalParsers: [{ component: CtrComponent }, { component: SingleTaskVerificationMarkdownComponent }], }), JwtModule.forRoot({ jwtOptionsProvider: { diff --git a/src/app/hf-markdown/hf-markdown.component.ts b/src/app/hf-markdown/hf-markdown.component.ts index 6709afe0..087ca86a 100644 --- a/src/app/hf-markdown/hf-markdown.component.ts +++ b/src/app/hf-markdown/hf-markdown.component.ts @@ -116,6 +116,14 @@ ${token}`; title="Click to create ${filepath} on ${target}" >${this.renderHighlightedCode(code, language, filename)}`; }, + + verifyTask(code: string, target: string, taskName: string) { + return `` + }, }; private renderHighlightedCode( diff --git a/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.html b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.html new file mode 100644 index 00000000..c88aca0a --- /dev/null +++ b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.html @@ -0,0 +1,39 @@ +
+ +
+ + Verify: {{ taskName }} on {{ target }} +
+
+ +
+
+
+
+ + +
+ + diff --git a/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.scss b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.scss new file mode 100644 index 00000000..21595ec7 --- /dev/null +++ b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.scss @@ -0,0 +1,78 @@ +.task-verification-box { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-left: 3px solid; + border-radius: 5px; +} + +.down { + transform: rotate(180deg); +} + +.sideways { + transform: rotate(90deg); +} + +.label { + margin-bottom: 7%; +} + +.flex-container { + display: flex !important; + flex-direction: row; + justify-content: space-between; +} + +.label-container { + display: flex !important; + flex-direction: row; + justify-content: space-between; + width: fit-content; +} + +.label { + margin:auto; + margin-left: 4px; +} +.label:hover { + cursor: default; +} + +#refreshButton:hover { + cursor: pointer !important; +} + +.list-group { + width: 100%; +} + +.greenBorder { + border-left-color: var(--clr-color-success-500, green) !important; +} + +.redBorder { + border-left-color: #f0ad4e !important; +} + + +details { + border: 1px solid var(--clr-color-neutral-400, #cccccc); + border-left: 3px solid; + border-radius: 4px; + padding: 0.5em 0.5em 0; + &[open] { + padding: 0.5em; + summary { + margin-bottom: 0.5em; + } + } + } + +summary { + font-weight: bold; + margin: -0.5em -0.5em 0; + padding: 0.5em; + display: list-item; + cursor: pointer; + } diff --git a/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.ts b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.ts new file mode 100644 index 00000000..d1996e33 --- /dev/null +++ b/src/app/hf-markdown/single-task-verification-markdown/single-task-verification-markdown.component.ts @@ -0,0 +1,35 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { TaskCommand } from 'src/app/scenario/taskVerification.type'; +import { VerificationService } from 'src/app/services/verification.service'; + +@Component({ + selector: 'app-single-task-verification-markdown', + templateUrl: './single-task-verification-markdown.component.html', + styleUrls: ['./single-task-verification-markdown.component.scss'] +}) +export class SingleTaskVerificationMarkdownComponent implements OnInit { + + @Input() target: string; + @Input() message: string; + @Input() taskName: string; + + detailsOpen = false + + + task?: TaskCommand + + constructor( + private verificationService: VerificationService + ) { } + + ngOnInit(): void { + this.verificationService.currentVerifications.subscribe((verificationMap) => { + let temp = verificationMap.get(this.target) + this.task = temp?.task_command?.filter(taskCommand => taskCommand.name == this.taskName)[0] + }) + } + + elementClicked() { + this.verificationService.verifyTask(this.target, this.taskName)?.subscribe() + } +} diff --git a/src/app/scenario/taskVerification.type.ts b/src/app/scenario/taskVerification.type.ts index 948ddc29..69a59b9e 100644 --- a/src/app/scenario/taskVerification.type.ts +++ b/src/app/scenario/taskVerification.type.ts @@ -1,17 +1,25 @@ -export type TaskVerification = { - vm_id: string, - vm_name: string, - task_command?: TaskCommand[] - task_command_output?: TaskCommand[] + + +type BaseTaskVerification = { + vm_id: string; + vm_name: string; +}; + +export type TaskVerification = BaseTaskVerification & { + task_command: TaskCommand[]; +}; + +export type TaskVerificationResponse = BaseTaskVerification & { + task_command_output?: TaskCommand[]; } export type TaskCommand = { - name: string, - description: string, - command: string, - expected_output_value: string, - expected_return_code: number - actual_output_value?: string, - actual_return_code?: number, - success?: boolean -} \ No newline at end of file + name: string; + description: string; + command: string; + expected_output_value: string; + expected_return_code: number; + actual_output_value?: string; + actual_return_code?: number; + success?: boolean; +}; diff --git a/src/app/services/verification.service.ts b/src/app/services/verification.service.ts index 80b5880f..c838e336 100644 --- a/src/app/services/verification.service.ts +++ b/src/app/services/verification.service.ts @@ -1,11 +1,12 @@ import { Injectable } from "@angular/core"; import { GargantuaClient, GargantuaClientFactory, extractResponseContent } from "./gargantua.service"; -import { TaskVerification } from "../scenario/taskVerification.type"; +import { TaskVerification, TaskVerificationResponse } from "../scenario/taskVerification.type"; import { VM } from "../VM"; import { ServerResponse } from "../ServerResponse"; import { BehaviorSubject, throwError } from "rxjs"; import { catchError, tap } from "rxjs/operators"; import { HttpErrorResponse } from "@angular/common/http"; +import { VMService } from "./vm.service"; @@ -32,6 +33,7 @@ export class VerificationService { constructor( private gcf: GargantuaClientFactory, + private vmService: VMService ) { } private useShellClient(endpoint: string): GargantuaClient { @@ -44,6 +46,31 @@ export class VerificationService { return client } + verifyTask(vmName: string, taskName: string) { + const taskVerification = {...this.verificationTaskRequests.get(vmName)} as TaskVerification + if (!taskVerification) { + return + } + const command = taskVerification.task_command?.filter(command => command.name == taskName) + if (!command) { + return + } + taskVerification.task_command = command + const body = [taskVerification] + const vm = this.vmService.cache.get(taskVerification.vm_id) + if (!vm) { + return + } + return this.useShellClient(vm.ws_endpoint).post("/verify", body).pipe( + catchError((e: HttpErrorResponse) => { + return throwError(e.error); + }), + tap((response: ServerResponse) => { + this.publishNewVerificationResults(response) + }) + ); + } + verify(vm: VM, vmName: string) { const body = [this.verificationTaskRequests.get(vmName)] @@ -59,9 +86,8 @@ export class VerificationService { } private publishNewVerificationResults(response: ServerResponse) { - const newVerificationList = JSON.parse(atob(response.content)) as unknown as TaskVerification[] - - newVerificationList.forEach((newTaskVerification: TaskVerification) => { + const newVerificationList = JSON.parse(atob(response.content)) as unknown as TaskVerificationResponse[] + newVerificationList.forEach((newTaskVerification: TaskVerificationResponse) => { const existingVerification = this._verifications.value.get(newTaskVerification.vm_name) if (existingVerification !== undefined) { existingVerification.task_command?.forEach((taskCommand, index, array) => {