import {
OnInit,
Component,
OnDestroy,
ViewChild,
ViewChildren,
ElementRef,
AfterContentInit,
SimpleChanges,
EventEmitter,
OnChanges
} from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { FlowChartService } from '../flow-chart/flow-chart.service';
import { IFlowChart } from 'app/shared/model/bizzrlCore/flow-chart.model';
import { Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import * as _ from 'lodash';
import * as customElementsData from './custom-elements.json';
import { JhiAlertService, JhiDataUtils } from 'ng-jhipster';
import * as BpmnJS from 'bpmn-js/dist/bpmn-modeler.development.js';
import BpmnModeler from 'bpmn-js/dist/bpmn-modeler.development.js';
import InjectionNames from 'bpmn-js/dist/bpmn-modeler.development.js';
import OriginalPaletteProvider from 'bpmn-js/dist/bpmn-modeler.development.js';
import BpmnPalletteModule from 'bpmn-js/lib/features/palette';
import gridModule from 'diagram-js/lib/features/grid-snapping';
import propertiesPanelModule from 'bpmn-js-properties-panel';
import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda';
import * as camundaModdleDescriptor from 'camunda-bpmn-moddle/resources/camunda.json';
@Component({
selector: 'jhi-view-diagram-component',
templateUrl: './view-diagram-component.html',
styleUrls: ['./view-diagram-component.scss']
})
export class ViewDiagramComponent implements OnInit, OnDestroy, AfterContentInit, OnChanges {
flowChartFindSubscription: Subscription;
flowChard: IFlowChart;
error: Error;
isChartLoading = false;
private bpmnDiagramViewer: BpmnJS;
private diagramModeler: BpmnModeler;
private diagramElemRegistry;
private diagramElemRegistryString;
private isElementRegistryDisp = false;
private isShowChangesOn = false;
private isEnableEvents = false;
private eventEnableStatus = 'Events Turned OFF';
private eventBus;
private importDone: EventEmitter<any> = new EventEmitter();
previousRoute: string;
@ViewChild('ref', { static: false }) private el: ElementRef;
@ViewChild('refProps', { static: false }) private elProps: ElementRef;
constructor(
protected activatedRoute: ActivatedRoute,
private router: Router,
private flowChartService: FlowChartService,
protected alertService: JhiAlertService
) {
console.log('json :', customElementsData);
this.bpmnDiagramViewer = new BpmnJS();
this.diagramModeler = new BpmnModeler({
keyboard: { bindTo: document },
BpmnPalletteModule,
propertiesPanel: {
parent: this.elProps
},
additionalModules: [
gridModule,
propertiesPanelModule,
propertiesProviderModule,
{ [InjectionNames.originalPaletteProvider]: ['type', OriginalPaletteProvider] }
],
moddleExtensions: { camunda: camundaModdleDescriptor }
});
/**
* propertiesPanel: { parent: this.elProps },
*/
console.log('diagramModeler is initalized properly..', this.diagramModeler);
this.diagramModeler.on('import.done', ({ error, warnings }) => {
console.log('Import Done event successfully emitted');
if (!error) {
console.log('Canvas Fit-viewport fired', warnings);
this.diagramModeler.get('canvas').zoom('fit-viewport');
this.diagramModeler.attachTo(this.el.nativeElement);
console.log('this.el.nativeElement::', this.el.nativeElement);
const propsPanel = this.diagramModeler.get('propertiesPanel');
console.log('propsPanel ', propsPanel);
propsPanel.attachTo(this.elProps.nativeElement);
// later attach events here as well as button click
this.onEnableEvents();
}
});
}
ngOnInit() {
this.isChartLoading = true;
let flowChardId = 0;
this.activatedRoute.params.subscribe((routerParams: Params) => {
flowChardId = +routerParams['id'];
console.log('RouterParams Params...', routerParams);
});
if (flowChardId != null) {
this.flowChartFindSubscription = this.flowChartService
.find(flowChardId)
.pipe(
map(httpResponse => {
let responseFlowChart: IFlowChart = null;
responseFlowChart = httpResponse.body;
console.log('Raw BPMN Diagram (transformation began...) ::', responseFlowChart.xmlPayload);
responseFlowChart.xmlPayload = _.unescape(atob(responseFlowChart.xmlPayload));
return responseFlowChart;
})
)
.subscribe(
responseIFlowChart => {
console.log(responseIFlowChart);
this.flowChard = responseIFlowChart;
console.log('BPMN Diagram (transformed) ::', this.flowChard.xmlPayload);
// attach BpmnJS instance to DOM element
if (this.flowChard.xmlPayload != null && this.flowChard.xmlPayload.length > 0) {
// this.bpmnDiagramViewer.importXML(this.flowChard.xmlPayload, function(err, warnings) {
this.diagramModeler.importXML(
this.flowChard.xmlPayload,
err => {
console.log('diagramModeler loading error :' + err);
this.importDone.emit({
type: 'error',
error: err
});
},
warnings => {
console.log('diagramModeler loaded with warning :', warnings);
this.importDone.emit({
type: 'success',
warning: warnings
});
}
);
}
},
Error => {
this.error = Error;
this.isChartLoading = false;
}
);
}
this.isChartLoading = false;
} // end of ngInit
ngOnDestroy() {
if (this.flowChartFindSubscription != null) {
this.flowChartFindSubscription.unsubscribe();
}
// destroy BpmnJS instance
if (this.bpmnDiagramViewer != null) {
this.bpmnDiagramViewer.destroy();
}
if (null != this.diagramModeler) {
this.diagramModeler.destroy();
}
}
ngAfterContentInit() {
// attach BpmnJS instance to DOM element
console.log('ngAfterContentInit Fired..');
if (this.diagramModeler != null && null != this.el) {
console.log('attaching diagramModeler to element ', this.diagramModeler);
this.diagramModeler.attachTo(this.el.nativeElement);
}
}
ngOnChanges(changes: SimpleChanges) {
// re-import whenever the diagram changes. not working thats different issue to fix
console.log('Simple Changes fired onChanges chjages=', changes);
this.refreshDiagram();
}
refreshDiagram() {
if (null != this.flowChard && this.flowChard.xmlPayload != null && this.flowChard.xmlPayload.length > 0) {
this.diagramModeler.destroy();
// this.bpmnDiagramViewer.importXML(this.flowChard.xmlPayload, function(err, warnings) {
this.diagramModeler.importXML(
this.flowChard.xmlPayload,
err => {
console.log('diagramModeler loading error :' + err);
this.importDone.emit({
type: 'error',
error: err
});
},
warnings => {
console.log('diagramModeler loaded with warning :', warnings);
this.importDone.emit({
type: 'success',
warning: warnings
});
}
);
}
}
onEnableEvents() {
this.isEnableEvents = !this.isEnableEvents;
if (null != this.diagramModeler) {
if (this.isEnableEvents) {
this.eventEnableStatus = 'Events Turned ON';
if (null == this.eventBus) {
this.eventBus = this.diagramModeler.get('eventBus');
console.log('Event Bus ::', this.eventBus);
}
const events = ['element.dblclick'];
/**, 'element.click', 'element.changed']; */
events.forEach(event => {
console.log('Event Bus inside forEach ::', this.eventBus);
this.eventBus.on(event, function(elem) {
console.log(event + ' on ' + elem.element.type);
if (elem.element.type === 'bpmn:BusinessRuleTask') {
alert('Would like to Author Rules ?');
}
});
});
} else {
this.eventEnableStatus = 'Events Turned OFF';
}
}
}
onSaveDiagram() {
if (null != this.bpmnDiagramViewer) {
this.isChartLoading = true;
this.diagramModeler.saveXML({ format: true }, (err, updatedXML) => {
this.callSaveService(updatedXML);
});
this.isChartLoading = false;
}
}
callSaveService(updatedXML) {
const togoXml = btoa(
_.escape(updatedXML).replace(
// TODO - Figure out y without this its not working
/[\u00a0-\u2666]/g,
c => {
return '&#' + c.charCodeAt(0) + ';';
}
)
);
this.flowChartService
.update({
id: this.flowChard.id,
name: this.flowChard.name,
xmlPayloadContentType: this.flowChard.xmlPayloadContentType,
xmlPayloadId: this.flowChard.xmlPayloadId,
xmlPayload: togoXml
})
.subscribe(value => this.saveSuccess(value), error => this.saveError(error));
}
saveSuccess(value) {
// Do after success stuff
if (null != value) {
if (value.statusText === 'OK') {
this.alertService.success('Diagram Successfully Saved', null, null);
} else {
this.alertService.warning('Something seems wnt wrong!!', null, null);
}
}
console.log('Save Success ::', value);
}
saveError(error) {
// Do after error stuff
this.alertService.error('Something seems wnt wrong!!', null, null);
console.log('Save Error ::', error);
}
onElementRegistry() {
if (this.diagramModeler != null) {
this.diagramElemRegistry = this.diagramModeler.get('elementRegistry');
this.diagramElemRegistryString = JSON.stringify(this.diagramElemRegistry);
console.log('Element Registry :: ', this.diagramElemRegistry);
this.isElementRegistryDisp = !this.isElementRegistryDisp;
}
}
onShowChanges() {
this.isShowChangesOn = !this.isShowChangesOn;
let changes = { stroke: 'green', fill: 'yellow' };
if (this.isShowChangesOn) {
changes = { stroke: 'green', fill: 'yellow' };
} else {
changes = { stroke: 'black', fill: 'white' };
}
if (null == this.diagramElemRegistry) {
this.diagramElemRegistry = this.diagramModeler.get('elementRegistry');
}
const modeling = this.diagramModeler.get('modeling');
const selectPizzaTask = this.diagramElemRegistry.get('_6-74');
const orderPizzaTask = this.diagramElemRegistry.get('_6-127');
console.log('selectPizzaTas ::', selectPizzaTask);
console.log('orderPizzaTask ::', orderPizzaTask);
console.log('modeling ', modeling);
const changElements = [selectPizzaTask, orderPizzaTask];
modeling.setColor(changElements, changes);
}
onCancelDiagram() {
console.log('moving back to parent component');
const params = { id: null };
this.router.navigate([], { queryParams: params });
}
}