Merge pull request #110 from sartography/chore/bpmn-refactor-455

Chore/bpmn refactor 455
This commit is contained in:
Dan Funk 2021-10-13 12:10:14 -04:00 committed by GitHub
commit 97736f824f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 89 additions and 51 deletions

View File

@ -26,6 +26,14 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
One way to check for coverage:
Install lcov (in ubuntu: sudo apt-get install lcov)
run `ng test --no-watch --code-coverage` to generate a coverage directory, with an lcov file in it
run `genhtml coverage/lcov.info -o coverage/html` to generate an html doc that looks at coverage (index.html)
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

View File

@ -1,5 +1,5 @@
<div mat-dialog-title *ngIf="data && data.category">
Delete category <strong>{{data.category.id}}</strong>?
Delete category <strong>{{data.category.display_name}}</strong>?
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
</div>
<div mat-dialog-content>

View File

@ -1,7 +1,11 @@
<div mat-dialog-title>
<div *ngIf="!this.data.library" mat-dialog-title>
<h1>Workflow Specification</h1>
</div>
<div *ngIf="this.data.library" mat-dialog-title>
<h1>Library Specification</h1>
</div>
<div mat-dialog-content>
<form [formGroup]="form">
<formly-form [model]="model" [fields]="fields" [options]="options" [form]="form"></formly-form>

View File

@ -1,3 +1,3 @@
::ng-deep formly-field mat-form-field {
margin-bottom: 40px;
}

View File

@ -68,6 +68,7 @@ export class WorkflowSpecDialogComponent {
required: true,
options: this.categories
},
hideExpression: this.data.library,
},
{
key: 'display_name',
@ -92,25 +93,15 @@ export class WorkflowSpecDialogComponent {
required: true,
},
},
{
{
key: 'standalone',
type: 'checkbox',
defaultValue: this.data.standalone ? this.data.standalone : false,
templateOptions: {
label: 'Standalone',
description: 'Is this a standalone workflow?',
indeterminate: false,
},
hideExpression: true,
},
{
key: 'library',
type: 'checkbox',
defaultValue: this.data.library ? this.data.library : false,
templateOptions: {
label: 'Library',
description: 'Is this a library workflow?',
indeterminate: false,
},
hideExpression: true,
},
];
});

View File

@ -18,9 +18,6 @@
<dl gdAreas="field value" gdColumns="10ch auto">
<dt>Name</dt><dd>{{workflowSpec.id}}</dd>
<dt>Description</dt><dd>{{workflowSpec.description}}</dd>
<dt>Standalone</dt><dd *ngIf="workflowSpec.standalone; then thenBlock else elseBlock"></dd>
<ng-template #thenBlock><dd>True</dd></ng-template>
<ng-template #elseBlock><dd>False</dd></ng-template>
</dl>
<h4>Workflow Spec Files</h4>
<app-file-list [workflowSpec]="workflowSpec"></app-file-list>

View File

