Edits existing non-BPMN workflow spec file details
This commit is contained in:
parent
d0f4916667
commit
d4d43537d6
|
@ -1,5 +1,8 @@
|
||||||
import {Component, Inject} from '@angular/core';
|
import {Component, Inject} from '@angular/core';
|
||||||
|
import {FormGroup} from '@angular/forms';
|
||||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||||
|
import {FormlyFieldConfig, FormlyFormOptions} from '@ngx-formly/core';
|
||||||
|
import {FileType} from 'sartography-workflow-lib';
|
||||||
import {FileMetaDialogData} from '../../_interfaces/dialog-data';
|
import {FileMetaDialogData} from '../../_interfaces/dialog-data';
|
||||||
import {cleanUpFilename} from '../../_util/string-clean';
|
import {cleanUpFilename} from '../../_util/string-clean';
|
||||||
|
|
||||||
|
@ -9,11 +12,56 @@ import {cleanUpFilename} from '../../_util/string-clean';
|
||||||
styleUrls: ['./file-meta-dialog.component.scss']
|
styleUrls: ['./file-meta-dialog.component.scss']
|
||||||
})
|
})
|
||||||
export class FileMetaDialogComponent {
|
export class FileMetaDialogComponent {
|
||||||
|
form: FormGroup = new FormGroup({});
|
||||||
|
model: any = {};
|
||||||
|
options: FormlyFormOptions = {};
|
||||||
|
fields: FormlyFieldConfig[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public dialogRef: MatDialogRef<FileMetaDialogComponent>,
|
public dialogRef: MatDialogRef<FileMetaDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: FileMetaDialogData
|
@Inject(MAT_DIALOG_DATA) public data: FileMetaDialogData
|
||||||
) {
|
) {
|
||||||
|
const fileTypeOptions = Object.entries(FileType).map(ft => {
|
||||||
|
return {
|
||||||
|
label: ft[0],
|
||||||
|
value: ft[1]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.fields = [
|
||||||
|
{
|
||||||
|
key: 'fileName',
|
||||||
|
type: 'input',
|
||||||
|
defaultValue: this.data.fileName,
|
||||||
|
templateOptions: {
|
||||||
|
label: 'File Name',
|
||||||
|
placeholder: 'Name of workflow specification',
|
||||||
|
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: 'fileType',
|
||||||
|
type: 'select',
|
||||||
|
defaultValue: this.data.fileType,
|
||||||
|
templateOptions: {
|
||||||
|
label: 'File Type',
|
||||||
|
placeholder: 'Extension of file',
|
||||||
|
required: true,
|
||||||
|
options: fileTypeOptions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'file',
|
||||||
|
type: 'file',
|
||||||
|
defaultValue: this.data.file,
|
||||||
|
templateOptions: {
|
||||||
|
label: 'File',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
onNoClick() {
|
onNoClick() {
|
||||||
|
|
|
@ -60,6 +60,12 @@ describe('OpenFileDialogComponent', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
httpMock.verify();
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
|
||||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
|
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
|
||||||
|
@ -7,11 +8,12 @@ import {MatInputModule} from '@angular/material/input';
|
||||||
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
|
import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
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 {mockWorkflowSpecCategory0} from 'sartography-workflow-lib';
|
import {ApiService, MockEnvironment, mockWorkflowSpecCategory0} from 'sartography-workflow-lib';
|
||||||
import {WorkflowSpecCategoryDialogData} from '../../_interfaces/dialog-data';
|
import {WorkflowSpecCategoryDialogData} from '../../_interfaces/dialog-data';
|
||||||
import {WorkflowSpecCategoryDialogComponent} from './workflow-spec-category-dialog.component';
|
import {WorkflowSpecCategoryDialogComponent} from './workflow-spec-category-dialog.component';
|
||||||
|
|
||||||
describe('WorkflowSpecDialogComponent', () => {
|
describe('WorkflowSpecDialogComponent', () => {
|
||||||
|
let httpMock: HttpTestingController;
|
||||||
let component: WorkflowSpecCategoryDialogComponent;
|
let component: WorkflowSpecCategoryDialogComponent;
|
||||||
let fixture: ComponentFixture<WorkflowSpecCategoryDialogComponent>;
|
let fixture: ComponentFixture<WorkflowSpecCategoryDialogComponent>;
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ describe('WorkflowSpecDialogComponent', () => {
|
||||||
FormlyModule.forRoot(),
|
FormlyModule.forRoot(),
|
||||||
FormlyMaterialModule,
|
FormlyMaterialModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
|
HttpClientTestingModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
|
@ -31,6 +34,8 @@ describe('WorkflowSpecDialogComponent', () => {
|
||||||
],
|
],
|
||||||
declarations: [WorkflowSpecCategoryDialogComponent],
|
declarations: [WorkflowSpecCategoryDialogComponent],
|
||||||
providers: [
|
providers: [
|
||||||
|
ApiService,
|
||||||
|
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment},
|
||||||
{
|
{
|
||||||
provide: MatDialogRef,
|
provide: MatDialogRef,
|
||||||
useValue: {
|
useValue: {
|
||||||
|
@ -45,11 +50,17 @@ describe('WorkflowSpecDialogComponent', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
httpMock = TestBed.inject(HttpTestingController);
|
||||||
fixture = TestBed.createComponent(WorkflowSpecCategoryDialogComponent);
|
fixture = TestBed.createComponent(WorkflowSpecCategoryDialogComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
httpMock.verify();
|
||||||
|
fixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {FileMeta, FileType, WorkflowSpec, WorkflowSpecCategory} from 'sartograph
|
||||||
export interface FileMetaDialogData {
|
export interface FileMetaDialogData {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
fileType: FileType;
|
fileType: FileType;
|
||||||
|
file?: File;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NewFileDialogData {
|
export interface NewFileDialogData {
|
||||||
|
|
|
@ -14,6 +14,8 @@ export class GetIconCodePipe implements PipeTransform {
|
||||||
return 'image';
|
return 'image';
|
||||||
case FileType.DMN:
|
case FileType.DMN:
|
||||||
return 'view_list';
|
return 'view_list';
|
||||||
|
default:
|
||||||
|
return 'insert_drive_file';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
[attr.data-file-meta-id]="fm.id"
|
[attr.data-file-meta-id]="fm.id"
|
||||||
[attr.data-workflow-spec-id]="workflowSpec.id"
|
[attr.data-workflow-spec-id]="workflowSpec.id"
|
||||||
>
|
>
|
||||||
<mat-icon (click)="editFile(fm.id)" mat-list-icon>{{fm.type | getIconCode}}</mat-icon>
|
<mat-icon (click)="editFile(fm)" mat-list-icon>{{fm.type | getIconCode}}</mat-icon>
|
||||||
<ng-container *ngIf="fm.type === fileType.BPMN">
|
<ng-container *ngIf="fm.type === fileType.BPMN">
|
||||||
<button (click)="makePrimary(fm)" *ngIf="!fm.primary" mat-flat-button>
|
<button (click)="makePrimary(fm)" *ngIf="!fm.primary" mat-flat-button>
|
||||||
<mat-icon>radio_button_unchecked</mat-icon>
|
<mat-icon>radio_button_unchecked</mat-icon>
|
||||||
|
@ -16,9 +16,9 @@
|
||||||
Primary process
|
Primary process
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<h4 (click)="editFile(fm.id)" mat-line>{{fm.name}}</h4>
|
<h4 (click)="editFile(fm)" mat-line>{{fm.name}}</h4>
|
||||||
<p (click)="editFile(fm.id)" mat-line>{{fm.last_updated | date}}</p>
|
<p (click)="editFile(fm)" mat-line>{{fm.last_updated | date}}</p>
|
||||||
<button (click)="editFile(fm.id)" class="mat-elevation-z0" color="primary" mat-icon-button>
|
<button (click)="editFile(fm)" class="mat-elevation-z0" color="primary" mat-icon-button>
|
||||||
<mat-icon>edit</mat-icon>
|
<mat-icon>edit</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<button (click)="confirmDelete(fm)" class="mat-elevation-z0" color="warn" mat-icon-button>
|
<button (click)="confirmDelete(fm)" class="mat-elevation-z0" color="warn" mat-icon-button>
|
||||||
|
|
|
@ -149,7 +149,7 @@ describe('FileListComponent', () => {
|
||||||
it('should navigate to modeler to edit a file', () => {
|
it('should navigate to modeler to edit a file', () => {
|
||||||
const routerNavigateSpy = spyOn((component as any).router, 'navigate');
|
const routerNavigateSpy = spyOn((component as any).router, 'navigate');
|
||||||
component.workflowSpec = mockWorkflowSpec0;
|
component.workflowSpec = mockWorkflowSpec0;
|
||||||
component.editFile(mockFileMeta0.id);
|
component.editFile(mockFileMeta0);
|
||||||
expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockFileMeta0.id}`]);
|
expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockFileMeta0.id}`]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,8 @@ import {MatSnackBar} from '@angular/material/snack-bar';
|
||||||
import {Router} from '@angular/router';
|
import {Router} from '@angular/router';
|
||||||
import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
|
import {ApiService, FileMeta, FileType, WorkflowSpec} from 'sartography-workflow-lib';
|
||||||
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
|
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
|
||||||
import {DeleteFileDialogData} from '../_interfaces/dialog-data';
|
import {FileMetaDialogComponent} from '../_dialogs/file-meta-dialog/file-meta-dialog.component';
|
||||||
|
import {DeleteFileDialogData, FileMetaDialogData} from '../_interfaces/dialog-data';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-file-list',
|
selector: 'app-file-list',
|
||||||
|
@ -28,8 +29,38 @@ export class FileListComponent implements OnInit {
|
||||||
this._loadFileMetas();
|
this._loadFileMetas();
|
||||||
}
|
}
|
||||||
|
|
||||||
editFile(fileMetaId: number) {
|
editFile(fileMeta: FileMeta) {
|
||||||
this.router.navigate([`/modeler/${this.workflowSpec.id}/${fileMetaId}`]);
|
if (fileMeta.type === FileType.BPMN ||fileMeta.type === FileType.DMN) {
|
||||||
|
this.router.navigate([`/modeler/${this.workflowSpec.id}/${fileMeta.id}`]);
|
||||||
|
} else {
|
||||||
|
// Show edit file meta dialog
|
||||||
|
this.editFileMeta(fileMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editFileMeta(fm: FileMeta) {
|
||||||
|
const dialogRef = this.dialog.open(FileMetaDialogComponent, {
|
||||||
|
data: {
|
||||||
|
fileName: fm.name,
|
||||||
|
fileType: fm.type,
|
||||||
|
file: fm.file,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialogRef.afterClosed().subscribe((data: FileMetaDialogData) => {
|
||||||
|
if (data && data.fileName && data.fileType) {
|
||||||
|
const newFileMeta: FileMeta = {
|
||||||
|
content_type: data.fileType,
|
||||||
|
name: data.fileName,
|
||||||
|
type: data.fileType,
|
||||||
|
file: data.file,
|
||||||
|
};
|
||||||
|
this.api.updateFileMeta(newFileMeta).subscribe(() => {
|
||||||
|
// Reload all fileMetas when all have been updated.
|
||||||
|
this._loadFileMetas();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDelete(fm: FileMeta) {
|
confirmDelete(fm: FileMeta) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
ApiService,
|
ApiService,
|
||||||
MockEnvironment,
|
MockEnvironment,
|
||||||
mockWorkflowSpec0,
|
mockWorkflowSpec0,
|
||||||
mockWorkflowSpec1,
|
mockWorkflowSpec1, mockWorkflowSpecCategories,
|
||||||
mockWorkflowSpecs
|
mockWorkflowSpecs
|
||||||
} from 'sartography-workflow-lib';
|
} from 'sartography-workflow-lib';
|
||||||
import {DeleteWorkflowSpecDialogComponent} from '../_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component';
|
import {DeleteWorkflowSpecDialogComponent} from '../_dialogs/delete-workflow-spec-dialog/delete-workflow-spec-dialog.component';
|
||||||
|
@ -69,15 +69,19 @@ describe('WorkflowSpecListComponent', () => {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
httpMock = TestBed.inject(HttpTestingController);
|
||||||
fixture = TestBed.createComponent(WorkflowSpecListComponent);
|
fixture = TestBed.createComponent(WorkflowSpecListComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
httpMock = TestBed.inject(HttpTestingController);
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const sReq = httpMock.expectOne('apiRoot/workflow-specification');
|
const catReq = httpMock.expectOne('apiRoot/workflow-specification-category');
|
||||||
expect(sReq.request.method).toEqual('GET');
|
expect(catReq.request.method).toEqual('GET');
|
||||||
sReq.flush(mockWorkflowSpecs);
|
catReq.flush(mockWorkflowSpecCategories);
|
||||||
|
expect(component.categories.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
const specReq = httpMock.expectOne('apiRoot/workflow-specification');
|
||||||
|
expect(specReq.request.method).toEqual('GET');
|
||||||
|
specReq.flush(mockWorkflowSpecs);
|
||||||
expect(component.workflowSpecs.length).toBeGreaterThan(0);
|
expect(component.workflowSpecs.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,8 @@ export class WorkflowSpecListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadWorkflowSpecCategories() {
|
private _loadWorkflowSpecCategories() {
|
||||||
|
console.log('=== _loadWorkflowSpecCategories ===');
|
||||||
|
|
||||||
this.api.getWorkflowSpecCategoryList().subscribe(cats => {
|
this.api.getWorkflowSpecCategoryList().subscribe(cats => {
|
||||||
this.categories = cats;
|
this.categories = cats;
|
||||||
this.workflowSpecsByCategory = [{
|
this.workflowSpecsByCategory = [{
|
||||||
|
@ -137,6 +139,7 @@ export class WorkflowSpecListComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadWorkflowSpecs() {
|
private _loadWorkflowSpecs() {
|
||||||
|
console.log('=== _loadWorkflowSpecs ===');
|
||||||
this.api.getWorkflowSpecList().subscribe(wfs => {
|
this.api.getWorkflowSpecList().subscribe(wfs => {
|
||||||
this.workflowSpecs = wfs;
|
this.workflowSpecs = wfs;
|
||||||
this.workflowSpecsByCategory.forEach(cat => {
|
this.workflowSpecsByCategory.forEach(cat => {
|
||||||
|
|
Loading…
Reference in New Issue