diff --git a/apps/web/src/app/workspaces/components/capability-request/capability-request.component.html b/apps/web/src/app/workspaces/components/capability-request/capability-request.component.html index efc305295b9cbe2cb4a6316ea86c89691d89b3f6..dbbf9f31cde039f9a87fd81a5b38e39bd29a8f0d 100644 --- a/apps/web/src/app/workspaces/components/capability-request/capability-request.component.html +++ b/apps/web/src/app/workspaces/components/capability-request/capability-request.component.html @@ -102,49 +102,51 @@ </div> </div> - <div id="parameters-files-versions-container" class="col-7"> - + <div id="parameters-files-container" class="col-7"> + <span id="versions-label">Versions</span> <app-versions id="versions" class="pt-2" - [capabilityVersions]="this.capabilityVersions" - > - - </app-versions> - <span id="versions-label">Versions</span> - <div id="versions-container" class="container fluid"> - - <form [formGroup]="form"> - <div class="form-group"> - <select id="versions-dropdown" class="custom-select"> - <option *ngFor="let version of this.capabilityVersions">{{version.version_number}}</option> - </select> - </div> - </form> - </div> + [capabilityRequest]="this.capabilityRequest" + (versionEvent) = setVersion($event) + ></app-versions> <br/> - - <span id="parameters-label">Parameters</span> + <span id="parameters-label" *ngIf="currentVersion !== undefined">Version {{currentVersion.version_number}} Parameters</span> + <span id="parameters-label" *ngIf="currentVersion === undefined">Version {{latestVersion.version_number}} Parameters</span> <app-parameters id="parameters" class="pt-2" - [capabilityRequest]="this.capabilityRequest" + [currentVersion]="currentVersion" + *ngIf="currentVersion !== undefined" + ></app-parameters> + <app-parameters + id="parameters" + class="pt-2" + [currentVersion]="latestVersion" + *ngIf="currentVersion === undefined" ></app-parameters> <br/> - <span id="files-label">Files</span> + <span id="files-label" *ngIf="currentVersion !== undefined">Version {{currentVersion.version_number}} Files</span> + <span id="files-label" *ngIf="currentVersion === undefined">Version {{latestVersion.version_number}} Files</span> <app-files id="files" class="pt-2" - [capabilityVersion]="this.currentVersion" + [capabilityVersion]="currentVersion" *ngIf="currentVersion !== undefined" ></app-files> + <app-files + id="files" + class="pt-2" + [capabilityVersion]="latestVersion" + *ngIf="currentVersion === undefined" + ></app-files> <br/> <app-metadata id="metadata" class="pt-2" - [capabilityVersion]="this.currentVersion" + [capabilityVersion]="currentVersion" *ngIf=" - this.currentVersion !== undefined && this.currentVersion.workflow_metadata !== null + currentVersion !== undefined && currentVersion.workflow_metadata !== null " ></app-metadata> <br/> diff --git a/apps/web/src/app/workspaces/components/capability-request/capability-request.component.ts b/apps/web/src/app/workspaces/components/capability-request/capability-request.component.ts index 4278d70bf604388cf741ddd4e102d4fe9c1ad108..db275da0f12102c1c33e7ee56053bbc3c489270b 100644 --- a/apps/web/src/app/workspaces/components/capability-request/capability-request.component.ts +++ b/apps/web/src/app/workspaces/components/capability-request/capability-request.component.ts @@ -16,20 +16,19 @@ * You should have received a copy of the GNU General Public License * along with Workspaces. If not, see <https://www.gnu.org/licenses/>. */ -import { Component, OnDestroy, 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 { CapabilityRequestService } from "../../services/capability-request.service"; -import { CapabilityVersion } from "../../model/capability-version"; -import { PollingDataUpdaterService } from "../../services/polling-data-updater.service"; -import { AlertService } from "../../../shared/alert/alert.service"; -import { JsonObject } from "@angular/compiler-cli/ngcc/src/packages/entry_point"; -import { Subject } from "rxjs"; -import { takeUntil } from "rxjs/operators"; -import { Capability } from "../../model/capability"; -import { FormControl, FormGroup, Validators } from "@angular/forms"; +import {Component, OnDestroy, 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 {CapabilityRequestService} from "../../services/capability-request.service"; +import {CapabilityVersion} from "../../model/capability-version"; +import {PollingDataUpdaterService} from "../../services/polling-data-updater.service"; +import {AlertService} from "../../../shared/alert/alert.service"; +import {JsonObject} from "@angular/compiler-cli/ngcc/src/packages/entry_point"; +import {Subject} from "rxjs"; +import {takeUntil} from "rxjs/operators"; +import {Capability} from "../../model/capability"; @Component({ selector: "app-capability-request", @@ -41,18 +40,10 @@ export class CapabilityRequestComponent implements OnInit, OnDestroy { public capability: Capability; public capabilityExecution: CapabilityExecution; public currentVersion: CapabilityVersion; - public capabilityVersions: Array<CapabilityVersion> = []; + public latestVersion: CapabilityVersion; private ngUnsubscribe = new Subject(); // to signal when all subscribers should unsubscribe (triggered in tear down) - form = new FormGroup({ - version: new FormControl("", Validators.required), - }); - - get f() { - return this.form.controls; - } - // Observer for capability request objects private capabilityRequestObserver = { next: (request) => { @@ -93,17 +84,10 @@ export class CapabilityRequestComponent implements OnInit, OnDestroy { private capabilityVersionObserver = { next: (capabilityVersion) => { if (capabilityVersion !== undefined) { - this.currentVersion = capabilityVersion; + this.latestVersion = capabilityVersion; } else { console.error("Current version returned undefined."); } - if ( - !this.capabilityVersions.find( - (version) => version.version_number == this.currentVersion.version_number, - ) - ) { - this.getAllVersions(); - } }, error: (error) => console.error("Error when retrieving current version:" + error), }; @@ -189,26 +173,12 @@ export class CapabilityRequestComponent implements OnInit, OnDestroy { .subscribe(addRestCallObservable); } - /** - * retrieve every capability version belonging to our capability request - * TODO: call from ngOnInit()? - */ - getAllVersions() { - // TODO: hard-coded for demo only; IRL, get request's versions from a service or something - const anotherVersion: CapabilityVersion = { - version_number: 1, - state: "Created", - capability_request_id: this.currentVersion.capability_request_id, - parameters: this.currentVersion.parameters, - workflow_metadata: this.currentVersion.workflow_metadata, - files: this.currentVersion.files, - type: this.currentVersion.type, - }; - this.capabilityVersions.push(this.currentVersion); - this.capabilityVersions.push(anotherVersion); + setVersion(version: CapabilityVersion){ + this.currentVersion = version; } - ngOnInit(): void {} + ngOnInit(): void { + } ngOnDestroy(): void { // Prevent memory leakage by unsubscribing all observers diff --git a/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.html b/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.html index 0d39260ea4bff17939eac34f255404a2c139db5e..426f5a6d22824f26098e4e20ed992988cab24a77 100644 --- a/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.html +++ b/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.html @@ -1,6 +1,6 @@ <div id="parameters-container" class="container-fluid rounded-top rounded-3 p-3"> - <div *ngIf="isEmpty(capabilityRequest.parameters) === false; else noParametersMessage"> - <div class="row my-2" *ngFor="let parameter of capabilityRequest.parameters | keyvalue"> + <div *ngIf="isEmpty(currentVersion.parameters) === false; else noParametersMessage"> + <div class="row my-2" *ngFor="let parameter of currentVersion.parameters | keyvalue"> <div class="col"> <span class="rounded-pill px-2 py-1 argument-key">{{ parameter.key }}</span> <span class="px-1"> = </span> diff --git a/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.ts b/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.ts index 48d118c251c3d4a0201602af2a05ca00af2dd84d..70c09701c54a3db15ba0c84f6a54946864ccac65 100644 --- a/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.ts +++ b/apps/web/src/app/workspaces/components/capability-request/components/parameters/parameters.component.ts @@ -19,6 +19,7 @@ import { Component, Input, OnInit } from "@angular/core"; import { CapabilityRequest } from "../../../../model/capability-request"; import { JsonObject } from "@angular/compiler-cli/ngcc/src/packages/entry_point"; +import {CapabilityVersion} from "../../../../model/capability-version"; @Component({ selector: "app-parameters", @@ -26,7 +27,7 @@ import { JsonObject } from "@angular/compiler-cli/ngcc/src/packages/entry_point" styleUrls: ["./parameters.component.scss"], }) export class ParametersComponent implements OnInit { - @Input() capabilityRequest: CapabilityRequest; + @Input() currentVersion: CapabilityVersion; constructor() {} diff --git a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.html b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.html index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d0b3e887d005ad7d15268228840e9529819fea81 100644 --- a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.html +++ b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.html @@ -0,0 +1,37 @@ +<div id="versions-container" class="container-fluid rounded-top rounded-3 p-3"> + <div ngbDropdown class="d-inline"> + <button class="btn btn-outline-secondary" id="versionDropdown" ngbDropdownToggle (click)="getAllVersions(capabilityRequest.id)" *ngIf="selected_version">Version {{selected_version.version_number}}</button> + <button class="btn btn-outline-secondary" id="versionDropdown" ngbDropdownToggle (click)="getAllVersions(capabilityRequest.id)" *ngIf="!selected_version">Select Version</button> + <div ngbDropdownMenu aria-labelledby="versionDropdown"> + <button ngbDropdownItem *ngFor="let version of capabilityVersions" (click)="getSpecificVersion(capabilityRequest.id, version.version_number)">{{version.version_number}}</button> + </div> + </div> + + <div class="d-inline-flex" *ngIf="selected_version"> + <h5 class="d-flex p-2"> + <span + id="version-status-badge-complete" + class="badge badge-pill badge-success py-2" + *ngIf="selected_version.state === 'Complete'" + ><span id="version-status-badge-txt-complete">{{ selected_version.state.toUpperCase() }}</span></span> + <span + id="version-status-badge-running" + class="badge badge-pill badge-primary py-2" + *ngIf="selected_version.state === 'Running'" + ><span id="version-status-badge-txt-running">{{ selected_version.state.toUpperCase() }}</span></span> + <span + id="version-status-badge-ready" + class="badge badge-pill badge-secondary py-2" + *ngIf="selected_version.state === 'Created'" + ><span id="version-status-badge-txt-ready">{{ selected_version.state.toUpperCase() }}</span></span> + <span + id="version-status-badge-failed" + class="badge badge-pill badge-danger py-2" + *ngIf="selected_version.state === 'Failed'" + ><span id="version-status-badge-txt-failed">{{ selected_version.state.toUpperCase() }}</span></span> + </h5> + </div> +</div> + +<ng-template #noParametersMessage> <em>This version has no parameters.</em> </ng-template> +<ng-template #noFilesMessage> <em>No files are attached to this request.</em> </ng-template> diff --git a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.scss b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6821f2d4d188fe499e4c38edb63ece10b265a40c 100644 --- a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.scss +++ b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.scss @@ -0,0 +1,20 @@ +@import "src/variables"; + +.argument-key, +.argument-value { + background-color: $parameters-pill-color; +} + +.filename { + background-color: $parameters-pill-color; +} + +#versions-container { + background-color: $parameters-container-bg; +} +#selected-version-parameters { + background-color: $parameters-container-bg; +} +#selected-version-files { + background-color: $parameters-container-bg; +} diff --git a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.ts b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.ts index 26296550d93637f5dc69c16ed014db5e80f6b8f6..4c5d484280b13ba95842d486e7868ff53c68649d 100644 --- a/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.ts +++ b/apps/web/src/app/workspaces/components/capability-request/components/versions/versions.component.ts @@ -16,8 +16,12 @@ * You should have received a copy of the GNU General Public License * along with Workspaces. If not, see <https://www.gnu.org/licenses/>. */ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input, OnInit, Output, EventEmitter} from '@angular/core'; import {CapabilityVersion} from "../../../../model/capability-version"; +import {CapabilityRequestService} from "../../../../services/capability-request.service"; +import {CapabilityRequest} from "../../../../model/capability-request"; +import {FormControl, FormGroup, Validators} from "@angular/forms"; +import {JsonObject} from "@angular/compiler-cli/ngcc/src/packages/entry_point"; @Component({ selector: 'app-versions', @@ -26,11 +30,60 @@ import {CapabilityVersion} from "../../../../model/capability-version"; }) export class VersionsComponent implements OnInit { - @Input() capabilityVersions: Array<CapabilityVersion>; + @Input() capabilityRequest: CapabilityRequest; + @Output() versionEvent = new EventEmitter<CapabilityVersion>(); + public capabilityVersions: Array<CapabilityVersion>; + public selected_version: CapabilityVersion - constructor() { } + + constructor(private capabilityRequestService: CapabilityRequestService) { + // this.getSpecificVersion(this.capabilityRequest.id, this.capabilityRequest.versions[this.capabilityRequest.versions.length-1].version_number); + } ngOnInit(): void { } + getVersion(): number { + return this.selected_version.version_number; + } + + getAllVersions(requestId: string) { + const versionsObserver = { + next: (request) => { + this.capabilityVersions = request; + console.log(this.capabilityVersions) + }, + error: (error) => console.error("Error when retrieving capability versions:" + error), + }; + this.capabilityRequestService.getAllVersions(requestId).subscribe(versionsObserver); + } + + getSpecificVersion(request_id: string, version_id: number){ + const specificVersionObserver = { + next: (version) => { + this.selected_version = version; + this.versionEvent.emit(version); + }, + error: (error) => console.error("Error when retrieving capability version:" + error), + }; + this.capabilityRequestService.getSpecificVersion(request_id, version_id).subscribe(specificVersionObserver); + } + + + /** + * Check if JsonObject is empty + * Taken from: https://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object + * @param obj Object to be checked + * @return boolean true if object is empty; else false + */ + isEmpty(obj: JsonObject): boolean { + for (const prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } + + return true; + } + } diff --git a/apps/web/src/app/workspaces/model/capability-request.ts b/apps/web/src/app/workspaces/model/capability-request.ts index ff59d736286556039f5e780d3b0f75e44bb1f4a6..93151486e581a6f46d6e6e04f2029879c43f55c4 100644 --- a/apps/web/src/app/workspaces/model/capability-request.ts +++ b/apps/web/src/app/workspaces/model/capability-request.ts @@ -19,6 +19,7 @@ import { CapabilityExecution } from "./capability-execution"; import { JsonObject } from "@angular/compiler-cli/ngcc/src/packages/entry_point"; import {Capability} from "./capability"; +import {CapabilityVersion} from "./capability-version"; export interface CapabilityRequest { id: string; @@ -26,6 +27,7 @@ export interface CapabilityRequest { capability: Capability; state: string; parameters: JsonObject; + versions: Array<CapabilityVersion>; current_execution: CapabilityExecution; ingested: boolean; created_at: string; diff --git a/apps/web/src/app/workspaces/services/capability-request.service.ts b/apps/web/src/app/workspaces/services/capability-request.service.ts index 23c1b57425fd57c01e71e5f5c86a39e230a5c213..d32fe0aa836e9b0d331aa1da90a1bfe17345a49c 100644 --- a/apps/web/src/app/workspaces/services/capability-request.service.ts +++ b/apps/web/src/app/workspaces/services/capability-request.service.ts @@ -80,12 +80,18 @@ export class CapabilityRequestService { } /** - * Gets URL to retrieve a list of active capability requests for a given capability - * @param capabilityName The name of the capability + * Get all versions of a capability request + * @param requestId ID of the parent request + * @return Array<CapabilityVersion> Result of REST call to retrieve all versions */ - public getCreatedCapabilityRequestsUrl(capabilityName: string): string { - return `capability/${capabilityName}/created-requests`; + public getAllVersions(requestId: string): Observable<Array<CapabilityVersion>> { + const getVersions = `capability/request/${requestId}/versions`; + return this.httpClient.get<any>(getVersions); + } + public getSpecificVersion(request_id: string, version_id: number): Observable<JsonObject>{ + const url = `capability/request/${request_id}/version/${version_id}`; + return this.httpClient.get<JsonObject>(url); } /** diff --git a/services/capability/capability/views/capability_request.py b/services/capability/capability/views/capability_request.py index 7a010b5fe8290a50a2a4484be11b23740f21f1f2..89e9379d4eff262ad48875435af7e2133003056c 100644 --- a/services/capability/capability/views/capability_request.py +++ b/services/capability/capability/views/capability_request.py @@ -33,7 +33,7 @@ from pyramid.view import view_config def view_capability_request(request: Request) -> Response: """ Pyramid view that accepts a request to view a capability request and responds with the request's info, if it exists - URL: capability/{capability_name}/request/{request_id} + URL: capability/request/{request_id} :param request: GET request :return: 200 OK response with JSON-formatted capability request info if found