@ -1,22 +1,16 @@
<div class="workflow-specs" fxLayout="column" fxLayoutGap="10px">
<h1>Workflow Specifications</h1>
<div class="buttons" fxLayout="row" fxLayoutGap="10px">
<button id="add_spec" mat-flat-button color="primary" (click)="editWorkflowSpec()" fxLayoutAlign="stretch">
<mat-icon>library_add</mat-icon>
Add new workflow specification
</button>
<button id="add_category" mat-flat-button color="accent" (click)="editWorkflowSpecCategory()" fxLayoutAlign="stretch">
<mat-icon>post_add</mat-icon>
Add category
</button>
<div class="buttons" fxLayout="row" fxLayoutGap="20px">
<div>
<h1 style="margin-top: 16px">Workflow Specifications</h1>
</div>
<mat-form-field class="search-field">
<label><input matInput type="search" placeholder="Search Workflows" class="form-control" [formControl]="searchField"></label>
<label><input matInput type="search" placeholder="Search Workflows" fxLayoutAlign="start" style="margin-top: 0;" class="form-control" [formControl]="searchField"></label>
</mat-form-field>
</div>
<mat-drawer-container class="example-container" autosize>
<mat-drawer #drawer class="example-sidenav" mode="side" opened="true">
<ng-container *ngIf="masterStatusSpec">
<div class="category">
<div class="category-top">
<h4>Master Specification</h4>
<mat-list>
<mat-list-item class="workflow-spec" fxLayout="row">
@ -27,13 +21,20 @@
</ng-container>
<mat-divider></mat-divider>
<mat-divider></mat-divider>
<ng-container>
<div class="category">
<mat-accordion class="example-headers-align">
<div class="category" fxLayout="row">
<h4 style="margin-top: 5px">Library Specs</h4>
<button id="add_spec" title="Add new Library" mat-flat-button color="primary" (click)="editWorkflowSpec('library')" fxLayoutAlign="auto">
<mat-icon>library_add</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<mat-accordion class="example-headers-align">
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
<h4>Libraries</h4>
<h4>All Libraries</h4>
</mat-panel-title>
</mat-expansion-panel-header>
<mat-list>
@ -45,16 +46,21 @@
</mat-list>
</mat-expansion-panel>
</mat-accordion>
</div>
</ng-container>
<mat-divider></mat-divider>
<ng-container>
<div class="category">
<h4>Categories</h4>
<div class="category" fxLayout="row">
<h4 style="margin-top: 5px">Study Specs</h4>
<button id="add_category" title="Add new Category" mat-flat-button color="accent" (click)="editWorkflowSpecCategory()" fxLayoutAlign="stretch">
<mat-icon>post_add</mat-icon>
</button>
<button id="add_library" title="Add new Study Spec" mat-flat-button color="primary" (click)="editWorkflowSpec('study')" fxLayoutAlign="start">
<mat-icon>library_add</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
@ -162,7 +168,7 @@
(click)="validateWorkflowSpec(wfs)">
<mat-icon>verified_user</mat-icon>
</button>
<button mat-mini-fab title="Edit this workflow specification" color="primary" (click)="editWorkflowSpec(wfs)">
<button mat-mini-fab title="Edit this workflow specification" color="primary" (click)="editWorkflowSpec(this.selectedSpec.library ? 'library' : 'study', wfs)">
<mat-icon>edit</mat-icon>
</button>
<button mat-icon-button title="Delete this workflow specification" color="warn"

View File

