mirror of
https://github.com/sartography/cr-connect-bpmn.git
synced 2025-02-27 15:40:34 +00:00
Merge branch 'dev' into chore/bpmn-refactor-455
This commit is contained in:
commit
756995e5fe
14
package-lock.json
generated
14
package-lock.json
generated
@ -43,7 +43,7 @@
|
|||||||
"ngx-markdown": "^12.0.1",
|
"ngx-markdown": "^12.0.1",
|
||||||
"protractor": "^7.0.0",
|
"protractor": "^7.0.0",
|
||||||
"rxjs": "^6.5.3",
|
"rxjs": "^6.5.3",
|
||||||
"sartography-workflow-lib": "^0.0.563",
|
"sartography-workflow-lib": "0.0.569",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"zone.js": "^0.11.4"
|
"zone.js": "^0.11.4"
|
||||||
@ -17413,9 +17413,9 @@
|
|||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
"node_modules/sartography-workflow-lib": {
|
"node_modules/sartography-workflow-lib": {
|
||||||
"version": "0.0.563",
|
"version": "0.0.569",
|
||||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.563.tgz",
|
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.569.tgz",
|
||||||
"integrity": "sha512-aW6nYc/5w6TOrywuUDiCiw4wbQYxRH4fBrH1p0sDtzRggMpdfBdn7ccLd3aH+4GKZSnnxUNe3AdPBKbZ8draug==",
|
"integrity": "sha512-hcE8wvGpnAUr59rxbcwjB9Nq8tlsQnf5jFb9em2LiDJGi8OxPWQoJ1l+7YV0e8zS1yhU6Ym65DfUV6u367VkAw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.2.0"
|
"tslib": "^2.2.0"
|
||||||
}
|
}
|
||||||
@ -34401,9 +34401,9 @@
|
|||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
"sartography-workflow-lib": {
|
"sartography-workflow-lib": {
|
||||||
"version": "0.0.563",
|
"version": "0.0.569",
|
||||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.563.tgz",
|
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.569.tgz",
|
||||||
"integrity": "sha512-aW6nYc/5w6TOrywuUDiCiw4wbQYxRH4fBrH1p0sDtzRggMpdfBdn7ccLd3aH+4GKZSnnxUNe3AdPBKbZ8draug==",
|
"integrity": "sha512-hcE8wvGpnAUr59rxbcwjB9Nq8tlsQnf5jFb9em2LiDJGi8OxPWQoJ1l+7YV0e8zS1yhU6Ym65DfUV6u367VkAw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^2.2.0"
|
"tslib": "^2.2.0"
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"backend:start": "cd docker && docker-compose up -d --force-recreate && cd ..",
|
"backend:start": "cd docker && docker-compose up -d --force-recreate && cd ..",
|
||||||
"backend": "npm run backend:stop && npm run backend:build && npm run backend:start",
|
"backend": "npm run backend:stop && npm run backend:build && npm run backend:start",
|
||||||
"env": "chmod +x ./docker/substitute-env-variables.sh && ./docker/substitute-env-variables.sh src/index.html PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,DEPLOY_URL,PORT0,GOOGLE_ANALYTICS_KEY,SENTRY_KEY,TITLE",
|
"env": "chmod +x ./docker/substitute-env-variables.sh && ./docker/substitute-env-variables.sh src/index.html PRODUCTION,API_URL,IRB_URL,HOME_ROUTE,BASE_HREF,DEPLOY_URL,PORT0,GOOGLE_ANALYTICS_KEY,SENTRY_KEY,TITLE",
|
||||||
"ci": "npm run lint && npm run test:coverage && sonar-scanner && npm run env && npm run backend && npm run e2e"
|
"ci": "npm run lint && npm run test:coverage && sonar-scanner"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"ngx-markdown": "^12.0.1",
|
"ngx-markdown": "^12.0.1",
|
||||||
"protractor": "^7.0.0",
|
"protractor": "^7.0.0",
|
||||||
"rxjs": "^6.5.3",
|
"rxjs": "^6.5.3",
|
||||||
"sartography-workflow-lib": "^0.0.563",
|
"sartography-workflow-lib": "0.0.569",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"zone.js": "^0.11.4"
|
"zone.js": "^0.11.4"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div mat-dialog-title *ngIf="data && data.category">
|
<div mat-dialog-title *ngIf="data && data.category">
|
||||||
Delete category <strong>{{data.category.name}}</strong>?
|
Delete category <strong>{{data.category.id}}</strong>?
|
||||||
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
|
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div mat-dialog-title *ngIf="data && data.workflowSpec">
|
<div mat-dialog-title *ngIf="data && data.workflowSpec">
|
||||||
Delete workflow specification <strong>{{data.workflowSpec.name}}</strong>?
|
Delete workflow specification <strong>{{data.workflowSpec.id}}</strong>?
|
||||||
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
|
<button mat-icon-button mat-dialog-close=""><mat-icon>close</mat-icon></button>
|
||||||
</div>
|
</div>
|
||||||
<div mat-dialog-content>
|
<div mat-dialog-content>
|
||||||
|
@ -25,18 +25,7 @@ export class WorkflowSpecCategoryDialogComponent {
|
|||||||
placeholder: 'ID of workflow spec category',
|
placeholder: 'ID of workflow spec category',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
hideExpression: true,
|
||||||
{
|
|
||||||
key: 'name',
|
|
||||||
type: 'input',
|
|
||||||
defaultValue: this.data.name,
|
|
||||||
templateOptions: {
|
|
||||||
label: 'Name',
|
|
||||||
placeholder: 'Name of workflow spec category',
|
|
||||||
description: 'Enter a name, in lowercase letters, separated by underscores, that is easy for you to remember.' +
|
|
||||||
'It will be converted to all_lowercase_with_underscores when you save.',
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'display_name',
|
key: 'display_name',
|
||||||
@ -50,6 +39,16 @@ export class WorkflowSpecCategoryDialogComponent {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'admin',
|
||||||
|
type: 'checkbox',
|
||||||
|
defaultValue: this.data.admin ? this.data.admin : false,
|
||||||
|
templateOptions: {
|
||||||
|
label: 'Admin Category',
|
||||||
|
description: 'Should this category only be shown to Admins?',
|
||||||
|
indeterminate: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -63,6 +62,7 @@ export class WorkflowSpecCategoryDialogComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
console.log('data is ', this.model);
|
||||||
this.model.name = toSnakeCase(this.model.name);
|
this.model.name = toSnakeCase(this.model.name);
|
||||||
this.dialogRef.close(this.model);
|
this.dialogRef.close(this.model);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,13 @@ import {Router} from '@angular/router';
|
|||||||
import {RouterTestingModule} from '@angular/router/testing';
|
import {RouterTestingModule} from '@angular/router/testing';
|
||||||
import {FormlyModule} from '@ngx-formly/core';
|
import {FormlyModule} from '@ngx-formly/core';
|
||||||
import {FormlyMaterialModule} from '@ngx-formly/material';
|
import {FormlyMaterialModule} from '@ngx-formly/material';
|
||||||
import {ApiService, MockEnvironment, mockWorkflowSpec0, mockWorkflowSpecCategories} from 'sartography-workflow-lib';
|
import {
|
||||||
|
ApiService,
|
||||||
|
MockEnvironment,
|
||||||
|
mockWorkflowSpec0,
|
||||||
|
mockWorkflowSpecCategories,
|
||||||
|
mockWorkflowSpecs
|
||||||
|
} from 'sartography-workflow-lib';
|
||||||
import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data';
|
import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data';
|
||||||
|
|
||||||
import {WorkflowSpecDialogComponent} from './workflow-spec-dialog.component';
|
import {WorkflowSpecDialogComponent} from './workflow-spec-dialog.component';
|
||||||
@ -74,6 +80,12 @@ describe('WorkflowSpecDialogComponent', () => {
|
|||||||
expect(catReq.request.method).toEqual('GET');
|
expect(catReq.request.method).toEqual('GET');
|
||||||
catReq.flush(mockWorkflowSpecCategories);
|
catReq.flush(mockWorkflowSpecCategories);
|
||||||
expect(component.categories.length).toBeGreaterThan(0);
|
expect(component.categories.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
const specReq = httpMock.expectOne('apiRoot/workflow-specification');
|
||||||
|
expect(specReq.request.method).toEqual('GET');
|
||||||
|
specReq.flush(mockWorkflowSpecs);
|
||||||
|
expect(component.specs.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
@ -1,22 +1,26 @@
|
|||||||
import {Component, Inject} from '@angular/core';
|
import {Component, Inject} from '@angular/core';
|
||||||
import {FormGroup} from '@angular/forms';
|
import {FormControl, FormGroup, ValidationErrors} from '@angular/forms';
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||||
import {FormlyFieldConfig, FormlyFormOptions, FormlyTemplateOptions} from '@ngx-formly/core';
|
import {FormlyFieldConfig, FormlyFormOptions, FormlyTemplateOptions} from '@ngx-formly/core';
|
||||||
import {ApiService, toSnakeCase} from 'sartography-workflow-lib';
|
import {ApiService, toSnakeCase} from 'sartography-workflow-lib';
|
||||||
import {v4 as uuidv4} from 'uuid';
|
import {v4 as uuidv4} from 'uuid';
|
||||||
import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data';
|
import {WorkflowSpecDialogData} from '../../_interfaces/dialog-data';
|
||||||
|
import {of} from "rxjs";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-workflow-spec-dialog',
|
selector: 'app-workflow-spec-dialog',
|
||||||
templateUrl: './workflow-spec-dialog.component.html',
|
templateUrl: './workflow-spec-dialog.component.html',
|
||||||
styleUrls: ['./workflow-spec-dialog.component.scss']
|
styleUrls: ['./workflow-spec-dialog.component.scss']
|
||||||
})
|
})
|
||||||
|
|
||||||
export class WorkflowSpecDialogComponent {
|
export class WorkflowSpecDialogComponent {
|
||||||
form: FormGroup = new FormGroup({});
|
form: FormGroup = new FormGroup({});
|
||||||
model: any = {};
|
model: any = {};
|
||||||
options: FormlyFormOptions = {};
|
options: FormlyFormOptions = {};
|
||||||
fields: FormlyFieldConfig[] = [];
|
fields: FormlyFieldConfig[] = [];
|
||||||
categories: any;
|
categories: any;
|
||||||
|
specs: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
@ -29,29 +33,29 @@ export class WorkflowSpecDialogComponent {
|
|||||||
label: c.display_name,
|
label: c.display_name,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this.api.getWorkflowSpecList().subscribe(wfs => {
|
||||||
|
this.specs = wfs.map(w => w.id);
|
||||||
|
|
||||||
this.fields = [
|
this.fields = [
|
||||||
{
|
{
|
||||||
key: 'id',
|
key: 'id',
|
||||||
type: 'input',
|
type: 'input',
|
||||||
defaultValue: this.data.id || uuidv4(),
|
defaultValue: this.data.id,
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
label: 'ID',
|
label: 'id',
|
||||||
placeholder: 'UUID of workflow specification',
|
|
||||||
description: 'This is an autogenerated unique ID and is not editable.',
|
|
||||||
required: true,
|
|
||||||
disabled: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'name',
|
|
||||||
type: 'input',
|
|
||||||
defaultValue: this.data.name,
|
|
||||||
templateOptions: {
|
|
||||||
label: 'Name',
|
|
||||||
placeholder: 'Name of workflow specification',
|
placeholder: 'Name of workflow specification',
|
||||||
description: 'Enter a name, in lowercase letters, separated by underscores, that is easy for you to remember.' +
|
description: 'Enter a name to identify this spec. It cannot be changed later.' +
|
||||||
'It will be converted to all_lowercase_with_underscores when you save.',
|
'It will be converted to all_lowercase_with_underscores when you save.',
|
||||||
required: true,
|
required: true,
|
||||||
|
disabled: this.data.id !== '',
|
||||||
|
},
|
||||||
|
asyncValidators: {
|
||||||
|
uniqueID: {
|
||||||
|
expression: (control: FormControl) => {
|
||||||
|
return of(this.specs.indexOf(control.value) === -1);
|
||||||
|
},
|
||||||
|
message: 'This ID name is already taken.',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -101,6 +105,7 @@ export class WorkflowSpecDialogComponent {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onNoClick() {
|
onNoClick() {
|
||||||
|
@ -20,7 +20,6 @@ export interface OpenFileDialogData {
|
|||||||
|
|
||||||
export interface WorkflowSpecDialogData {
|
export interface WorkflowSpecDialogData {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
|
||||||
display_name: string;
|
display_name: string;
|
||||||
description: string;
|
description: string;
|
||||||
category_id: number;
|
category_id: number;
|
||||||
@ -31,9 +30,9 @@ export interface WorkflowSpecDialogData {
|
|||||||
|
|
||||||
export interface WorkflowSpecCategoryDialogData {
|
export interface WorkflowSpecCategoryDialogData {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
|
||||||
display_name: string;
|
display_name: string;
|
||||||
display_order?: number;
|
display_order?: number;
|
||||||
|
admin: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DeleteFileDialogData {
|
export interface DeleteFileDialogData {
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Back
|
Back
|
||||||
</a>
|
</a>
|
||||||
{{workflowSpec.display_name}}
|
{{workflowSpec.display_name}}
|
||||||
({{workflowSpec.name}})
|
({{workflowSpec.id}})
|
||||||
</mat-toolbar-row>
|
</mat-toolbar-row>
|
||||||
<mat-toolbar-row>
|
<mat-toolbar-row>
|
||||||
<button #newMenuTrigger="matMenuTrigger" mat-button [matMenuTriggerFor]="newMenu" title="Open diagram">
|
<button #newMenuTrigger="matMenuTrigger" mat-button [matMenuTriggerFor]="newMenu" title="Open diagram">
|
||||||
|
@ -178,11 +178,11 @@ export class ModelerComponent implements AfterViewInit {
|
|||||||
});
|
});
|
||||||
dialogRef.afterClosed().subscribe(dialogResult => {
|
dialogRef.afterClosed().subscribe(dialogResult => {
|
||||||
if (dialogResult) {
|
if (dialogResult) {
|
||||||
this.router.navigate(['/home', this.workflowSpec.name]);
|
this.router.navigate(['/home', this.workflowSpec.id]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.router.navigate(['/home', this.workflowSpec.name]);
|
this.router.navigate(['/home', this.workflowSpec.id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -404,7 +404,7 @@ export class ModelerComponent implements AfterViewInit {
|
|||||||
// Add new file meta
|
// Add new file meta
|
||||||
this.api.addFile({workflow_spec_id: this.workflowSpec.id}, this.diagramFileMeta, this.diagramFile).subscribe(fileMeta => {
|
this.api.addFile({workflow_spec_id: this.workflowSpec.id}, this.diagramFileMeta, this.diagramFile).subscribe(fileMeta => {
|
||||||
this.router.navigate(['/modeler', this.workflowSpec.id, fileMeta.id]);
|
this.router.navigate(['/modeler', this.workflowSpec.id, fileMeta.id]);
|
||||||
this.snackBar.open(`Saved new file ${fileMeta.name} to workflow spec ${this.workflowSpec.name}.`, 'Ok', {duration: 5000});
|
this.snackBar.open(`Saved new file ${fileMeta.name} to workflow spec ${this.workflowSpec.display_name}.`, 'Ok', {duration: 5000});
|
||||||
}, () => {
|
}, () => {
|
||||||
// if this fails, we make sure that the file is treated as still new,
|
// if this fails, we make sure that the file is treated as still new,
|
||||||
// and we make the user re-enter the file details as they weren't actually saved.
|
// and we make the user re-enter the file details as they weren't actually saved.
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<dl gdAreas="field value" gdColumns="10ch auto">
|
<dl gdAreas="field value" gdColumns="10ch auto">
|
||||||
<dt>ID</dt><dd>{{workflowSpec.id}}</dd>
|
<dt>Name</dt><dd>{{workflowSpec.id}}</dd>
|
||||||
<dt>Name</dt><dd>{{workflowSpec.name}}</dd>
|
|
||||||
<dt>Description</dt><dd>{{workflowSpec.description}}</dd>
|
<dt>Description</dt><dd>{{workflowSpec.description}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<h4>Workflow Spec Files</h4>
|
<h4>Workflow Spec Files</h4>
|
||||||
|
@ -72,11 +72,13 @@
|
|||||||
<ng-container *ngIf="!(cat.id === null && cat.workflow_specs.length === 0)">
|
<ng-container *ngIf="!(cat.id === null && cat.workflow_specs.length === 0)">
|
||||||
<mat-expansion-panel hideToggle (opened)="selectCat(cat)" [expanded]="isSelected(cat)">
|
<mat-expansion-panel hideToggle (opened)="selectCat(cat)" [expanded]="isSelected(cat)">
|
||||||
<mat-expansion-panel-header>
|
<mat-expansion-panel-header>
|
||||||
<mat-panel-title>
|
|
||||||
{{cat.display_name}}
|
|
||||||
</mat-panel-title>
|
|
||||||
<mat-panel-description>
|
<mat-panel-description>
|
||||||
({{cat.name}})
|
<div *ngIf="cat.admin" style="color: darkorange">
|
||||||
|
{{cat.display_name}}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!cat.admin">
|
||||||
|
{{cat.display_name}}
|
||||||
|
</div>
|
||||||
</mat-panel-description>
|
</mat-panel-description>
|
||||||
<button mat-mini-fab color="primary" style="box-shadow: none">
|
<button mat-mini-fab color="primary" style="box-shadow: none">
|
||||||
{{cat.workflow_specs.length}}
|
{{cat.workflow_specs.length}}
|
||||||
|
@ -53,7 +53,6 @@ export class MdDialogMock {
|
|||||||
|
|
||||||
const librarySpec0: WorkflowSpec = {
|
const librarySpec0: WorkflowSpec = {
|
||||||
id: 'one_thing',
|
id: 'one_thing',
|
||||||
name: 'one_thing',
|
|
||||||
display_name: 'One thing',
|
display_name: 'One thing',
|
||||||
description: 'Do just one thing',
|
description: 'Do just one thing',
|
||||||
category_id: 2,
|
category_id: 2,
|
||||||
@ -153,7 +152,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
it('should show a metadata dialog when editing a workflow spec', () => {
|
it('should show a metadata dialog when editing a workflow spec', () => {
|
||||||
let mockSpecData: WorkflowSpecDialogData = {
|
let mockSpecData: WorkflowSpecDialogData = {
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
|
||||||
display_name: '',
|
display_name: '',
|
||||||
description: '',
|
description: '',
|
||||||
category_id: 0,
|
category_id: 0,
|
||||||
@ -261,8 +259,8 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
it('should show a metadata dialog when editing a workflow spec category', () => {
|
it('should show a metadata dialog when editing a workflow spec category', () => {
|
||||||
let mockCatData: WorkflowSpecCategoryDialogData = {
|
let mockCatData: WorkflowSpecCategoryDialogData = {
|
||||||
id: null,
|
id: null,
|
||||||
name: '',
|
|
||||||
display_name: '',
|
display_name: '',
|
||||||
|
admin: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _upsertWorkflowSpecCategorySpy = spyOn((component as any), '_upsertWorkflowSpecCategory')
|
const _upsertWorkflowSpecCategorySpy = spyOn((component as any), '_upsertWorkflowSpecCategory')
|
||||||
@ -285,6 +283,7 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
const _updateWorkflowSpecCategorySpy = spyOn((component as any), '_updateWorkflowSpecCategory').and.stub();
|
const _updateWorkflowSpecCategorySpy = spyOn((component as any), '_updateWorkflowSpecCategory').and.stub();
|
||||||
|
|
||||||
component.selectedCat = undefined;
|
component.selectedCat = undefined;
|
||||||
|
mockWorkflowSpecCategory1.id = null;
|
||||||
(component as any)._upsertWorkflowSpecCategory(mockWorkflowSpecCategory1 as WorkflowSpecCategoryDialogData);
|
(component as any)._upsertWorkflowSpecCategory(mockWorkflowSpecCategory1 as WorkflowSpecCategoryDialogData);
|
||||||
expect(_addWorkflowSpecCategorySpy).toHaveBeenCalled();
|
expect(_addWorkflowSpecCategorySpy).toHaveBeenCalled();
|
||||||
expect(_updateWorkflowSpecCategorySpy).not.toHaveBeenCalled();
|
expect(_updateWorkflowSpecCategorySpy).not.toHaveBeenCalled();
|
||||||
@ -500,7 +499,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
it('should load master workflow spec', () => {
|
it('should load master workflow spec', () => {
|
||||||
const mockMasterSpec: WorkflowSpec = {
|
const mockMasterSpec: WorkflowSpec = {
|
||||||
id: 'master_status_spec',
|
id: 'master_status_spec',
|
||||||
name: 'master_status_spec',
|
|
||||||
display_name: 'master_status_spec',
|
display_name: 'master_status_spec',
|
||||||
description: 'master_status_spec',
|
description: 'master_status_spec',
|
||||||
is_master_spec: true,
|
is_master_spec: true,
|
||||||
@ -536,7 +534,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
it('should disallow deselecting library if being used as library', () => {
|
it('should disallow deselecting library if being used as library', () => {
|
||||||
let mockSpecData: WorkflowSpecDialogData = {
|
let mockSpecData: WorkflowSpecDialogData = {
|
||||||
id: '25',
|
id: '25',
|
||||||
name: 'name1',
|
|
||||||
display_name: 'displayname',
|
display_name: 'displayname',
|
||||||
description: 'descr',
|
description: 'descr',
|
||||||
category_id: 0,
|
category_id: 0,
|
||||||
@ -555,7 +552,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
localSelectedSpec.parents = [
|
localSelectedSpec.parents = [
|
||||||
{ id: 1234,
|
{ id: 1234,
|
||||||
display_name: 'test parent',
|
display_name: 'test parent',
|
||||||
name: 'parent1'
|
|
||||||
}]
|
}]
|
||||||
component.selectedSpec = localSelectedSpec;
|
component.selectedSpec = localSelectedSpec;
|
||||||
component.editWorkflowSpec(localSelectedSpec);
|
component.editWorkflowSpec(localSelectedSpec);
|
||||||
@ -570,7 +566,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
// that fails prior to saving if any of these are blank
|
// that fails prior to saving if any of these are blank
|
||||||
let mockSpecData: WorkflowSpecDialogData = {
|
let mockSpecData: WorkflowSpecDialogData = {
|
||||||
id: '25',
|
id: '25',
|
||||||
name: 'name1',
|
|
||||||
display_name: 'displayname',
|
display_name: 'displayname',
|
||||||
description: 'descr',
|
description: 'descr',
|
||||||
category_id: 0,
|
category_id: 0,
|
||||||
@ -589,7 +584,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
localSelectedSpec.parents = [
|
localSelectedSpec.parents = [
|
||||||
{ id: 1234,
|
{ id: 1234,
|
||||||
display_name: 'test parent',
|
display_name: 'test parent',
|
||||||
name: 'parent1'
|
|
||||||
}]
|
}]
|
||||||
component.selectedSpec = localSelectedSpec;
|
component.selectedSpec = localSelectedSpec;
|
||||||
component.editWorkflowSpec(localSelectedSpec);
|
component.editWorkflowSpec(localSelectedSpec);
|
||||||
@ -605,7 +599,6 @@ describe('WorkflowSpecListComponent', () => {
|
|||||||
badWorkflowSpec.parents=[
|
badWorkflowSpec.parents=[
|
||||||
{ id: 1234,
|
{ id: 1234,
|
||||||
display_name: 'test parent',
|
display_name: 'test parent',
|
||||||
name: 'parent1'
|
|
||||||
}]
|
}]
|
||||||
badWorkflowSpec.library=true;
|
badWorkflowSpec.library=true;
|
||||||
const mockConfirmDeleteData: DeleteWorkflowSpecDialogData = {
|
const mockConfirmDeleteData: DeleteWorkflowSpecDialogData = {
|
||||||
|
@ -32,11 +32,11 @@ import { SettingsService } from '../settings.service';
|
|||||||
|
|
||||||
|
|
||||||
export interface WorkflowSpecCategoryGroup {
|
export interface WorkflowSpecCategoryGroup {
|
||||||
id: number;
|
id?: number;
|
||||||
name: string;
|
|
||||||
display_name: string;
|
display_name: string;
|
||||||
workflow_specs?: WorkflowSpec[];
|
workflow_specs?: WorkflowSpec[];
|
||||||
display_order: number;
|
display_order: number;
|
||||||
|
admin: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -93,17 +93,17 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
selectCat(selectedCat?: WorkflowSpecCategory) {
|
selectCat(selectedCat?: WorkflowSpecCategoryGroup) {
|
||||||
this.selectedCat = selectedCat;
|
this.selectedCat = selectedCat;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSelected(cat: WorkflowSpecCategory) {
|
isSelected(cat: WorkflowSpecCategoryGroup) {
|
||||||
return this.selectedCat && this.selectedCat.id === cat.id;
|
return this.selectedCat && this.selectedCat.id === cat.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectSpec(selectedSpec?: WorkflowSpec) {
|
selectSpec(selectedSpec?: WorkflowSpec) {
|
||||||
this.selectedSpec = selectedSpec;
|
this.selectedSpec = selectedSpec;
|
||||||
this.location.replaceState(environment.homeRoute + '/' + selectedSpec.name);
|
this.location.replaceState(environment.homeRoute + '/' + selectedSpec.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryExpanded(cat: WorkflowSpecCategory) {
|
categoryExpanded(cat: WorkflowSpecCategory) {
|
||||||
@ -128,7 +128,6 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
const hasDisplayOrder = selectedSpec && isNumberDefined(selectedSpec.display_order);
|
const hasDisplayOrder = selectedSpec && isNumberDefined(selectedSpec.display_order);
|
||||||
const dialogData: WorkflowSpecDialogData = {
|
const dialogData: WorkflowSpecDialogData = {
|
||||||
id: selectedSpec ? selectedSpec.id : '',
|
id: selectedSpec ? selectedSpec.id : '',
|
||||||
name: selectedSpec ? selectedSpec.name || selectedSpec.id : '',
|
|
||||||
display_name: selectedSpec ? selectedSpec.display_name : '',
|
display_name: selectedSpec ? selectedSpec.display_name : '',
|
||||||
description: selectedSpec ? selectedSpec.description : '',
|
description: selectedSpec ? selectedSpec.description : '',
|
||||||
category_id: selectedSpec ? selectedSpec.category_id : null,
|
category_id: selectedSpec ? selectedSpec.category_id : null,
|
||||||
@ -145,7 +144,8 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((data: WorkflowSpecDialogData) => {
|
dialogRef.afterClosed().subscribe((data: WorkflowSpecDialogData) => {
|
||||||
if (data && data.id && data.name && data.display_name && data.description) {
|
data.id = this.toLowercaseId(data.id);
|
||||||
|
if (data && data.id && data.display_name && data.description) {
|
||||||
if (this.canSaveWorkflowSpec(data)) {
|
if (this.canSaveWorkflowSpec(data)) {
|
||||||
this._upsertWorkflowSpecification(selectedSpec == null, data);
|
this._upsertWorkflowSpecification(selectedSpec == null, data);
|
||||||
}
|
}
|
||||||
@ -153,6 +153,11 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to convert strings to valid ID's.
|
||||||
|
toLowercaseId(id: String) {
|
||||||
|
return id.replace(/ /g,"_").toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
editWorkflowSpecCategory(selectedCat?: WorkflowSpecCategoryGroup) {
|
editWorkflowSpecCategory(selectedCat?: WorkflowSpecCategoryGroup) {
|
||||||
this.selectedCat = selectedCat;
|
this.selectedCat = selectedCat;
|
||||||
|
|
||||||
@ -162,20 +167,19 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
width: '50vw',
|
width: '50vw',
|
||||||
data: {
|
data: {
|
||||||
id: this.selectedCat ? this.selectedCat.id : null,
|
id: this.selectedCat ? this.selectedCat.id : null,
|
||||||
name: this.selectedCat ? this.selectedCat.name || this.selectedCat.id : '',
|
|
||||||
display_name: this.selectedCat ? this.selectedCat.display_name : '',
|
display_name: this.selectedCat ? this.selectedCat.display_name : '',
|
||||||
display_order: this.selectedCat ? this.selectedCat.display_order : null,
|
display_order: this.selectedCat ? this.selectedCat.display_order : null,
|
||||||
|
admin: this.selectedCat ? this.selectedCat.admin : null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
dialogRef.afterClosed().subscribe((data: WorkflowSpecCategoryDialogData) => {
|
dialogRef.afterClosed().subscribe((data: WorkflowSpecCategoryDialogData) => {
|
||||||
if (data && isNumberDefined(data.id) && data.name && data.display_name) {
|
if (data && data.display_name) {
|
||||||
this._upsertWorkflowSpecCategory(data);
|
this._upsertWorkflowSpecCategory(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeleteWorkflowSpecCategory(cat: WorkflowSpecCategory) {
|
confirmDeleteWorkflowSpecCategory(cat: WorkflowSpecCategoryGroup) {
|
||||||
const dialogRef = this.dialog.open(DeleteWorkflowSpecCategoryDialogComponent, {
|
const dialogRef = this.dialog.open(DeleteWorkflowSpecCategoryDialogComponent, {
|
||||||
data: {
|
data: {
|
||||||
confirm: false,
|
confirm: false,
|
||||||
@ -220,17 +224,24 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
|
|
||||||
editCategoryDisplayOrder(catId: number, direction: string) {
|
editCategoryDisplayOrder(catId: number, direction: string) {
|
||||||
this.api.reorderWorkflowCategory(catId, direction).subscribe(cat_change => {
|
this.api.reorderWorkflowCategory(catId, direction).subscribe(cat_change => {
|
||||||
if(cat_change) {
|
|
||||||
this.workflowSpecsByCategory = this.workflowSpecsByCategory.map(cat => {
|
this.workflowSpecsByCategory = this.workflowSpecsByCategory.map(cat => {
|
||||||
let new_cat = cat_change.find(i2 => i2.id === cat.id);
|
let new_cat = this.ensure(cat_change.find(i2 => i2.id === cat.id));
|
||||||
cat.display_order = new_cat.display_order;
|
cat.display_order = new_cat.display_order;
|
||||||
return cat;
|
return cat;
|
||||||
});
|
});
|
||||||
this.workflowSpecsByCategory.sort((x,y) => x.display_order - y.display_order);
|
this.workflowSpecsByCategory.sort((x,y) => x.display_order - y.display_order);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure that in array.find, we find what we are expecting. (Ensures TS type safety)
|
||||||
|
ensure<T>(argument: T | undefined | null, message: string = 'Spec not found!'): T {
|
||||||
|
if (argument === undefined || argument === null) {
|
||||||
|
throw new TypeError(message);
|
||||||
|
}
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
editSpecDisplayOrder(cat: WorkflowSpecCategoryGroup, specId: string, direction: string) {
|
editSpecDisplayOrder(cat: WorkflowSpecCategoryGroup, specId: string, direction: string) {
|
||||||
this.api.reorderWorkflowSpecification(specId, direction).subscribe(wfs => {
|
this.api.reorderWorkflowSpecification(specId, direction).subscribe(wfs => {
|
||||||
cat.workflow_specs= wfs;
|
cat.workflow_specs= wfs;
|
||||||
@ -240,6 +251,8 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
private _loadWorkflowSpecCategories(selectedSpecName: string = null) {
|
private _loadWorkflowSpecCategories(selectedSpecName: string = null) {
|
||||||
this.api.getWorkflowSpecCategoryList().subscribe(cats => {
|
this.api.getWorkflowSpecCategoryList().subscribe(cats => {
|
||||||
this.categories = cats;
|
this.categories = cats;
|
||||||
|
// Clear out this object before re-filling it
|
||||||
|
this.workflowSpecsByCategory = [];
|
||||||
|
|
||||||
this.categories.forEach((cat, i) => {
|
this.categories.forEach((cat, i) => {
|
||||||
this.workflowSpecsByCategory.push(cat);
|
this.workflowSpecsByCategory.push(cat);
|
||||||
@ -279,11 +292,11 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
|
|
||||||
// Set the selected workflow to something sensible.
|
// Set the selected workflow to something sensible.
|
||||||
if (!selectedSpecName && this.selectedSpec) {
|
if (!selectedSpecName && this.selectedSpec) {
|
||||||
selectedSpecName = this.selectedSpec.name;
|
selectedSpecName = this.selectedSpec.id;
|
||||||
}
|
}
|
||||||
if (selectedSpecName) {
|
if (selectedSpecName) {
|
||||||
this.workflowSpecs.forEach(ws => {
|
this.workflowSpecs.forEach(ws => {
|
||||||
if (selectedSpecName && selectedSpecName === ws.name) {
|
if (selectedSpecName && selectedSpecName === ws.id) {
|
||||||
this.selectedSpec = ws;
|
this.selectedSpec = ws;
|
||||||
this.selectedCat = this.selectedSpec.category;
|
this.selectedCat = this.selectedSpec.category;
|
||||||
}
|
}
|
||||||
@ -295,11 +308,10 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _upsertWorkflowSpecification(isNew: boolean, data: WorkflowSpecDialogData) {
|
private _upsertWorkflowSpecification(isNew: boolean, data: WorkflowSpecDialogData) {
|
||||||
if (data.id && data.name && data.display_name && data.description) {
|
if (data.id && data.display_name && data.description) {
|
||||||
|
|
||||||
const newSpec: WorkflowSpec = {
|
const newSpec: WorkflowSpec = {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
name: data.name,
|
|
||||||
display_name: data.display_name,
|
display_name: data.display_name,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
category_id: data.category_id,
|
category_id: data.category_id,
|
||||||
@ -317,21 +329,21 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _upsertWorkflowSpecCategory(data: WorkflowSpecCategoryDialogData) {
|
private _upsertWorkflowSpecCategory(data: WorkflowSpecCategoryDialogData) {
|
||||||
if (isNumberDefined(data.id) && data.name && data.display_name) {
|
if (data.display_name) {
|
||||||
|
if (isNumberDefined(data.id)) {
|
||||||
// Save old workflow spec id, in case it's changed
|
|
||||||
const catId = this.selectedCat ? this.selectedCat.id : undefined;
|
|
||||||
|
|
||||||
const newCat: WorkflowSpecCategory = {
|
const newCat: WorkflowSpecCategory = {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
name: data.name,
|
|
||||||
display_name: data.display_name,
|
display_name: data.display_name,
|
||||||
display_order: data.display_order,
|
display_order: data.display_order,
|
||||||
|
admin: data.admin,
|
||||||
};
|
};
|
||||||
|
this._updateWorkflowSpecCategory(data.id, newCat);
|
||||||
if (isNumberDefined(catId)) {
|
|
||||||
this._updateWorkflowSpecCategory(catId, newCat);
|
|
||||||
} else {
|
} else {
|
||||||
|
const newCat: WorkflowSpecCategory = {
|
||||||
|
display_name: data.display_name,
|
||||||
|
display_order: data.display_order,
|
||||||
|
admin: data.admin,
|
||||||
|
};
|
||||||
this._addWorkflowSpecCategory(newCat);
|
this._addWorkflowSpecCategory(newCat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -347,7 +359,7 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
|
|
||||||
private _addWorkflowSpec(newSpec: WorkflowSpec) {
|
private _addWorkflowSpec(newSpec: WorkflowSpec) {
|
||||||
this.api.addWorkflowSpecification(newSpec).subscribe(_ => {
|
this.api.addWorkflowSpecification(newSpec).subscribe(_ => {
|
||||||
this._loadWorkflowSpecs(newSpec.name);
|
this._loadWorkflowSpecs(newSpec.id);
|
||||||
this._displayMessage('Saved new workflow spec.');
|
this._displayMessage('Saved new workflow spec.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -355,7 +367,7 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
private _deleteWorkflowSpec(workflowSpec: WorkflowSpec) {
|
private _deleteWorkflowSpec(workflowSpec: WorkflowSpec) {
|
||||||
this.api.deleteWorkflowSpecification(workflowSpec.id).subscribe(() => {
|
this.api.deleteWorkflowSpecification(workflowSpec.id).subscribe(() => {
|
||||||
this._loadWorkflowSpecs();
|
this._loadWorkflowSpecs();
|
||||||
this._displayMessage(`Deleted workflow spec ${workflowSpec.name}.`);
|
this._displayMessage(`Deleted workflow spec ${workflowSpec.id}.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,7 +388,7 @@ export class WorkflowSpecListComponent implements OnInit {
|
|||||||
private _deleteWorkflowSpecCategory(workflowSpecCategory: WorkflowSpecCategory) {
|
private _deleteWorkflowSpecCategory(workflowSpecCategory: WorkflowSpecCategory) {
|
||||||
this.api.deleteWorkflowSpecCategory(workflowSpecCategory.id).subscribe(() => {
|
this.api.deleteWorkflowSpecCategory(workflowSpecCategory.id).subscribe(() => {
|
||||||
this._loadWorkflowSpecCategories();
|
this._loadWorkflowSpecCategories();
|
||||||
this._displayMessage(`Deleted workflow spec category ${workflowSpecCategory.name}.`);
|
this._displayMessage(`Deleted workflow spec category ${workflowSpecCategory.id}.`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user