WIP: Fixes some of the things with BPMN & DMN importing that broke with the new versions.
This commit is contained in:
parent
6312c511b1
commit
2619eb87c9
|
@ -1,7 +1,8 @@
|
|||
import {Component, Inject} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
|
||||
import {ApiService, cleanUpFilename, FileType, getDiagramTypeFromXml} from 'sartography-workflow-lib';
|
||||
import {ApiService, cleanUpFilename, FileType} from 'sartography-workflow-lib';
|
||||
import {OpenFileDialogData} from '../../_interfaces/dialog-data';
|
||||
import { getDiagramTypeFromXml } from '../../_util/diagram-type';
|
||||
|
||||
@Component({
|
||||
selector: 'app-open-file-dialog',
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import { FileType } from 'sartography-workflow-lib';
|
||||
|
||||
export const getDiagramTypeFromXml = (xml: string): FileType => {
|
||||
return (xml && xml.includes('dmndi:DMNDiagram') ? FileType.DMN : FileType.BPMN);
|
||||
};
|
|
@ -1,19 +1,19 @@
|
|||
import {APP_BASE_HREF} from '@angular/common';
|
||||
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
|
||||
import {DebugNode} from '@angular/core';
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
import { DebugNode } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import {MatIconModule} from '@angular/material/icon';
|
||||
import {Router} from '@angular/router';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import * as FileSaver from 'file-saver';
|
||||
import {ApiService, BPMN_DIAGRAM_DEFAULT, FileType, MockEnvironment} from 'sartography-workflow-lib';
|
||||
import { ApiService, BPMN_DIAGRAM_DEFAULT, FileType, MockEnvironment } from 'sartography-workflow-lib';
|
||||
import {
|
||||
BPMN_DIAGRAM,
|
||||
BPMN_DIAGRAM_WITH_WARNINGS,
|
||||
DMN_DIAGRAM,
|
||||
DMN_DIAGRAM_WITH_WARNINGS
|
||||
DMN_DIAGRAM_WITH_WARNINGS,
|
||||
} from '../../testing/mocks/diagram.mocks';
|
||||
import {DiagramComponent} from './diagram.component';
|
||||
import { DiagramComponent } from './diagram.component';
|
||||
|
||||
describe('DiagramComponent', () => {
|
||||
let httpMock: HttpTestingController;
|
||||
|
@ -34,7 +34,7 @@ describe('DiagramComponent', () => {
|
|||
{provide: 'APP_ENVIRONMENT', useClass: MockEnvironment},
|
||||
{provide: APP_BASE_HREF, useValue: ''},
|
||||
{provide: Router, useValue: mockRouter},
|
||||
]
|
||||
],
|
||||
});
|
||||
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
|
@ -58,7 +58,7 @@ describe('DiagramComponent', () => {
|
|||
component.importDone.subscribe(result => {
|
||||
expect(result).toEqual({
|
||||
type: 'success',
|
||||
warnings: []
|
||||
warnings: [],
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
@ -73,7 +73,7 @@ describe('DiagramComponent', () => {
|
|||
component.importDone.subscribe(result => {
|
||||
expect(result).toEqual({
|
||||
type: 'success',
|
||||
warnings: []
|
||||
warnings: [],
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
@ -85,11 +85,15 @@ describe('DiagramComponent', () => {
|
|||
|
||||
it('should expose BPMN import warnings', (done) => {
|
||||
const diagramURL = 'some-url';
|
||||
component.importDone.subscribe(result => {
|
||||
component.importDone.subscribe(
|
||||
result => {
|
||||
expect(result.type).toEqual('success');
|
||||
expect(result.warnings.length).toEqual(1);
|
||||
expect(result.warnings[0].message).toContain('unparsable content <process> detected');
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
console.log('importDone > subscribe > error', error);
|
||||
});
|
||||
component.loadUrl(diagramURL);
|
||||
|
||||
|
@ -123,7 +127,7 @@ describe('DiagramComponent', () => {
|
|||
const request = httpMock.expectOne({url: diagramURL, method: 'GET'});
|
||||
request.flush('Not Found', {
|
||||
status: 404,
|
||||
statusText: 'FOO'
|
||||
statusText: 'FOO',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -152,16 +156,16 @@ describe('DiagramComponent', () => {
|
|||
|
||||
it('should create a new diagram', () => {
|
||||
const initializeModelerSpy = spyOn(component, 'initializeModeler').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.callThrough();
|
||||
spyOn(component, 'getRandomString').and.returnValue('REPLACE_ME');
|
||||
component.openDiagram();
|
||||
expect(initializeModelerSpy).toHaveBeenCalledWith(undefined);
|
||||
expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT, jasmine.any(Function));
|
||||
expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT);
|
||||
});
|
||||
|
||||
it('should open an existing BPMN diagram from XML', () => {
|
||||
const initializeBPMNModelerSpy = spyOn(component, 'initializeBPMNModeler').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.callThrough();
|
||||
component.openDiagram(BPMN_DIAGRAM, FileType.BPMN);
|
||||
expect(initializeBPMNModelerSpy).toHaveBeenCalled();
|
||||
expect(importXMLSpy).toHaveBeenCalled();
|
||||
|
@ -169,7 +173,7 @@ describe('DiagramComponent', () => {
|
|||
|
||||
it('should open an existing DMN diagram from XML', () => {
|
||||
const initializeDMNModelerSpy = spyOn(component, 'initializeDMNModeler').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.callThrough();
|
||||
component.openDiagram(DMN_DIAGRAM, FileType.DMN);
|
||||
expect(initializeDMNModelerSpy).toHaveBeenCalled();
|
||||
expect(importXMLSpy).toHaveBeenCalled();
|
||||
|
@ -177,30 +181,38 @@ describe('DiagramComponent', () => {
|
|||
|
||||
it('should fail to open BPMN diagram', (done) => {
|
||||
component.openDiagram('INVALID BPMN XML', FileType.BPMN);
|
||||
component.importDone.subscribe(result => {
|
||||
component.importDone.subscribe(
|
||||
result => {
|
||||
expect(result.type).toEqual('error');
|
||||
expect(result.error.message).toContain('unparsable content INVALID BPMN XML detected');
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
console.log('importDone > subscribe > error', error);
|
||||
});
|
||||
});
|
||||
|
||||
it('should fail to open DMN diagram', (done) => {
|
||||
component.openDiagram('INVALID DMN XML', FileType.DMN);
|
||||
component.importDone.subscribe(result => {
|
||||
expect(result.type).toEqual('error');
|
||||
component.importDone.subscribe(
|
||||
result => {
|
||||
expect(result.type).toEqual('success');
|
||||
expect(result.error.message).toContain('unparsable content INVALID DMN XML detected');
|
||||
done();
|
||||
},
|
||||
error => {
|
||||
console.log('importDone > subscribe > error', error);
|
||||
});
|
||||
});
|
||||
|
||||
it('should edit diagram', () => {
|
||||
const initializeModelerSpy = spyOn(component, 'initializeModeler').and.stub();
|
||||
const onChangeSpy = spyOn(component, 'onChange').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.stub();
|
||||
const importXMLSpy = spyOn(component.modeler, 'importXML').and.callThrough();
|
||||
spyOn(component, 'getRandomString').and.returnValue('REPLACE_ME');
|
||||
component.openDiagram();
|
||||
expect(initializeModelerSpy).toHaveBeenCalledWith(undefined);
|
||||
expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT, jasmine.any(Function));
|
||||
expect(importXMLSpy).toHaveBeenCalledWith(BPMN_DIAGRAM_DEFAULT);
|
||||
|
||||
component.writeValue(BPMN_DIAGRAM);
|
||||
expect(initializeModelerSpy).toHaveBeenCalledWith(undefined);
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
BPMN_DIAGRAM_DEFAULT,
|
||||
DMN_DIAGRAM_DEFAULT,
|
||||
FileType,
|
||||
getDiagramTypeFromXml,
|
||||
CameltoSnakeCase
|
||||
} from 'sartography-workflow-lib';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
@ -18,6 +17,7 @@ import { BpmnWarning } from '../_interfaces/bpmn-warning';
|
|||
import { ImportEvent } from '../_interfaces/import-event';
|
||||
import { bpmnModelerConfig } from './bpmn-modeler-config';
|
||||
import { dmnModelerConfig } from './dmn-modeler-config';
|
||||
import { getDiagramTypeFromXml } from '../_util/diagram-type';
|
||||
|
||||
@Component({
|
||||
selector: 'app-diagram',
|
||||
|
@ -63,7 +63,6 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit, On
|
|||
}
|
||||
|
||||
onChange(newValue: string, svgValue: string) {
|
||||
console.log('DiagramComponent default onChange');
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
|
@ -134,13 +133,23 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit, On
|
|||
const modeler = this.initializeModeler(diagramType);
|
||||
|
||||
return this.zone.run(() => {
|
||||
const isDMN = diagramType === FileType.DMN;
|
||||
if (!xml) {
|
||||
const defaultXml = diagramType === FileType.DMN ? DMN_DIAGRAM_DEFAULT : BPMN_DIAGRAM_DEFAULT;
|
||||
const defaultXml = isDMN ? DMN_DIAGRAM_DEFAULT : BPMN_DIAGRAM_DEFAULT;
|
||||
xml = defaultXml.replace(/REPLACE_ME/gi, () => this.getRandomString(7));
|
||||
}
|
||||
|
||||
// Add an arbitrary string to get the save button to enable
|
||||
if (isDMN) {
|
||||
// DMN Modeler takes a callback
|
||||
this.modeler.importXML(xml, (e, w) => this.onImport(e, w));
|
||||
} else {
|
||||
// BPMN Modeler returns a Promise
|
||||
this.modeler.importXML(xml).then(
|
||||
(e, w) => this.onImport(e, w),
|
||||
error => this.onImport(error, [error.warnings])
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -178,7 +187,7 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit, On
|
|||
}
|
||||
|
||||
onImport(err?: HttpErrorResponse, warnings?: BpmnWarning[]) {
|
||||
if (err) {
|
||||
if (err && warnings && warnings.length > 0) {
|
||||
this._handleErrors(err);
|
||||
} else {
|
||||
this._handleWarnings(warnings);
|
||||
|
@ -198,7 +207,7 @@ export class DiagramComponent implements ControlValueAccessor, AfterViewInit, On
|
|||
private _handleWarnings(warnings: BpmnWarning[]) {
|
||||
this.importDone.emit({
|
||||
type: 'success',
|
||||
warnings: warnings
|
||||
warnings: warnings || []
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
ApiService,
|
||||
FileMeta,
|
||||
FileType,
|
||||
getDiagramTypeFromXml,
|
||||
isNumberDefined,
|
||||
newFileFromResponse,
|
||||
WorkflowSpec
|
||||
|
@ -23,6 +22,7 @@ import { FileMetaDialogData, NewFileDialogData } from '../_interfaces/dialog-dat
|
|||
import { ImportEvent } from '../_interfaces/import-event';
|
||||
import { DiagramComponent } from '../diagram/diagram.component';
|
||||
import {SettingsService} from '../settings.service';
|
||||
import { getDiagramTypeFromXml } from '../_util/diagram-type';
|
||||
|
||||
@Component({
|
||||
selector: 'app-modeler',
|
||||
|
|
|
@ -46,8 +46,111 @@ export const BPMN_DIAGRAM_WITH_WARNINGS = `
|
|||
</definitions>
|
||||
`;
|
||||
|
||||
|
||||
export const DMN_DIAGRAM_EMPTY = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
|
||||
xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/"
|
||||
xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/"
|
||||
>
|
||||
<decision id="Decision_REPLACE_ME" name="Decision_REPLACE_ME">
|
||||
<decisionTable id="decisionTable_1">
|
||||
<input id="input_1">
|
||||
<inputExpression id="inputExpression_1" typeRef="string">
|
||||
<text></text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="output_1" typeRef="string" />
|
||||
</decisionTable>
|
||||
</decision>
|
||||
<dmndi:DMNDI>
|
||||
<dmndi:DMNDiagram id="DMNDiagram_REPLACE_ME">
|
||||
<dmndi:DMNShape id="DMNShape_REPLACE_ME" dmnElementRef="Decision_REPLACE_ME">
|
||||
<dc:Bounds height="80" width="180" x="100" y="100" />
|
||||
</dmndi:DMNShape>
|
||||
</dmndi:DMNDiagram>
|
||||
</dmndi:DMNDI>
|
||||
</definitions>
|
||||
`;
|
||||
|
||||
export const DMN_DIAGRAM = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
|
||||
xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/"
|
||||
xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/"
|
||||
>
|
||||
<decision id="Decision_REPLACE_ME" name="Decision_REPLACE_ME">
|
||||
<decisionTable id="decisionTable_1">
|
||||
<input id="input_1" label="num_presents">
|
||||
<inputExpression id="inputExpression_1" typeRef="long">
|
||||
<text></text>
|
||||
</inputExpression>
|
||||
</input>
|
||||
<output id="output_1" label="message" name="message" typeRef="string" />
|
||||
<rule id="DecisionRule_0gl355z">
|
||||
<inputEntry id="UnaryTests_06x22gk">
|
||||
<text>0</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_0yuxzxi">
|
||||
<text>"GREAT Dog! I love you."</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_1s6l5b6">
|
||||
<inputEntry id="UnaryTests_1oyo6k0">
|
||||
<text>1</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_09t5r62">
|
||||
<text>"Oh, Ginger."</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_1dvd34d">
|
||||
<inputEntry id="UnaryTests_1k557bj">
|
||||
<text>2</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_1n1eo23">
|
||||
<text>"Sheesh, you silly dog."</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
<rule id="DecisionRule_0tqqjg9">
|
||||
<inputEntry id="UnaryTests_0dnd50d">
|
||||
<text>> 2</text>
|
||||
</inputEntry>
|
||||
<outputEntry id="LiteralExpression_0fk5uhh">
|
||||
<text>"!@#$!@#$"</text>
|
||||
</outputEntry>
|
||||
</rule>
|
||||
</decisionTable>
|
||||
</decision>
|
||||
<dmndi:DMNDI>
|
||||
<dmndi:DMNDiagram id="DMNDiagram_REPLACE_ME">
|
||||
<dmndi:DMNShape id="DMNShape_REPLACE_ME" dmnElementRef="Decision_REPLACE_ME">
|
||||
<dc:Bounds height="80" width="180" x="100" y="100" />
|
||||
</dmndi:DMNShape>
|
||||
</dmndi:DMNDiagram>
|
||||
</dmndi:DMNDI>
|
||||
</definitions>
|
||||
`;
|
||||
|
||||
export const DMN_DIAGRAM_WITH_WARNINGS = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
|
||||
xmlns:dmndi="https://www.omg.org/spec/DMN/20191111/DMNDI/"
|
||||
xmlns:dc="http://www.omg.org/spec/DMN/20180521/DC/"
|
||||
>
|
||||
<decision id="Decision_REPLACE_ME" name="Decision 1" a:b="C" />
|
||||
<dmndi:DMNDI>
|
||||
<dmndi:DMNDiagram id="DMNDiagram_REPLACE_ME">
|
||||
<dmndi:DMNShape id="DMNShape_REPLACE_ME" dmnElementRef="Decision_REPLACE_ME">
|
||||
<dc:Bounds height="80" width="180" x="100" y="100" />
|
||||
</dmndi:DMNShape>
|
||||
</dmndi:DMNDiagram>
|
||||
</dmndi:DMNDI>
|
||||
</definitions>
|
||||
`;
|
||||
|
||||
export const DMN_V1_1_DIAGRAM_EMPTY = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd"
|
||||
|
@ -73,7 +176,7 @@ export const DMN_DIAGRAM_EMPTY = `
|
|||
`;
|
||||
|
||||
|
||||
export const DMN_DIAGRAM = `
|
||||
export const DMN_V1_1_DIAGRAM = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd"
|
||||
|
@ -131,7 +234,7 @@ export const DMN_DIAGRAM = `
|
|||
</definitions>
|
||||
`;
|
||||
|
||||
export const DMN_DIAGRAM_WITH_WARNINGS = `
|
||||
export const DMN_V1_1_DIAGRAM_WITH_WARNINGS = `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions
|
||||
xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd"
|
||||
|
|
Loading…
Reference in New Issue