Skip to content
Snippets Groups Projects
Commit bbded616 authored by Nathan Hertz's avatar Nathan Hertz
Browse files

- Capability request status page now grabs all correct information from its...

- Capability request status page now grabs all correct information from its request and fills that into the UI
- If the request is complete and the execution has a delivery URL, a download button appears on the page linking to the download area
parent 357e4ed0
No related branches found
No related tags found
1 merge request!191WS-191: Capability request status page grabs info from DB
Pipeline #1328 passed with warnings
Showing
with 149 additions and 61 deletions
......@@ -23,14 +23,8 @@ $running-status-bg-gradient: linear-gradient(
);
// QUEUED status color
$running-status-bg-light: #5fb2f4;
$running-status-bg-dark: #2196f3;
$running-status-bg-gradient: linear-gradient(
0deg,
$running-status-bg-dark 0%,
$running-status-bg-light 100%
);
$queued-status-bg: #b6b4b4;
// Capability request parameters
$parameters-container-bg: #f7f7f7;
$parameters-container-bg: #ffffff;
$parameters-pill-color: #d9d8d8;
<header>
<app-request-header></app-request-header>
</header>
<div id="definition-parameters-and-versions" class="container-fluid">
<div class="row">
<div id="capability-definition-container" class="col">
<span id="capability-label">Capability</span>
<app-capability-definition id="capability-definition"></app-capability-definition>
</div>
<div id="parameters-container" class="col">
<span id="parameters-label">Parameters</span>
<app-parameters id="parameters"></app-parameters>
<div *ngIf="capabilityRequest">
<header>
<app-request-header [capabilityRequest]="capabilityRequest"></app-request-header>
</header>
<div id="definition-parameters-and-versions" class="container-fluid">
<div class="row">
<div id="capability-definition-container" class="col">
<span id="capability-label">Capability</span>
<app-capability-definition
*ngIf="capability !== undefined"
id="capability-definition"
[capabilityRequest]="capabilityRequest"
[capability]="capability"
></app-capability-definition>
<div
class="d-flex justify-content-center py-3"
*ngIf="capabilityRequest.state === 'Complete' && capabilityExecution.delivery_url"
>
<a class="btn btn-warning" href="{{ capabilityExecution.delivery_url }}">Download</a>
</div>
</div>
<div id="parameters-container" class="col">
<span id="parameters-label">Parameters</span>
<app-parameters id="parameters" [capabilityRequest]="capabilityRequest"></app-parameters>
</div>
</div>
</div>
</div>
import { Component, OnInit } from "@angular/core";
import { CapabilityRequest } from "../../model/capability-request";
import { ActivatedRoute } from "@angular/router";
import { DataRetrieverService } from "../../services/data-retriever.service";
import { CapabilityExecution } from "../../model/capability-execution";
import { Capability } from "../../model/capability";
@Component({
selector: "app-capability-request",
......@@ -7,10 +11,30 @@ import { CapabilityRequest } from "../../model/capability-request";
styleUrls: ["./capability-request.component.scss"],
})
export class CapabilityRequestComponent implements OnInit {
private capabilityRequest: CapabilityRequest;
public capabilityRequest: CapabilityRequest;
public capability: Capability;
public capabilityExecution: CapabilityExecution;
constructor() {
this.capabilityRequest = null;
private capabilityRequestObserver = {
next: (request) => {
this.capabilityRequest = request;
this.capabilityExecution = request.current_execution;
this.dataRetriever
.getCapability(this.capabilityRequest.capability_name)
.subscribe(this.capabilityObserver);
},
error: (error) => console.error("Error when retrieving capability request:" + error),
};
private capabilityObserver = {
next: (capability) => {
this.capability = capability;
},
error: (error) => console.error("Error when retrieving capability:" + error),
};
constructor(private route: ActivatedRoute, private dataRetriever: DataRetrieverService) {
const requestID = parseInt(this.route.snapshot.paramMap.get("id"));
this.dataRetriever.getCapabilityRequest(requestID).subscribe(this.capabilityRequestObserver);
}
ngOnInit(): void {}
......
<div id="definition-container">
<h5 id="capability-name">null</h5>
<h5 id="capability-name">{{ capability.name }}</h5>
<div id="step-sequence">
<div class="container-fluid">
<div class="row bg-primary rounded rounded-lg mb-1 text-white py-2 align-items-center">
<div class="col">RUN WORKFLOW null</div>
<div
class="row bg-primary rounded rounded-lg mb-1 text-white py-2 align-items-center"
*ngFor="let step of capabilityStepList"
>
<div class="col">{{ step[0].toUpperCase() }} {{ step[1] }}</div>
<div class="col-auto">
<span class="fas fa-play-circle fa-2x"></span>
</div>
</div>
<div class="row bg-secondary rounded rounded-lg mb-1 text-white py-2 align-items-center">
<div class="col">AWAIT WORKFLOW</div>
<div class="col-auto"><span class="fa fa-circle fa-2x"></span></div>
</div>
</div>
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit } from "@angular/core";
import { CapabilityRequest } from "../../../../model/capability-request";
import { Capability } from "../../../../model/capability";
@Component({
selector: 'app-capability-definition',
templateUrl: './capability-definition.component.html',
styleUrls: ['./capability-definition.component.scss']
selector: "app-capability-definition",
templateUrl: "./capability-definition.component.html",
styleUrls: ["./capability-definition.component.scss"],
})
export class CapabilityDefinitionComponent implements OnInit {
@Input() capabilityRequest: CapabilityRequest;
@Input() capability: Capability;
public capabilityStepList: Array<Array<string>>;
constructor() { }
constructor() {}
ngOnInit(): void {
this.capabilityStepList = this.stepStringToList(this.capability.steps);
}
stepStringToList(stepString: string): Array<Array<string>> {
const step_list = stepString.split("\n");
const splitStepList = [];
step_list.forEach((step) => splitStepList.push(step.split(" ")));
return splitStepList;
}
}
<div id="parameters-container" class="container-fluid rounded-top rounded-3 p-3">
<div class="row">
<div class="row" *ngFor="let parameter of capabilityRequest.parameters | keyvalue">
<div class="col">
<span class="rounded-pill px-2 py-1 argument-key">arguments</span>
<span class="rounded-pill px-2 py-1 argument-key">{{ parameter.key }}</span>
<span class="px-1"> = </span>
<span class="rounded-pill px-2 py-1 argument-value">null</span>
<span class="rounded-pill px-2 py-1 argument-value">{{ parameter.value }}</span>
</div>
</div>
</div>
import { Component, OnInit } from "@angular/core";
import { Component, Input, OnInit } from "@angular/core";
import { CapabilityRequest } from "../../../../model/capability-request";
@Component({
selector: "app-parameters",
......@@ -6,6 +7,8 @@ import { Component, OnInit } from "@angular/core";
styleUrls: ["./parameters.component.scss"],
})
export class ParametersComponent implements OnInit {
@Input() capabilityRequest: CapabilityRequest;
constructor() {}
ngOnInit(): void {}
......
<div id="request-id-and-status">
<h2 id="request-id">Request #7</h2>
<app-running-status-button id="request-status"></app-running-status-button>
<h2 id="request-id">Request #{{ capabilityRequest.id }}</h2>
<app-running-status-button
id="request-status"
[capabilityRequest]="capabilityRequest"
></app-running-status-button>
</div>
<div id="created-and-updated-timestamps">
<h5 id="created-time" class="timestamp">Created 2 hours ago</h5>
<h5 id="last-updated-time" class="timestamp">Updated 2 seconds ago</h5>
<h5 id="created-time" class="timestamp">Created at {{ capabilityRequest.created_at }}</h5>
<h5 id="last-updated-time" class="timestamp">Updated at {{ capabilityRequest.updated_at }}</h5>
</div>
import { Component, OnInit } from "@angular/core";
import { Component, Input, OnInit } from "@angular/core";
import { CapabilityRequest } from "../../../../model/capability-request";
@Component({
selector: "app-request-header",
......@@ -6,6 +7,8 @@ import { Component, OnInit } from "@angular/core";
styleUrls: ["./request-header.component.scss"],
})
export class RequestHeaderComponent implements OnInit {
@Input() capabilityRequest: CapabilityRequest;
constructor() {}
ngOnInit(): void {}
......
<button id="request-status-button" type="button" class="running-status btn btn-success">
<span class="fas fa-play"></span><span id="request-status-button-txt">RUNNING</span>
<span class="fas fa-play"></span
><span id="request-status-button-txt">{{ capabilityRequest.state.toUpperCase() }}</span>
</button>
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit } from "@angular/core";
import { CapabilityRequest } from "../../../../../model/capability-request";
@Component({
selector: 'app-running-status-button',
templateUrl: './running-status-button.component.html',
styleUrls: ['./running-status-button.component.scss']
selector: "app-running-status-button",
templateUrl: "./running-status-button.component.html",
styleUrls: ["./running-status-button.component.scss"],
})
export class RunningStatusButtonComponent implements OnInit {
@Input() capabilityRequest: CapabilityRequest;
constructor() { }
ngOnInit(): void {
}
constructor() {}
ngOnInit(): void {}
}
......@@ -5,4 +5,8 @@ export interface CapabilityExecution {
id: string;
state: string;
version_number: string;
delivery_url: string;
created_at: string;
updated_at: string;
type: string;
}
import { CapabilityExecution } from "./capability-execution";
export interface CapabilityRequest {
id: string;
capabilityId: string;
capability_name: string;
state: string;
parameters: Array<string>;
// TODO: Add versions
parameters: JSON;
current_execution: CapabilityExecution;
created_at: string;
updated_at: string;
type: string;
}
export interface Capability {
name: string;
steps: string;
max_jobs: string;
enabled: string;
}
......@@ -2,6 +2,7 @@ import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { CapabilityRequest } from "../model/capability-request";
import { Capability } from "../model/capability";
@Injectable({
providedIn: "root",
......@@ -13,4 +14,8 @@ export class DataRetrieverService {
const url = `capability/request/${id}`;
return this.httpClient.get<CapabilityRequest>(url);
}
getCapability(name: string): Observable<Capability> {
const url = `capability/${name}`;
return this.httpClient.get<Capability>(url);
}
}
......@@ -5,7 +5,7 @@ import { CapabilityRequestComponent } from "./components/capability-request/capa
const routes: Routes = [
{ path: "", component: WorkspacesComponent },
{ path: "request-status", component: CapabilityRequestComponent },
{ path: "request-status/:id", component: CapabilityRequestComponent },
{ path: "**", redirectTo: "Search", pathMatch: "full" },
];
......
@import "~bootstrap/scss/bootstrap.scss";
//@import "src/variables.scss";
* {
font-family: "Lato", Helvetica, Arial, sans-serif;
......
......@@ -28,8 +28,7 @@ def view_capability_request(request: Request) -> Response:
return Response(json_body=capability_request.__json__())
else:
not_found_msg = (
f"Capability request for capability {request.matchdict['capability_name']}",
f"with ID {request.matchdict['request_id']} not found.",
f"Capability request with ID {request.matchdict['request_id']} not found.",
)
return HTTPNotFound(detail=not_found_msg)
......
......@@ -172,6 +172,9 @@ class CapabilityRequest(Base, CapabilityRequestIF):
"parameters": self.parameters,
"created_at": self.created_at.isoformat(),
"updated_at": self.updated_at.isoformat(),
"current_execution": self.current_execution.__json__()
if self.current_execution
else None,
}
@classmethod
......@@ -182,6 +185,14 @@ class CapabilityRequest(Base, CapabilityRequestIF):
copy["updated_at"] = datetime.datetime.fromisoformat(copy["updated_at"])
return CapabilityRequest(**copy)
@property
def current_version(self) -> CapabilityVersion:
return self.versions[-1] if len(self.versions) else None
@property
def current_execution(self) -> CapabilityExecution:
return self.current_version.current_execution if self.current_version else None
class CapabilityVersion(Base, CapabilityVersionIF):
"""
......@@ -204,6 +215,10 @@ class CapabilityVersion(Base, CapabilityVersionIF):
def capability(self):
return self.request.capability
@property
def current_execution(self) -> CapabilityExecution:
return self.executions[-1] if len(self.executions) else None
class SaPath(sa.types.TypeDecorator):
impl = sa.types.String
......@@ -288,6 +303,7 @@ class CapabilityExecution(Base, CapabilityExecutionIF, JSONSerializable):
version_number=self.version_number,
current_step=self.current_step,
current_workflow_request_id=self.current_workflow_request_id,
delivery_url=self.delivery_url,
created_at=self.created_at.isoformat(),
updated_at=self.updated_at.isoformat(),
)
......
......@@ -113,7 +113,8 @@ class CapabilityService(CapabilityServiceIF):
)
# update some fields on the execution, if possible
execution.delivery_url = delivery["url"] if "url" in delivery else None
# Extra / at the end added to make nginx happy -nhertz
execution.delivery_url = delivery["url"] + "/" if "url" in delivery else None
execution.delivery_path = delivery["delivered_to"] if "delivered_to" in delivery else None
@on_message(type="capability-submitted")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment