mirror of
https://github.com/sartography/cr-connect-bpmn.git
synced 2025-01-11 17:44:32 +00:00
Finish #367 to allow user to choose libraries for a given workflow
This commit is contained in:
parent
30857d0189
commit
6c9a3807f9
14
package-lock.json
generated
14
package-lock.json
generated
@ -40,7 +40,7 @@
|
||||
"ngx-markdown": "^9.1.1",
|
||||
"protractor": "^7.0.0",
|
||||
"rxjs": "~6.5.4",
|
||||
"sartography-workflow-lib": "0.0.532",
|
||||
"sartography-workflow-lib": "0.0.534",
|
||||
"tslib": "^1.13.0",
|
||||
"uuid": "^7.0.2",
|
||||
"zone.js": "^0.10.3"
|
||||
@ -15269,9 +15269,9 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/sartography-workflow-lib": {
|
||||
"version": "0.0.532",
|
||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.532.tgz",
|
||||
"integrity": "sha512-Q9uYVCIAjiRruhrQztPlKF6VC0na56X33ximXCAbyXF5TMeyR5KyslgprXNkVeyMLo4z1I2YBO+5ffOQ9I7TYA==",
|
||||
"version": "0.0.534",
|
||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.534.tgz",
|
||||
"integrity": "sha512-oUradcyBTsi7mpcIMsuG+WRTHsbc2TeUojK6WqtoAkI9YSGQqBZxCJVRxTWEVVMKsgXrxBytjhz7entsOR0w+g==",
|
||||
"peerDependencies": {
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/core": "^9.1.11",
|
||||
@ -32187,9 +32187,9 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sartography-workflow-lib": {
|
||||
"version": "0.0.532",
|
||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.532.tgz",
|
||||
"integrity": "sha512-Q9uYVCIAjiRruhrQztPlKF6VC0na56X33ximXCAbyXF5TMeyR5KyslgprXNkVeyMLo4z1I2YBO+5ffOQ9I7TYA==",
|
||||
"version": "0.0.534",
|
||||
"resolved": "https://registry.npmjs.org/sartography-workflow-lib/-/sartography-workflow-lib-0.0.534.tgz",
|
||||
"integrity": "sha512-oUradcyBTsi7mpcIMsuG+WRTHsbc2TeUojK6WqtoAkI9YSGQqBZxCJVRxTWEVVMKsgXrxBytjhz7entsOR0w+g==",
|
||||
"requires": {}
|
||||
},
|
||||
"sass": {
|
||||
|
@ -55,7 +55,7 @@
|
||||
"ngx-markdown": "^9.1.1",
|
||||
"protractor": "^7.0.0",
|
||||
"rxjs": "~6.5.4",
|
||||
"sartography-workflow-lib": "0.0.532",
|
||||
"sartography-workflow-lib": "0.0.534",
|
||||
"tslib": "^1.13.0",
|
||||
"uuid": "^7.0.2",
|
||||
"zone.js": "^0.10.3"
|
||||
|
@ -53,8 +53,9 @@ import {MatSidenavModule} from '@angular/material/sidenav';
|
||||
import { ConfirmDialogComponent } from './_dialogs/confirm-dialog/confirm-dialog.component';
|
||||
import {MatExpansionModule} from '@angular/material/expansion';
|
||||
import { SettingsComponent } from './settings/settings.component';
|
||||
import {MatSelect, MatSelectModule} from '@angular/material/select';
|
||||
import { MatSelectModule} from '@angular/material/select';
|
||||
import {LibraryListComponent} from './library-list/library-list.component';
|
||||
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||
|
||||
@Injectable()
|
||||
export class ThisEnvironment implements AppEnvironment {
|
||||
@ -135,6 +136,7 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
|
||||
AppRoutingModule,
|
||||
MatSidenavModule,
|
||||
MatExpansionModule,
|
||||
MatCheckboxModule,
|
||||
// <-- This line MUST be last (https://angular.io/guide/router#module-import-order-matters)
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
|
@ -1,46 +1,10 @@
|
||||
<div class="file-list">
|
||||
<mat-list>
|
||||
<mat-list-item
|
||||
*ngFor="let fm of fileMetas"
|
||||
[attr.data-file-meta-id]="fm.id"
|
||||
[attr.data-workflow-spec-id]="workflowSpec.id"
|
||||
*ngFor="let fm of workflowLibraries"
|
||||
>
|
||||
<mat-icon (click)="editFile(fm)" mat-list-icon>{{fm.type | getIconCode}}</mat-icon>
|
||||
<ng-container *ngIf="fm.type === fileType.BPMN">
|
||||
<button (click)="makePrimary(fm)" *ngIf="!fm.primary" mat-flat-button class="make-primary">
|
||||
<mat-icon>radio_button_unchecked</mat-icon>
|
||||
Make primary process
|
||||
</button>
|
||||
<button *ngIf="fm.primary" mat-flat-button class="make-primary">
|
||||
<mat-icon>radio_button_checked</mat-icon>
|
||||
Primary process
|
||||
</button>
|
||||
</ng-container>
|
||||
<h4 (click)="editFile(fm)" mat-line>{{fm.name}}</h4>
|
||||
<p (click)="editFile(fm)" mat-line> Updated: {{fm.last_modified | date:'medium'}}</p>
|
||||
<button (click)="downloadFile(fm)" class="mat-elevation-z0" color="primary" mat-icon-button>
|
||||
<mat-icon>save_alt</mat-icon>
|
||||
</button>
|
||||
<button (click)="editFile(fm)" class="mat-elevation-z0" color="primary" mat-icon-button>
|
||||
<mat-icon>edit</mat-icon>
|
||||
</button>
|
||||
<button (click)="confirmDelete(fm)" class="mat-elevation-z0" color="warn" mat-icon-button>
|
||||
<mat-icon>delete</mat-icon>
|
||||
</button>
|
||||
<mat-checkbox (click)="updateItem(fm,isChecked(fm))" [checked]="isChecked(fm)">{{fm.display_name}}</mat-checkbox>
|
||||
</mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
<div class="file-list-actions">
|
||||
<button [queryParams]="{action: 'newFile'}" [routerLink]="['/modeler/' + workflowSpec.id]" mat-button>
|
||||
<mat-icon>note_add</mat-icon>
|
||||
Add new BPMN or DMN file
|
||||
</button>
|
||||
<button [queryParams]="{action: 'openFile'}" [routerLink]="['/modeler/' + workflowSpec.id]" mat-button>
|
||||
<mat-icon>cloud_upload</mat-icon>
|
||||
Upload BPMN or DMN file
|
||||
</button>
|
||||
<button (click)="editFile()" mat-button>
|
||||
<mat-icon>cloud_upload</mat-icon>
|
||||
Upload Template file
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -1,241 +1,57 @@
|
||||
import {APP_BASE_HREF} from '@angular/common';
|
||||
import {HttpHeaders} from '@angular/common/http';
|
||||
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
|
||||
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/dialog';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import {MatIconModule} from '@angular/material/icon';
|
||||
import {MatListModule} from '@angular/material/list';
|
||||
import {MatSnackBarModule} from '@angular/material/snack-bar';
|
||||
import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import createClone from 'rfdc';
|
||||
import {of} from 'rxjs';
|
||||
import {
|
||||
ApiService,
|
||||
FileMeta,
|
||||
FileType,
|
||||
MockEnvironment, mockFile0,
|
||||
mockFileMeta0,
|
||||
mockFileMetas,
|
||||
mockWorkflowSpec0
|
||||
} from 'sartography-workflow-lib';
|
||||
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
|
||||
import {DeleteFileDialogData} from '../_interfaces/dialog-data';
|
||||
import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe';
|
||||
import {FileListComponent} from '../file-list/file-list.component';
|
||||
import {MatMenuModule} from '@angular/material/menu';
|
||||
import {ApiService, MockEnvironment, mockWorkflowSpec0, mockWorkflowSpec1, WorkflowSpec} from 'sartography-workflow-lib';
|
||||
import {LibraryListComponent} from './library-list.component';
|
||||
|
||||
|
||||
describe('FileListComponent', () => {
|
||||
|
||||
describe('LibraryListComponent', () => {
|
||||
let component: LibraryListComponent;
|
||||
let fixture: ComponentFixture<LibraryListComponent>;
|
||||
let httpMock: HttpTestingController;
|
||||
let component: FileListComponent;
|
||||
let fixture: ComponentFixture<FileListComponent>;
|
||||
const timeString = '2020-01-23T12:34:12.345Z';
|
||||
const timeCode = new Date(timeString).getTime();
|
||||
|
||||
let libraries: WorkflowSpec[];
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
BrowserAnimationsModule,
|
||||
HttpClientTestingModule,
|
||||
MatDialogModule,
|
||||
MatIconModule,
|
||||
MatListModule,
|
||||
MatSnackBarModule,
|
||||
RouterTestingModule,
|
||||
],
|
||||
declarations: [
|
||||
DeleteFileDialogComponent,
|
||||
FileListComponent,
|
||||
GetIconCodePipe,
|
||||
LibraryListComponent
|
||||
],
|
||||
imports: [
|
||||
HttpClientTestingModule,
|
||||
MatIconModule,
|
||||
MatMenuModule,
|
||||
// RouterTestingModule,
|
||||
],
|
||||
providers: [
|
||||
ApiService,
|
||||
{
|
||||
},
|
||||
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment},
|
||||
{provide: APP_BASE_HREF, useValue: ''},
|
||||
{
|
||||
provide: MatDialogRef,
|
||||
useValue: {
|
||||
close: (dialogResult: any) => {
|
||||
}
|
||||
}
|
||||
},
|
||||
{provide: MAT_DIALOG_DATA, useValue: []},
|
||||
]
|
||||
}).overrideModule(BrowserDynamicTestingModule, {
|
||||
set: {
|
||||
entryComponents: [
|
||||
DeleteFileDialogComponent,
|
||||
]
|
||||
}
|
||||
],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(FileListComponent);
|
||||
component = fixture.componentInstance;
|
||||
localStorage.setItem('token', 'some_token');
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
fixture = TestBed.createComponent(LibraryListComponent);
|
||||
component = fixture.componentInstance;
|
||||
libraries = [mockWorkflowSpec0, mockWorkflowSpec1];
|
||||
libraries[0].library = true;
|
||||
libraries[1].library = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
|
||||
const fmsReq = httpMock.expectOne(`apiRoot/file?workflow_spec_id=${mockWorkflowSpec0.id}`);
|
||||
expect(fmsReq.request.method).toEqual('GET');
|
||||
fmsReq.flush(mockFileMetas);
|
||||
expect(component.fileMetas.length).toBeGreaterThan(0);
|
||||
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
fixture.destroy();
|
||||
const uReq = httpMock.expectOne('apiRoot/workflow-specification?libraries=true');
|
||||
expect(uReq.request.method).toEqual('GET');
|
||||
uReq.flush(libraries);
|
||||
expect(component.workflowLibraries).toEqual(libraries);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should sort files by name', () => {
|
||||
let prevFileMeta;
|
||||
|
||||
for (const thisFileMeta of component.fileMetas) {
|
||||
if (!prevFileMeta) {
|
||||
prevFileMeta = thisFileMeta;
|
||||
} else {
|
||||
expect(thisFileMeta.name).toBeGreaterThan(prevFileMeta.name);
|
||||
prevFileMeta = thisFileMeta;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('should show a confirmation dialog before deleting a file', () => {
|
||||
const mockConfirmDeleteData: DeleteFileDialogData = {
|
||||
confirm: false,
|
||||
fileMeta: mockFileMeta0,
|
||||
};
|
||||
|
||||
const _deleteFileSpy = spyOn((component as any), '_deleteFile').and.stub();
|
||||
const openDialogSpy = spyOn(component.dialog, 'open')
|
||||
.and.returnValue({afterClosed: () => of(mockConfirmDeleteData)} as any);
|
||||
|
||||
component.confirmDelete(mockFileMeta0);
|
||||
expect(openDialogSpy).toHaveBeenCalled();
|
||||
expect(_deleteFileSpy).not.toHaveBeenCalled();
|
||||
|
||||
mockConfirmDeleteData.confirm = true;
|
||||
component.confirmDelete(mockFileMeta0);
|
||||
expect(openDialogSpy).toHaveBeenCalled();
|
||||
expect(_deleteFileSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should delete a file', () => {
|
||||
const loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub();
|
||||
(component as any)._deleteFile(mockFileMeta0);
|
||||
const fmsReq = httpMock.expectOne(`apiRoot/file/${mockFileMeta0.id}`);
|
||||
expect(fmsReq.request.method).toEqual('DELETE');
|
||||
fmsReq.flush(null);
|
||||
|
||||
expect(loadFileMetasSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should navigate to modeler to edit a BPMN or DMN file', () => {
|
||||
const routerNavigateSpy = spyOn((component as any).router, 'navigate');
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
component.editFile(mockFileMeta0);
|
||||
expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockFileMeta0.id}`]);
|
||||
|
||||
routerNavigateSpy.calls.reset();
|
||||
const mockDmnMeta = createClone()(mockFileMeta0);
|
||||
mockDmnMeta.type = FileType.DMN;
|
||||
component.editFile(mockDmnMeta);
|
||||
expect(routerNavigateSpy).toHaveBeenCalledWith([`/modeler/${mockWorkflowSpec0.id}/${mockDmnMeta.id}`]);
|
||||
});
|
||||
|
||||
it('should open file metadata dialog for non-BPMN files', () => {
|
||||
const routerNavigateSpy = spyOn((component as any).router, 'navigate');
|
||||
const editFileMetaSpy = spyOn(component, 'editFileMeta');
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
const mockDocMeta = createClone()(mockFileMeta0);
|
||||
mockDocMeta.type = FileType.DOCX;
|
||||
component.editFile(mockDocMeta);
|
||||
expect(routerNavigateSpy).not.toHaveBeenCalled();
|
||||
expect(editFileMetaSpy).toHaveBeenCalledWith(mockDocMeta);
|
||||
|
||||
routerNavigateSpy.calls.reset();
|
||||
editFileMetaSpy.calls.reset();
|
||||
component.editFile(null);
|
||||
expect(routerNavigateSpy).not.toHaveBeenCalled();
|
||||
expect(editFileMetaSpy).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it('should open file metadata dialog', () => {
|
||||
const _openFileDialogSpy = spyOn((component as any), '_openFileDialog').and.stub();
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
const mockDocMeta: FileMeta = createClone()(mockFileMeta0);
|
||||
mockDocMeta.type = FileType.DOCX;
|
||||
component.editFileMeta(mockDocMeta);
|
||||
|
||||
const expectedFile = new File([], mockDocMeta.name, {
|
||||
type: mockDocMeta.content_type,
|
||||
lastModified: timeCode
|
||||
});
|
||||
const fReq = httpMock.expectOne(`apiRoot/file/${mockDocMeta.id}/data`);
|
||||
|
||||
const mockHeaders = new HttpHeaders()
|
||||
.append('last-modified', expectedFile.lastModified.toString())
|
||||
.append('content-type', mockDocMeta.content_type);
|
||||
expect(fReq.request.method).toEqual('GET');
|
||||
fReq.flush(new ArrayBuffer(8), {headers: mockHeaders});
|
||||
expect(fReq.request.method).toEqual('GET');
|
||||
expect(_openFileDialogSpy).toHaveBeenCalledWith(mockDocMeta, expectedFile);
|
||||
|
||||
_openFileDialogSpy.calls.reset();
|
||||
|
||||
component.editFileMeta(null);
|
||||
expect(_openFileDialogSpy).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should upload new file from file dialog', () => {
|
||||
const openDialogSpy = spyOn(component.dialog, 'open')
|
||||
.and.returnValue({afterClosed: () => of({file: mockFile0})} as any);
|
||||
const _loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub();
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
|
||||
(component as any)._openFileDialog();
|
||||
const addReq = httpMock.expectOne(`apiRoot/file?workflow_spec_id=${mockWorkflowSpec0.id}`);
|
||||
expect(addReq.request.method).toEqual('POST');
|
||||
addReq.flush(mockFileMeta0);
|
||||
|
||||
expect(openDialogSpy).toHaveBeenCalled();
|
||||
expect(_loadFileMetasSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should update existing file from file dialog', () => {
|
||||
const openDialogSpy = spyOn(component.dialog, 'open')
|
||||
.and.returnValue({afterClosed: () => of({fileMetaId: mockFileMeta0.id, file: mockFile0})} as any);
|
||||
const _loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub();
|
||||
component.workflowSpec = mockWorkflowSpec0;
|
||||
|
||||
(component as any)._openFileDialog(mockFileMeta0, mockFile0);
|
||||
const updateReq = httpMock.expectOne(`apiRoot/file/${mockFileMeta0.id}/data`);
|
||||
expect(updateReq.request.method).toEqual('PUT');
|
||||
updateReq.flush(mockFileMeta0);
|
||||
|
||||
expect(openDialogSpy).toHaveBeenCalled();
|
||||
expect(_loadFileMetasSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should flag a file as primary', () => {
|
||||
const updateFileMetaSpy = spyOn((component as any).api, 'updateFileMeta').and.returnValue(of(mockFileMeta0));
|
||||
const _loadFileMetasSpy = spyOn((component as any), '_loadFileMetas').and.stub();
|
||||
expect(component.fileMetas.length).toEqual(mockFileMetas.length);
|
||||
component.makePrimary(mockFileMeta0);
|
||||
|
||||
expect(updateFileMetaSpy).toHaveBeenCalledTimes(mockFileMetas.length);
|
||||
expect(component.fileMetas.length).toEqual(mockFileMetas.length);
|
||||
expect(component.fileMetas.reduce((sum, fm) => fm.primary ? sum + 1 : sum, 0)).toEqual(1);
|
||||
expect(_loadFileMetasSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -1,20 +1,8 @@
|
||||
import {Component, Input, OnChanges, OnInit} from '@angular/core';
|
||||
import {MatDialog} from '@angular/material/dialog';
|
||||
import {MatSnackBar} from '@angular/material/snack-bar';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {
|
||||
ApiService,
|
||||
FileMeta,
|
||||
FileParams,
|
||||
FileType,
|
||||
getFileType,
|
||||
isNumberDefined, newFileFromResponse,
|
||||
WorkflowSpec
|
||||
} from 'sartography-workflow-lib';
|
||||
import {DeleteFileDialogComponent} from '../_dialogs/delete-file-dialog/delete-file-dialog.component';
|
||||
import {OpenFileDialogComponent} from '../_dialogs/open-file-dialog/open-file-dialog.component';
|
||||
import {DeleteFileDialogData, OpenFileDialogData} from '../_interfaces/dialog-data';
|
||||
import * as fileSaver from 'file-saver';
|
||||
|
||||
@Component({
|
||||
selector: 'app-library-list',
|
||||
@ -22,136 +10,47 @@ import * as fileSaver from 'file-saver';
|
||||
styleUrls: ['./library-list.component.scss']
|
||||
})
|
||||
export class LibraryListComponent implements OnInit, OnChanges {
|
||||
@Input() workflowSpec: WorkflowSpec;
|
||||
fileMetas: FileMeta[];
|
||||
fileType = FileType;
|
||||
@Input() workflowSpecId: string;
|
||||
workflowLibraries: WorkflowSpec[];
|
||||
|
||||
constructor(
|
||||
private api: ApiService,
|
||||
public dialog: MatDialog,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private snackBar: MatSnackBar,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._loadFileMetas();
|
||||
this._loadWorkflowLibraries();
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this._loadFileMetas();
|
||||
this._loadWorkflowLibraries();
|
||||
}
|
||||
|
||||
editFile(fileMeta?: FileMeta) {
|
||||
if (fileMeta && ((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);
|
||||
|
||||
isChecked(libraryspec): boolean {
|
||||
let checked = false;
|
||||
for (const item of libraryspec.parents) {
|
||||
checked = checked || (item.id === this.workflowSpecId);
|
||||
}
|
||||
return checked;
|
||||
}
|
||||
|
||||
editFileMeta(fm: FileMeta) {
|
||||
if (fm && isNumberDefined(fm.id)) {
|
||||
this.api.getFileData(fm.id).subscribe(response => {
|
||||
const file = newFileFromResponse(fm, response);
|
||||
this._openFileDialog(fm, file);
|
||||
updateItem(library: WorkflowSpec , checked: boolean) {
|
||||
if (checked) {
|
||||
this.api.deleteWorkflowLibrary(this.workflowSpecId, library.id).subscribe(() => {
|
||||
this._loadWorkflowLibraries();
|
||||
});
|
||||
} else {
|
||||
this._openFileDialog();
|
||||
}
|
||||
}
|
||||
|
||||
confirmDelete(fm: FileMeta) {
|
||||
const dialogRef = this.dialog.open(DeleteFileDialogComponent, {
|
||||
data: {
|
||||
confirm: false,
|
||||
fileMeta: fm,
|
||||
}
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((data: DeleteFileDialogData) => {
|
||||
if (data && data.confirm && data.fileMeta) {
|
||||
this._deleteFile(data.fileMeta);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
makePrimary(fmPrimary: FileMeta) {
|
||||
if (fmPrimary.type === FileType.BPMN) {
|
||||
let numUpdated = 0;
|
||||
// Fixme: This buisness rule does not belong here.
|
||||
this.fileMetas.forEach(fm => {
|
||||
fm.primary = (fmPrimary.id === fm.id);
|
||||
this.api.updateFileMeta(fm).subscribe(() => {
|
||||
numUpdated++;
|
||||
|
||||
// Reload all fileMetas when all have been updated.
|
||||
if (numUpdated === this.fileMetas.length) {
|
||||
this._loadFileMetas();
|
||||
}
|
||||
});
|
||||
this.api.addWorkflowLibrary(this.workflowSpecId, library.id).subscribe(() => {
|
||||
this._loadWorkflowLibraries();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _openFileDialog(fm?: FileMeta, file?: File) {
|
||||
const dialogData: OpenFileDialogData = {
|
||||
fileMetaId: fm ? fm.id : undefined,
|
||||
file: file,
|
||||
mode: 'local',
|
||||
fileTypes: [FileType.DOC, FileType.DOCX, FileType.XLSX, FileType.XLS],
|
||||
};
|
||||
const dialogRef = this.dialog.open(OpenFileDialogComponent, {data: dialogData});
|
||||
private _loadWorkflowLibraries() {
|
||||
|
||||
dialogRef.afterClosed().subscribe((data: OpenFileDialogData) => {
|
||||
if (data && data.file) {
|
||||
const newFileMeta: FileMeta = {
|
||||
id: data.fileMetaId,
|
||||
content_type: data.file.type,
|
||||
name: data.file.name,
|
||||
type: getFileType(data.file),
|
||||
workflow_spec_id: this.workflowSpec.id,
|
||||
};
|
||||
|
||||
if (isNumberDefined(data.fileMetaId)) {
|
||||
// Update existing file
|
||||
this.api.updateFileData(newFileMeta, data.file).subscribe(() => {
|
||||
this._loadFileMetas();
|
||||
});
|
||||
} else {
|
||||
// Add new file
|
||||
const fileParams: FileParams = {
|
||||
workflow_spec_id: this.workflowSpec.id,
|
||||
};
|
||||
|
||||
this.api.addFile(fileParams, newFileMeta, data.file).subscribe(dbFm => {
|
||||
this._loadFileMetas();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private _deleteFile(fileMeta: FileMeta) {
|
||||
this.api.deleteFileMeta(fileMeta.id).subscribe(() => {
|
||||
this._loadFileMetas();
|
||||
this.snackBar.open(`Deleted file ${fileMeta.name}.`, 'Ok', {duration: 3000});
|
||||
});
|
||||
}
|
||||
|
||||
private _loadFileMetas() {
|
||||
this.api.getFileMetas({workflow_spec_id: this.workflowSpec.id}).subscribe(fms => {
|
||||
this.fileMetas = fms.sort((a, b) => (a.name > b.name) ? 1 : -1);
|
||||
});
|
||||
}
|
||||
|
||||
downloadFile(fm: FileMeta) {
|
||||
this.api.getFileData(fm.id).subscribe(response => {
|
||||
const blob = new Blob([response.body], {type: fm.content_type});
|
||||
fileSaver.saveAs(blob, fm.name);
|
||||
this.api.getWorkflowSpecificationLibraries().subscribe(wfs => {
|
||||
this.workflowLibraries = wfs;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,10 @@
|
||||
<ng-template #thenBlock><dd>True</dd></ng-template>
|
||||
<ng-template #elseBlock><dd>False</dd></ng-template>
|
||||
</dl>
|
||||
|
||||
<div *ngIf="!workflowSpec.library">
|
||||
<h4>Included Libraries</h4>
|
||||
<app-library-list [workflowSpecId]="workflowSpec.id"></app-library-list>
|
||||
</div>
|
||||
<h4>Workflow Spec Files</h4>
|
||||
<app-file-list [workflowSpec]="workflowSpec"></app-file-list>
|
||||
</mat-card-content>
|
||||
|
Loading…
x
Reference in New Issue
Block a user