@ -16,8 +16,31 @@
min-height: 600px;
}
.category-top {
padding: 0 1rem 1rem 0;
h4 {
margin: 1rem 1rem 0 0;
}
.category-actions {
opacity: 0;
&:hover {
opacity: 1;
}
}
&:hover {
.category-actions {
opacity: 1;
}
}
}
.category {
padding: 1rem 1rem 0 0;
padding: 2rem 1rem 1rem 0;
h4 {
margin: 1rem 1rem 0 0;

View File

@ -167,12 +167,12 @@ describe('WorkflowSpecListComponent', () => {
component.selectedSpec = mockWorkflowSpec1;
component.selectedSpec.parents = [];
component.selectedSpec.libraries = [];
component.editWorkflowSpec();
component.editWorkflowSpec('study');
expect(openDialogSpy).toHaveBeenCalled();
expect(_upsertWorkflowSpecificationSpy).not.toHaveBeenCalled();
mockSpecData = mockWorkflowSpec0 as WorkflowSpecDialogData;
component.editWorkflowSpec(mockWorkflowSpec0);
component.editWorkflowSpec('study', mockWorkflowSpec0);
expect(openDialogSpy).toHaveBeenCalled();
expect(_upsertWorkflowSpecificationSpy).toHaveBeenCalled();
});
@ -199,6 +199,7 @@ describe('WorkflowSpecListComponent', () => {
it('should add a workflow spec', () => {
const _loadWorkflowSpecsSpy = spyOn((component as any), '_loadWorkflowSpecs').and.stub();
const _loadWorkflowLibrariesSpy = spyOn((component as any), '_loadWorkflowLibraries').and.stub();
const _displayMessageSpy = spyOn((component as any), '_displayMessage').and.stub();
(component as any)._addWorkflowSpec(mockWorkflowSpec0);
const wfsReq = httpMock.expectOne(`apiRoot/workflow-specification`);
@ -206,6 +207,7 @@ describe('WorkflowSpecListComponent', () => {
wfsReq.flush(mockWorkflowSpec0);
expect(_loadWorkflowSpecsSpy).toHaveBeenCalled();
expect(_loadWorkflowLibrariesSpy).toHaveBeenCalled();
expect(_displayMessageSpy).toHaveBeenCalled();
});
@ -248,12 +250,14 @@ describe('WorkflowSpecListComponent', () => {
it('should delete a workflow spec', () => {
const loadWorkflowSpecsSpy = spyOn((component as any), '_loadWorkflowSpecs').and.stub();
const _loadWorkflowLibrariesSpy = spyOn((component as any), '_loadWorkflowLibraries').and.stub();
(component as any)._deleteWorkflowSpec(mockWorkflowSpec0);
const wfsReq = httpMock.expectOne(`apiRoot/workflow-specification/${mockWorkflowSpec0.id}`);
expect(wfsReq.request.method).toEqual('DELETE');
wfsReq.flush(null);
expect(loadWorkflowSpecsSpy).toHaveBeenCalled();
expect(_loadWorkflowLibrariesSpy).toHaveBeenCalled();
});
it('should show a metadata dialog when editing a workflow spec category', () => {

View File

@ -79,7 +79,6 @@ export class WorkflowSpecListComponent implements OnInit {
this.searchField = new FormControl();
this.searchField.valueChanges.subscribe(value => {
this._loadWorkflowSpecs(null, value);
console.log(value);
});
}
@ -112,6 +111,7 @@ export class WorkflowSpecListComponent implements OnInit {
}
canSaveWorkflowSpec(proposed: WorkflowSpecDialogData){
// Can possibly remove or bypass this method alltogether
if ((this.selectedSpec.parents.length > 0) && (!proposed.library)){
this.snackBar.open('This Workflow Specification is still being used as a Library. Please remove references first!', 'Ok', { duration: 5000 });
return false;
@ -123,7 +123,7 @@ export class WorkflowSpecListComponent implements OnInit {
return true;
}
editWorkflowSpec(selectedSpec?: WorkflowSpec) {
editWorkflowSpec(state: String, selectedSpec?: WorkflowSpec) {
const hasDisplayOrder = selectedSpec && isNumberDefined(selectedSpec.display_order);
const dialogData: WorkflowSpecDialogData = {
@ -133,7 +133,7 @@ export class WorkflowSpecListComponent implements OnInit {
category_id: selectedSpec ? selectedSpec.category_id : null,
display_order: hasDisplayOrder ? selectedSpec.display_order : 0,
standalone: selectedSpec ? selectedSpec.standalone : null,
library: selectedSpec ? selectedSpec.library : null,
library: selectedSpec ? selectedSpec.library : (state === 'library' ? true : null),
};
// Open new filename/workflow spec dialog
@ -144,10 +144,12 @@ export class WorkflowSpecListComponent implements OnInit {
});
dialogRef.afterClosed().subscribe((data: WorkflowSpecDialogData) => {
data.id = this.toLowercaseId(data.id);
if (data && data.id && data.display_name && data.description) {
if (this.canSaveWorkflowSpec(data)) {
this._upsertWorkflowSpecification(selectedSpec == null, data);
if (data.id) {
data.id = this.toLowercaseId(data.id);
if (data && data.id && data.display_name && data.description) {
if (this.canSaveWorkflowSpec(data)) {
this._upsertWorkflowSpecification(selectedSpec == null, data);
}
}
}
});
@ -359,6 +361,7 @@ export class WorkflowSpecListComponent implements OnInit {
private _addWorkflowSpec(newSpec: WorkflowSpec) {
this.api.addWorkflowSpecification(newSpec).subscribe(_ => {
this._loadWorkflowLibraries();
this._loadWorkflowSpecs(newSpec.id);
this._displayMessage('Saved new workflow spec.');
});
@ -367,6 +370,7 @@ export class WorkflowSpecListComponent implements OnInit {
private _deleteWorkflowSpec(workflowSpec: WorkflowSpec) {
this.api.deleteWorkflowSpecification(workflowSpec.id).subscribe(() => {
this._loadWorkflowSpecs();
this._loadWorkflowLibraries();
this._displayMessage(`Deleted workflow spec ${workflowSpec.id}.`);
});
}
@ -388,7 +392,7 @@ export class WorkflowSpecListComponent implements OnInit {
private _deleteWorkflowSpecCategory(workflowSpecCategory: WorkflowSpecCategory) {
this.api.deleteWorkflowSpecCategory(workflowSpecCategory.id).subscribe(() => {
this._loadWorkflowSpecCategories();
this._displayMessage(`Deleted workflow spec category ${workflowSpecCategory.id}.`);
this._displayMessage(`Deleted workflow spec category ${workflowSpecCategory.display_name}.`);
});
}
@ -396,6 +400,7 @@ export class WorkflowSpecListComponent implements OnInit {
this.snackBar.open(message, 'Ok', {duration: 3000});
}
/**
* Deprecated - backend now reorders
*