Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ssa/vlass-manager-ui
1 result
Show changes
Commits on Source (3)
......@@ -33,7 +33,6 @@ import {JobspecTargetComponent} from './jobspecs/jobspec/jobspec-detail/jobspec-
import {JobspecInputComponent} from './jobspecs/jobspec/jobspec-detail/jobspec-input/jobspec-input.component';
import {JobspecExecutionComponent} from './jobspecs/jobspec/jobspec-detail/jobspec-execution/jobspec-execution.component';
import {ExecutionDetailComponent} from './executions/execution/execution-detail/execution-detail.component';
import {ExecutionDetailPlanesComponent} from './executions/execution/execution-detail/execution-detail-planes/execution-detail-planes.component';
import {FontAwesomeModule} from "@fortawesome/angular-fontawesome";
import {LoadingComponent} from './loading/loading.component';
import {QueueSettingsComponent} from './settings/queue-settings/queue-settings.component';
......@@ -77,7 +76,6 @@ export function init_app(configService: ConfigurationService) {
JobspecInputComponent,
JobspecExecutionComponent,
ExecutionDetailComponent,
ExecutionDetailPlanesComponent,
LoadingComponent,
QueueSettingsComponent,
FutureProductComponent,
......
<form [formGroup]="planesFormGroup" (ngSubmit)="acceptPlanes()" class="mb-2">
<h4 class="pt-2 border-top">
Planes
</h4>
<div class="w-100" *ngFor="let plane of getPlaneKeys()">
<label><input type="checkbox" [formControlName]="plane" value="{{plane}}" checked/>{{plane}}</label>
</div>
<button type="submit" class="btn btn-success btn-sm">
Accept &amp; Archive Selected Planes
</button>
</form>
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {ExecutionDetailPlanesComponent} from './execution-detail-planes.component';
describe('ExecutionDetailPlanesComponent', () => {
let component: ExecutionDetailPlanesComponent;
let fixture: ComponentFixture<ExecutionDetailPlanesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ExecutionDetailPlanesComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ExecutionDetailPlanesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import {Component, EventEmitter, Input, Output, OnDestroy, OnInit} from '@angular/core';
import {FormControl, FormGroup} from '@angular/forms';
import {AlertService} from '../../../../services/alert.service';
import {JobsService} from '../../../../services/jobs.service';
import {Job} from '../../../../model/job';
import {Observable} from 'rxjs';
@Component({
selector: 'app-execution-detail-planes',
templateUrl: './execution-detail-planes.component.html',
styleUrls: ['./execution-detail-planes.component.scss']
})
export class ExecutionDetailPlanesComponent implements OnInit, OnDestroy {
@Input() job: Job;
@Output() planesWritten: EventEmitter<any> = new EventEmitter();
planes: Observable<string>;
planeKeys: string[];
planesFormGroup: FormGroup;
constructor(
private jobService: JobsService,
private alertService: AlertService
) {
// Form group to contain the plane checkboxes
this.planesFormGroup = new FormGroup({});
this.planeKeys = null;
}
ngOnInit(): void {
}
ngOnDestroy(): void {
}
// Reads plane names from a JSON file and returns them in a list
getPlaneKeys(): string[] {
// Return the plane names if we already fetched them
if (this.planeKeys !== null) {
return this.planeKeys;
}
this.planeKeys = [];
// Get the plane names from the spectral window numbers in the planes.json file
this.jobService.getPlanes(this.job.job_id).subscribe(response => {
this.planeKeys = Object.keys(response.body);
// Create a form control for each of the plane checkboxes and add them into the same group
this.planeKeys.forEach(control => this.planesFormGroup.addControl(control, new FormControl(true)));
// Set the planes data here to signal that the controls are done being added and the HTML can finish loading
this.planes = response.body;
},
error => {
this.alertService.error('Could not retrieve planes from planes.json. ' + error);
});
return this.planeKeys;
}
// Writes to a file in lustre to flag planes to be accepted
acceptPlanes(): void {
this.alertService.info('Flagging accepted planes to be cached');
// Collect the selected planes and write their names separated by a newline
let planesText = '';
const planes = this.planesFormGroup.value;
Object.keys(planes).forEach(key => {
if (planes[key] === true) {
planesText += key + '\n';
}
});
planesText = planesText.trim();
// Write out the planes string if any are selected
if (planesText.length > 0) {
this.jobService.writePlanes(this.job.job_id, planesText).subscribe(
result => {},
error => {
this.alertService.error('Planes did not save. ' + error);
},
() => {
// Trigger acceptQa on the parent if there were no errors during the save
this.planesWritten.emit();
this.alertService.success('Planes Saved');
});
}
}
}
<ng-container *ngIf="jobDetail; else loading">
<div class="row no-gutters" *ngIf="jobDetail.queueName !== 'se_coarse_cube_imaging' && canAcceptArchive(jobDetail.status, jobDetail.archiveStatus)">
<div class="col">
<button type="button" class="btn btn-success btn-sm" (click)="acceptQa()">Accept &amp; Archive</button>
</div>
<div class="col" *ngIf="jobDetail.queueName == 'quicklook'">
<button type="button" class="btn btn-danger btn-sm" (click)="rejectQa()">Reject &amp; Archive</button>
</div>
</div>
<p><b>SDM ID:</b> {{ job.jobspec_sdm_id }} </p>
......@@ -26,7 +18,7 @@
</a>
</p>
<form [formGroup]="noteFormGroup" (ngSubmit)="updateNotes()" class="mb-2">
<form formGroup="noteFormGroup" (ngSubmit)="updateNotes()" class="mb-2">
<div class="row mt-3 mr-0">
<div class="col-auto">
<h4 class="pt-2">
......@@ -43,10 +35,33 @@
</div>
</form>
<app-execution-detail-planes [job]="job"
(planesWritten)="acceptQa()"
*ngIf="jobDetail.queueName === 'se_coarse_cube_imaging' && canAcceptArchive(jobDetail.status, jobDetail.archiveStatus)">
</app-execution-detail-planes>
<div *ngIf="canSelectPlanes()">
<h4 class="pt-2 border-top">
Planes
</h4>
<div class="w-100" *ngFor="let plane of getPlaneKeys()" formGroup="planesFormGroup">
<label><input type="checkbox" formControlName="plane" value="{{plane}}" checked/>{{plane}}</label>
</div>
</div>
<div *ngIf="canSelectTiles()">
<h4 class="pt-2 border-top">
Tiles
</h4>
<div class="w-100" *ngFor="let tile of getTiles()" formGroup="tilesFormGroup">
<label><input type="checkbox" formControlName="tile" value="{{tile}}" checked/>{{tile}}</label>
</div>
</div>
<div class="row no-gutters" *ngIf="jobDetail.queueName !== 'se_coarse_cube_imaging' && canAcceptArchive(jobDetail.status, jobDetail.archiveStatus)">
<div class="col">
<button type="button" class="btn btn-success btn-sm" (click)="acceptQa()">Accept &amp; Archive</button>
</div>
<div class="col" *ngIf="jobDetail.queueName == 'quicklook'">
<button type="button" class="btn btn-danger btn-sm" (click)="rejectQa()">Reject &amp; Archive</button>
</div>
</div>
<h4 class="pt-2 border-top">
<fa-icon [icon]="faList"></fa-icon>
......
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output} from '@angular/core';
import {Job, JobExecution} from "../../../model/job";
import {Subject} from "rxjs";
import {Subject, Observable, of} from "rxjs";
import {JobsService} from "../../../services/jobs.service";
import {FormControl, FormGroup} from "@angular/forms";
import {ConfigurationService} from "../../../env/configuration.service";
......@@ -14,31 +14,32 @@ import {auditTime, takeUntil} from "rxjs/operators";
styleUrls: ['./execution-detail.component.scss']
})
export class ExecutionDetailComponent implements OnInit, OnDestroy {
noteFormGroup = new FormGroup({
notes: new FormControl(),
id: new FormControl()
});
planesFormGroup = new FormGroup({});
private ngUnsubscribe = new Subject<void>();
@Input() job: Job;
@Output() reload = new EventEmitter();
public jobDetail: JobExecution;
noteFormGroup: FormGroup;
public faSave = faSave;
public faList = faList;
public faCheckCircle = faCheckCircle;
public faStickyNote = faStickyNote;
public faCopy = faCopy;
public weblogUrl;
public weblogUrl: string;
planeKeys: string[] = [];
tiles: string[] = [];
constructor(
private configService: ConfigurationService,
private jobService: JobsService,
private alertService: AlertService
) {
this.noteFormGroup = new FormGroup({
notes: new FormControl(),
id: new FormControl()
});
}
ngOnInit() {
......@@ -128,6 +129,9 @@ export class ExecutionDetailComponent implements OnInit, OnDestroy {
}
acceptQa() {
if (this.canSelectPlanes()) {
this.acceptPlanes();
}
this.updateNotes(); // make sure notes are saved before submitting
this.alertService.info('Accepting ' + this.job.job_id);
this.performQa(this.job.job_id, 'accept');
......@@ -162,6 +166,78 @@ export class ExecutionDetailComponent implements OnInit, OnDestroy {
}
};
canSelectPlanes(): boolean {
return this.jobDetail.queueName === 'se_continuum_cube_imaging' || true;
}
canSelectTiles(): boolean {
return this.jobDetail.queueName === 'calibration' || true;
}
// Reads plane names from a JSON file and returns them in a list
getPlaneKeys(): string[] {
// Return the plane names if we already fetched them
if (this.planeKeys.length > 0) {
return this.planeKeys;
}
this.planeKeys = [];
// Get the plane names from the spectral window numbers in the planes.json file
this.jobService.getPlanes(this.job.job_id).subscribe((response: string[]) => {
this.planeKeys = response;
},
error => {
this.alertService.error('Could not retrieve planes from planes.json. ' + error);
});
return this.planeKeys;
}
// Reads tile names from a JSON file and returns them in a list
getTiles(): string[] {
// Return the plane names if we already fetched them
if (this.tiles.length > 0) {
return this.tiles;
}
this.tiles = [];
// Get the plane names from the spectral window numbers in the planes.json file
this.jobService.getTiles(this.job.job_id).subscribe((response: string[]) => {
this.tiles = response;
},
error => {
this.alertService.error('Could not retrieve tiles: ' + error);
});
return this.tiles;
}
// Writes to a file in lustre to flag planes to be accepted
acceptPlanes(): void {
this.alertService.info('Flagging accepted planes to be cached');
// Collect the selected planes and write their names separated by a newline
let planesText = '';
const planes = this.planesFormGroup.value;
Object.keys(planes).forEach(key => {
if (planes[key] === true) {
planesText += key + '\n';
}
});
planesText = planesText.trim();
// Write out the planes string if any are selected
if (planesText.length > 0) {
this.jobService.writePlanes(this.job.job_id, planesText).subscribe(
result => {},
error => {
this.alertService.error('Planes did not save. ' + error);
},
() => {
this.alertService.success('Planes Saved');
});
}
}
ngOnDestroy(): void {
this.ngUnsubscribe.next();
......
import {Injectable} from '@angular/core';
import {HttpClient, HttpParams} from "@angular/common/http";
import {ConfigurationService} from "../env/configuration.service";
import {Observable} from "rxjs";
import {Observable, of} from "rxjs";
import {map, switchMap} from "rxjs/operators";
import {Job, JobExecution, JobSpec} from "../model/job";
import {FiltersService} from "./filters.service";
......@@ -164,19 +164,30 @@ export class JobsService {
}
// Returns a JSON encoded string of plane information
public getPlanes(id: number): Observable<any> {
return this.http.get(this.configService.config.url + this.endPoint + 'jobs/' + id + '/planes', {observe: 'response'}).pipe(
map(response => {
return response;
}));
public getPlanes(id: number): Observable<string[]> {
// return this.http.get(this.configService.config.url + this.endPoint + 'jobs/' + id + '/planes', {observe: 'response'}).pipe(
// map(response => {
// return response;
// }));
return of(["plane1", "plane2", "plane3"]);
}
// Returns a JSON encoded string of plane information
public getTiles(id: number): Observable<string[]> {
// return this.http.get<string[]>(this.configService.config.url + this.endPoint + 'jobs/' + id + '/tiles', {observe: 'response'}).pipe(
// map(response => {
// return response.body;
// }));
return of(["tile1", "tile2"]);
}
// Writes a string of plane names
public writePlanes(id: number, planes: string): Observable<any> {
return this.http.put(this.configService.config.url + this.endPoint + 'jobs/' + id + '/writePlanes', {planes}, {observe: 'response'}).pipe(
map(response => {
return response.status;
}));
// return this.http.put(this.configService.config.url + this.endPoint + 'jobs/' + id + '/writePlanes', {planes}, {observe: 'response'}).pipe(
// map(response => {
// return response.status;
// }));
return of("ab")
}
// Returns a response containing the execution's pipeline directory to append to the weblog URL as a string
......