diff --git a/src/app/_interfaces/file-meta-dialog-data.ts b/src/app/_interfaces/file-meta-dialog-data.ts index 9d0cd58..3cbe984 100644 --- a/src/app/_interfaces/file-meta-dialog-data.ts +++ b/src/app/_interfaces/file-meta-dialog-data.ts @@ -1,7 +1,6 @@ +import {FileType} from 'sartography-workflow-lib'; + export interface FileMetaDialogData { fileName: string; - workflowSpecId: string; - name: string; - displayName: string; - description: string; + fileType: FileType; } diff --git a/src/app/_util/string-clean.ts b/src/app/_util/string-clean.ts index b033f7b..852076b 100644 --- a/src/app/_util/string-clean.ts +++ b/src/app/_util/string-clean.ts @@ -1,3 +1,5 @@ +import {FileType} from 'sartography-workflow-lib'; + export const trimString = (str: string): string => { return !str ? '' : String(str).replace(/^\W+|\W+$/gi, ''); }; @@ -9,12 +11,12 @@ export const toSnakeCase = (str: string): string => { .toLowerCase(); }; -export const cleanUpFilename = (str: string, extension: string): string => { +export const cleanUpFilename = (str: string, extension: FileType|string): string => { const arr = trimString(str).split('.'); // Add file extension, if necessary if (arr.length < 2) { - arr.push('bpmn'); + arr.push(extension); } else { (arr[arr.length - 1]) = extension; } diff --git a/src/app/diagram/diagram.component.spec.ts b/src/app/diagram/diagram.component.spec.ts index 50b990f..01254d6 100644 --- a/src/app/diagram/diagram.component.spec.ts +++ b/src/app/diagram/diagram.component.spec.ts @@ -3,7 +3,7 @@ import {DebugNode} from '@angular/core'; import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {MatIconModule} from '@angular/material/icon'; import * as FileSaver from 'file-saver'; -import {ApiService, FileType, MockEnvironment} from 'sartography-workflow-lib'; +import {ApiService, BPMN_DIAGRAM_DEFAULT, FileType, MockEnvironment} from 'sartography-workflow-lib'; import { BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS, @@ -134,10 +134,11 @@ describe('DiagramComponent', () => { it('should create a new diagram', () => { const initializeModelerSpy = spyOn(component, 'initializeModeler').and.stub(); - const createDiagramSpy = spyOn(component.modeler, 'createDiagram').and.stub(); + const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub(); + spyOn(component, 'getRandomString').and.returnValue('REPLACE_ME'); component.openDiagram(); expect(initializeModelerSpy).toHaveBeenCalledWith(undefined); - expect(createDiagramSpy).toHaveBeenCalled(); + expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT, jasmine.any(Function)); }); it('should open an existing BPMN diagram from XML', () => { @@ -177,10 +178,11 @@ describe('DiagramComponent', () => { it('should edit diagram', () => { const initializeModelerSpy = spyOn(component, 'initializeModeler').and.stub(); const onChangeSpy = spyOn(component, 'onChange').and.stub(); - const createDiagramSpy = spyOn(component.modeler, 'createDiagram').and.stub(); + const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub(); + spyOn(component, 'getRandomString').and.returnValue('REPLACE_ME'); component.openDiagram(); expect(initializeModelerSpy).toHaveBeenCalledWith(undefined); - expect(createDiagramSpy).toHaveBeenCalled(); + expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT, jasmine.any(Function)); component.writeValue(BPMN_DIAGRAM); expect(initializeModelerSpy).toHaveBeenCalledWith(undefined); diff --git a/src/app/diagram/diagram.component.ts b/src/app/diagram/diagram.component.ts index df98c1f..b3b49d5 100644 --- a/src/app/diagram/diagram.component.ts +++ b/src/app/diagram/diagram.component.ts @@ -4,14 +4,13 @@ import {ControlValueAccessor} from '@angular/forms'; import BpmnModeler from 'bpmn-js/lib/Modeler'; import DmnModeler from 'dmn-js/lib/Modeler'; import * as fileSaver from 'file-saver'; -import {ApiService, FileType} from 'sartography-workflow-lib'; -import {DMN_DIAGRAM_EMPTY} from '../../testing/mocks/diagram.mocks'; +import {ApiService, BPMN_DIAGRAM_DEFAULT, DMN_DIAGRAM_DEFAULT, FileType} from 'sartography-workflow-lib'; +import {v4 as uuidv4} from 'uuid'; import {BpmnWarning} from '../_interfaces/bpmn-warning'; import {ImportEvent} from '../_interfaces/import-event'; import {getDiagramTypeFromXml} from '../_util/diagram-type'; import {bpmnModelerConfig} from './bpmn-modeler-config'; import {dmnModelerConfig} from './dmn-modeler-config'; -import {v4 as uuidv4} from 'uuid'; @Component({ selector: 'app-diagram', @@ -89,18 +88,14 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit { this.diagramType = diagramType || getDiagramTypeFromXml(xml); this.xml = xml; this.initializeModeler(diagramType); + return this.zone.run(() => { - if (xml) { - this.modeler.importXML(xml, (e, w) => this.onImport(e, w)); - } else { - if (this.modeler.createDiagram) { - this.modeler.createDiagram((e, w) => this.onImport(e, w)); - } else { - const r = 'REPLACE_ME'; - const newXml = DMN_DIAGRAM_EMPTY.replace(/REPLACE_ME/gi, () => uuidv4().slice(0, 7)); - this.modeler.importXML(newXml, (e, w) => this.onImport(e, w)); - } + if (!xml) { + const defaultXml = diagramType === FileType.DMN ? DMN_DIAGRAM_DEFAULT : BPMN_DIAGRAM_DEFAULT; + xml = defaultXml.replace(/REPLACE_ME/gi, () => this.getRandomString(7)); } + + this.modeler.importXML(xml, (e, w) => this.onImport(e, w)); }); } @@ -174,6 +169,11 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit { this.modeler.on('import.done', ({error}) => { if (!error) { this.modeler.get('canvas').zoom('fit-viewport'); + window.scrollTo({ + top: 0, + left: 0, + behavior: 'smooth', + }); } }); } @@ -197,6 +197,11 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit { this.modeler.on('import.done', ({error}) => { if (!error) { this.modeler.getActiveViewer().get('canvas').zoom('fit-viewport'); + window.scrollTo({ + top: 0, + left: 0, + behavior: 'smooth', + }); } }); } @@ -207,4 +212,8 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit { e.innerHTML = ''; }); } + + private getRandomString(len: number): string { + return uuidv4().slice(0, len); + } } diff --git a/src/app/file-list/file-list.component.spec.ts b/src/app/file-list/file-list.component.spec.ts index 3dd3a5f..e4b6b4f 100644 --- a/src/app/file-list/file-list.component.spec.ts +++ b/src/app/file-list/file-list.component.spec.ts @@ -2,6 +2,7 @@ import {HttpClientTestingModule, HttpTestingController} from '@angular/common/ht import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {MatIconModule} from '@angular/material/icon'; import {MatListModule} from '@angular/material/list'; +import {RouterTestingModule} from '@angular/router/testing'; import { ApiService, FileType, @@ -10,6 +11,7 @@ import { mockFileMetas, mockWorkflowSpec0 } from 'sartography-workflow-lib'; +import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe'; import {FileListComponent} from './file-list.component'; describe('FileListComponent', () => { @@ -23,8 +25,10 @@ describe('FileListComponent', () => { HttpClientTestingModule, MatIconModule, MatListModule, + RouterTestingModule, ], declarations: [ + GetIconCodePipe, FileListComponent ], providers: [ diff --git a/src/app/file-meta-dialog/file-meta-dialog.component.html b/src/app/file-meta-dialog/file-meta-dialog.component.html index 4586ea5..aceb3d2 100644 --- a/src/app/file-meta-dialog/file-meta-dialog.component.html +++ b/src/app/file-meta-dialog/file-meta-dialog.component.html @@ -1,22 +1,13 @@
- - - - - - - - - - +
- +
diff --git a/src/app/file-meta-dialog/file-meta-dialog.component.spec.ts b/src/app/file-meta-dialog/file-meta-dialog.component.spec.ts index b3ef894..88e26ce 100644 --- a/src/app/file-meta-dialog/file-meta-dialog.component.spec.ts +++ b/src/app/file-meta-dialog/file-meta-dialog.component.spec.ts @@ -4,6 +4,7 @@ import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from '@angular/material/ import {MatFormFieldModule} from '@angular/material/form-field'; import {MatInputModule} from '@angular/material/input'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {FileType} from 'sartography-workflow-lib'; import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data'; import {FileMetaDialogComponent} from './file-meta-dialog.component'; @@ -52,10 +53,7 @@ describe('EditFileMetaDialogComponent', () => { const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); const dataBefore: FileMetaDialogData = { fileName: 'green_eggs.bpmn', - workflowSpecId: 'green_eggs', - name: 'green_eggs', - displayName: 'Green Eggs', - description: 'Eat them! Eat them! Here they are.', + fileType: FileType.BPMN, }; component.data = dataBefore; @@ -67,10 +65,7 @@ describe('EditFileMetaDialogComponent', () => { const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); const dataBefore: FileMetaDialogData = { fileName: 'and_ham.bpmn', - workflowSpecId: 'and_ham', - name: 'and_hame', - displayName: 'And Ham', - description: 'Would you, could you, in a box?', + fileType: FileType.BPMN, }; component.data = dataBefore; @@ -82,10 +77,7 @@ describe('EditFileMetaDialogComponent', () => { const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); const dataBefore: FileMetaDialogData = { fileName: ' 🍳 green_eggs.v1-2020-01-01.XML.bmnp 🍖 ', - workflowSpecId: 'green_eggs', - name: 'green_eggs', - displayName: 'Green Eggs', - description: 'Eat them! Eat them! Here they are.', + fileType: FileType.BPMN, }; component.data = dataBefore; @@ -94,21 +86,4 @@ describe('EditFileMetaDialogComponent', () => { expectedData.fileName = 'green_eggs.v1-2020-01-01.XML.bpmn'; expect(closeSpy).toHaveBeenCalledWith(expectedData); }); - - it('should clean up workflow spec id', () => { - const closeSpy = spyOn(component.dialogRef, 'close').and.stub(); - const dataBefore: FileMetaDialogData = { - fileName: 'green_eggs.bpmn', - workflowSpecId: ' 🍳 Green Eggs & Ham: A Dish Best Served Cold? 🍖 ', - name: 'green_eggs', - displayName: 'Green Eggs', - description: 'I would not, could not, with a fox!', - }; - - component.data = dataBefore; - component.onSubmit(); - const expectedData: FileMetaDialogData = JSON.parse(JSON.stringify(dataBefore)); - expectedData.workflowSpecId = 'green_eggs_ham_a_dish_best_served_cold'; - expect(closeSpy).toHaveBeenCalledWith(dataBefore); - }); }); diff --git a/src/app/file-meta-dialog/file-meta-dialog.component.ts b/src/app/file-meta-dialog/file-meta-dialog.component.ts index 803bc2a..173c647 100644 --- a/src/app/file-meta-dialog/file-meta-dialog.component.ts +++ b/src/app/file-meta-dialog/file-meta-dialog.component.ts @@ -21,8 +21,7 @@ export class FileMetaDialogComponent { } onSubmit() { - this.data.workflowSpecId = toSnakeCase(this.data.workflowSpecId); - this.data.fileName = cleanUpFilename(this.data.fileName, 'bpmn'); + this.data.fileName = cleanUpFilename(this.data.fileName, this.data.fileType); this.dialogRef.close(this.data); } diff --git a/src/app/modeler/modeler.component.html b/src/app/modeler/modeler.component.html index 1f76c89..5c0d73f 100644 --- a/src/app/modeler/modeler.component.html +++ b/src/app/modeler/modeler.component.html @@ -1,4 +1,12 @@ + + + {{workflowSpec.display_name}} + ({{workflowSpec.name}}) + - @@ -82,7 +90,13 @@ - + diff --git a/src/app/modeler/modeler.component.scss b/src/app/modeler/modeler.component.scss index 98ae427..3a76a74 100644 --- a/src/app/modeler/modeler.component.scss +++ b/src/app/modeler/modeler.component.scss @@ -22,11 +22,11 @@ mat-form-field { mat-toolbar { transition: all 200ms ease-in-out; - height: 64px; + height: 128px; } mat-toolbar.expanded { - height: 128px; + height: 192px; } ::ng-deep .tooltip-text { diff --git a/src/app/modeler/modeler.component.spec.ts b/src/app/modeler/modeler.component.spec.ts index cdb8ade..cd56b5f 100644 --- a/src/app/modeler/modeler.component.spec.ts +++ b/src/app/modeler/modeler.component.spec.ts @@ -13,7 +13,8 @@ import {MatToolbarModule} from '@angular/material/toolbar'; import {MatTooltipModule} from '@angular/material/tooltip'; import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; import {BrowserAnimationsModule, NoopAnimationsModule} from '@angular/platform-browser/animations'; -import {of} from 'rxjs'; +import {ActivatedRoute, convertToParamMap} from '@angular/router'; +import {Observable, of} from 'rxjs'; import { ApiService, FileMeta, @@ -27,6 +28,7 @@ import { import {BPMN_DIAGRAM, BPMN_DIAGRAM_WITH_WARNINGS} from '../../testing/mocks/diagram.mocks'; import {BpmnWarning} from '../_interfaces/bpmn-warning'; import {FileMetaDialogData} from '../_interfaces/file-meta-dialog-data'; +import {GetIconCodePipe} from '../_pipes/get-icon-code.pipe'; import {DiagramComponent} from '../diagram/diagram.component'; import {FileMetaDialogComponent} from '../file-meta-dialog/file-meta-dialog.component'; import {ModelerComponent} from './modeler.component'; @@ -40,6 +42,7 @@ describe('ModelerComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ + GetIconCodePipe, ModelerComponent, DiagramComponent, FileMetaDialogComponent, @@ -70,6 +73,12 @@ describe('ModelerComponent', () => { } }, {provide: MAT_DIALOG_DATA, useValue: []}, + {provide: ActivatedRoute, useValue: { + paramMap: of(convertToParamMap({ + workflowSpecId: mockWorkflowSpec0.id, + fileMetaId: `${mockFileMeta0.id}` + })) + }} ] }).overrideModule(BrowserDynamicTestingModule, {set: {entryComponents: [FileMetaDialogComponent]}}) .compileComponents(); @@ -198,7 +207,7 @@ describe('ModelerComponent', () => { }); it('should get the diagram file name', () => { - expect(component.getFileName()).toEqual('No file selected'); + expect(component.getFileName()).toEqual(mockFileMeta0.name); const filename = 'expected_file_name.jpg'; component.diagramFile = new File([], filename, {type: 'image/jpeg'}); @@ -261,10 +270,7 @@ describe('ModelerComponent', () => { it('should open file metadata dialog', () => { const data: FileMetaDialogData = { fileName: 'after', - workflowSpecId: 'after', - name: 'after', - description: 'after', - displayName: 'after', + fileType: FileType.BPMN, }; const upsertSpy = spyOn(component, '_upsertSpecAndFileMeta').and.stub(); @@ -275,14 +281,11 @@ describe('ModelerComponent', () => { expect(upsertSpy).toHaveBeenCalledWith(data); }); - it('should update spec and file metadata for existing file', () => { + it('should update file metadata for existing file', () => { const newXml = 'New Value'; const data: FileMetaDialogData = { fileName: mockFileMeta0.name, - workflowSpecId: mockWorkflowSpec0.id, - name: mockWorkflowSpec0.name, - description: mockWorkflowSpec0.description, - displayName: mockWorkflowSpec0.display_name, + fileType: FileType.BPMN, }; const updateWorkflowSpecificationSpy = spyOn(component.api, 'updateWorkflowSpecification') .and.returnValue(of(mockWorkflowSpec0)); @@ -310,14 +313,11 @@ describe('ModelerComponent', () => { expect(snackBarSpy).toHaveBeenCalled(); }); - it('should create new spec and file metadata for new file', () => { + it('should create new file metadata for new file', () => { const newXml = 'New Value'; const data: FileMetaDialogData = { fileName: mockFileMeta0.name, - workflowSpecId: mockWorkflowSpec0.id, - name: mockWorkflowSpec0.id, - description: mockWorkflowSpec0.description, - displayName: mockWorkflowSpec0.display_name, + fileType: FileType.BPMN, }; const noDateOrVersion: FileMeta = { diff --git a/src/app/modeler/modeler.component.ts b/src/app/modeler/modeler.component.ts index cce55a5..71ffd1c 100644 --- a/src/app/modeler/modeler.component.ts +++ b/src/app/modeler/modeler.component.ts @@ -33,6 +33,9 @@ export class ModelerComponent implements AfterViewInit { private xml = ''; private draftXml = ''; @ViewChild(DiagramComponent, {static: false}) private diagramComponent: DiagramComponent; + private diagramType: FileType; + private workflowSpecId: string; + private fileMetaId: number; constructor( private api: ApiService, @@ -40,7 +43,24 @@ export class ModelerComponent implements AfterViewInit { public dialog: MatDialog, private route: ActivatedRoute, ) { - this.loadFilesFromDb(); + + this.route.queryParams.subscribe(q => { + if (q && q.action) { + if (q.action === 'openFile') { + this.expandToolbar = true; + this.openMethod = 'file'; + } else if (q.action === 'newFile') { + + } + } + }) + + this.route.paramMap.subscribe(paramMap => { + console.log('paramMap', paramMap); + this.workflowSpecId = paramMap.get('workflowSpecId'); + this.fileMetaId = parseInt(paramMap.get('fileMetaId'), 10); + this.loadFilesFromDb(); + }); } ngAfterViewInit(): void { @@ -89,7 +109,7 @@ export class ModelerComponent implements AfterViewInit { } getFileName() { - return this.diagramFile ? this.diagramFile.name : 'No file selected'; + return this.diagramFile ? this.diagramFile.name : this.fileName || 'No file selected'; } onFileSelected($event: Event) { @@ -99,9 +119,9 @@ export class ModelerComponent implements AfterViewInit { // Arrow function here preserves this context onLoad = (event: ProgressEvent) => { this.xml = (event.target as FileReader).result.toString(); - const diagramType = this.diagramFileMeta ? this.diagramFileMeta.type : getDiagramTypeFromXml(this.xml); + const diagramType = getDiagramTypeFromXml(this.xml); this.diagramComponent.openDiagram(this.xml, diagramType); - }; + } readFile(file: File) { // FileReader must be instantiated this way so unit test can spy on it. @@ -139,6 +159,7 @@ export class ModelerComponent implements AfterViewInit { this.fileName = ''; this.diagramFileMeta = undefined; this.diagramFile = undefined; + this.diagramType = diagramType; this.diagramComponent.openDiagram(undefined, diagramType); } @@ -148,16 +169,14 @@ export class ModelerComponent implements AfterViewInit { height: '400px', width: '400px', data: { - fileName: this.diagramFileMeta ? this.diagramFileMeta.name : '', - workflowSpecId: this.diagramFileMeta ? this.diagramFileMeta.workflow_spec_id : '', - description: this.workflowSpec ? this.workflowSpec.description : '', - displayName: this.workflowSpec ? this.workflowSpec.display_name : '', + fileName: this.diagramFile ? this.diagramFile.name : this.fileName || '', + fileType: getDiagramTypeFromXml(this.xml), }, }); dialogRef.afterClosed().subscribe((data: FileMetaDialogData) => { - if (data && data.fileName && data.workflowSpecId) { - this._upsertSpecAndFileMeta(data); + if (data && data.fileName) { + this._upsertFileMeta(data); } }); } @@ -167,12 +186,9 @@ export class ModelerComponent implements AfterViewInit { } getFileMetaDisplayString(fileMeta: FileMeta) { - const spec = this.getWorkflowSpec(fileMeta.workflow_spec_id); - - if (spec) { - const specName = spec.id + ' - ' + spec.name + ' - ' + spec.display_name; + if (fileMeta) { const lastUpdated = new DatePipe('en-us').transform(fileMeta.last_updated); - return `${specName} (${fileMeta.name}) - v${fileMeta.version} (${lastUpdated})`; + return `${fileMeta.name} - v${fileMeta.version} (${lastUpdated})`; } else { return 'Loading...'; } @@ -198,89 +214,62 @@ export class ModelerComponent implements AfterViewInit { } private loadFilesFromDb() { - - this.route.paramMap.subscribe(paramMap => { - const workflowSpecId = paramMap.get('workflowSpecId'); - const fileMetaId = parseInt(paramMap.get('fileMetaId'), 10); - - console.log('workflowSpecId', workflowSpecId); - console.log('fileMetaId', fileMetaId); - - this.api.getWorkflowSpecList().subscribe(wfs => { + this.api.getWorkflowSpecList().subscribe(wfs => { this.workflowSpecs = wfs; this.workflowSpecs.forEach(w => { - if (w.id === workflowSpecId) { + if (w.id === this.workflowSpecId) { this.workflowSpec = w; - } - this.api.listBpmnFiles(w.id).subscribe(files => { - this.bpmnFiles = []; - files.forEach(f => { - this.api.getFileData(f.id).subscribe(d => { - if ((f.type === FileType.BPMN) || (f.type === FileType.DMN)) { - f.content_type = 'text/xml'; - f.file = new File([d], f.name, {type: f.content_type}); - this.bpmnFiles.push(f); + this.api.listBpmnFiles(w.id).subscribe(files => { + this.bpmnFiles = []; + files.forEach(f => { + this.api.getFileData(f.id).subscribe(d => { + if ((f.type === FileType.BPMN) || (f.type === FileType.DMN)) { + f.content_type = 'text/xml'; + f.file = new File([d], f.name, {type: f.content_type}); + this.bpmnFiles.push(f); - if (f.id === fileMetaId) { - this.diagramFileMeta = f; - this.diagramFile = f.file; - this.onSubmitFileToOpen(); + if (f.id === this.fileMetaId) { + this.diagramFileMeta = f; + this.diagramFile = f.file; + this.onSubmitFileToOpen(); + } } - } + }); }); }); - }); + } }); }); - }); } - private _upsertSpecAndFileMeta(data: FileMetaDialogData) { - if (data.fileName && data.workflowSpecId) { + private _upsertFileMeta(data: FileMetaDialogData) { + if (data.fileName) { this.xml = this.draftXml; // Save old workflow spec id, if user wants to change it const specId = this.workflowSpec ? this.workflowSpec.id : undefined; - - this.workflowSpec = { - id: data.workflowSpecId, - name: data.name, - display_name: data.displayName, - description: data.description, - }; - const fileMetaId = this.diagramFileMeta ? this.diagramFileMeta.id : undefined; + const fileType = this.diagramFileMeta ? this.diagramFileMeta.type : FileType.BPMN; this.diagramFileMeta = { id: fileMetaId, content_type: 'text/xml', name: data.fileName, - type: FileType.BPMN, + type: fileType, file: new File([this.xml], data.fileName, {type: 'text/xml'}), - workflow_spec_id: data.workflowSpecId, + workflow_spec_id: this.workflowSpec.id, }; - const newSpec: WorkflowSpec = { - id: data.workflowSpecId, - name: data.name, - display_name: data.displayName, - description: data.description, - }; - - if (specId) { - // Update existing workflow spec and file - this.api.updateWorkflowSpecification(specId, newSpec).subscribe(spec => { - this.api.updateFileMeta(specId, this.diagramFileMeta).subscribe(fileMeta => { - this.loadFilesFromDb(); - this.snackBar.open('Saved changes to workflow spec and file.', 'Ok', {duration: 5000}); - }); + if (specId && fileMetaId) { + // Update existing file meta + this.api.updateFileMeta(specId, this.diagramFileMeta).subscribe(fileMeta => { + this.loadFilesFromDb(); + this.snackBar.open('Saved changes to workflow spec and file.', 'Ok', {duration: 5000}); }); } else { - // Add new workflow spec and file - this.api.addWorkflowSpecification(newSpec).subscribe(spec => { - this.api.addFileMeta(newSpec.id, this.diagramFileMeta).subscribe(fileMeta => { - this.loadFilesFromDb(); - this.snackBar.open('Saved new workflow spec and file.', 'Ok', {duration: 5000}); - }); + // Add new file meta + this.api.addFileMeta(specId, this.diagramFileMeta).subscribe(fileMeta => { + this.loadFilesFromDb(); + this.snackBar.open('Saved new workflow spec and file.', 'Ok', {duration: 5000}); }); } }