relu-bpmn
Version:
RELU快速开发平台bpmn组件
737 lines (736 loc) • 36.7 kB
JavaScript
import { bpmnSequenceFlow, bpmnIncoming, bpmnOutgoing, bpmnInclusive, typeStart, typeTask, typeSubFlow, typeEnd, typeTrigger, typeEventTrigger, typeTimeTrigger, typeNoticeTrigger, typeWebhookTrigger, typeGetData, typeAddData, typeUpdateData, typeDelData, typeInterface, typeMessage, typeLaunchFlow, typeSchedule, typeProcessing, typeInclusion, } from '../config/variableName';
import { buildBitUUID } from '../utils/uuidUtil';
import { hasGatewayType, typeConfig } from '../config';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { getExternalLabelMid } from 'bpmn-js/lib/util/LabelUtil';
export class NodeUtils {
static isStartNode(node) {
return node && node?.type === typeStart;
}
static isApproverNode(node) {
return node && node?.type === typeTask;
}
static isProcessingNode(node) {
return node && node?.type === typeProcessing;
}
static isSubFlowNode(node) {
return node && node?.type === typeSubFlow;
}
static isInterflowNode(node) {
return node && node?.type === typeTask && node?.isInterflow;
}
static isConnectNode(node) {
return node && node?.type === bpmnSequenceFlow;
}
static isEndNode(node) {
return node && node?.type === typeEnd;
}
static isTriggerNode(node) {
return node && node?.type === typeTrigger;
}
static isEventTriggerNode(node) {
return node && node?.type === typeEventTrigger;
}
static isTimeTriggerNode(node) {
return node && node?.type === typeTimeTrigger;
}
static isNoticeTriggerNode(node) {
return node && node?.type === typeNoticeTrigger;
}
static isWebhookTriggerNode(node) {
return node && node?.type === typeWebhookTrigger;
}
static isGetDataNode(node) {
return node && node?.type === typeGetData;
}
static isAddDataNode(node) {
return node && node?.type === typeAddData;
}
static isUpdateDataNode(node) {
return node && node?.type === typeUpdateData;
}
static isDeleteDataNode(node) {
return node && node?.type === typeDelData;
}
static isDataInterfaceNode(node) {
return node && node?.type === typeInterface;
}
static isMessageNode(node) {
return node && node?.type === typeMessage;
}
static isLaunchFlowNode(node) {
return node && node?.type === typeLaunchFlow;
}
static isScheduleNode(node) {
return node && node?.type === typeSchedule;
}
static getPreNodeList(element) {
let preList = [];
if (!element || !element.incoming || !element.incoming.length)
return preList;
for (let i = 0; i < element.incoming.length; i++) {
const item = element.incoming[i];
preList.push(item.source);
}
return preList;
}
static getConditionsContent(conditions, matchLogic) {
let content = '';
for (let i = 0; i < conditions.length; i++) {
const e = conditions[i];
content += conditions.length == 1 ? '' : (i == 0 ? '' : ` ${matchLogic} `) + '( ';
for (let j = 0; j < e.groups.length; j++) {
const groups = e.groups[j];
const logic = j == 0 ? '' : ` ${e.logic} `;
const text = ` ${groups.fieldName} ${groups.symbolName}${groups.fieldLabel ? groups.fieldLabel : groups.fieldValue || groups.fieldValue === 0 ? groups.fieldValue : ''} `;
content += logic + text;
}
content += conditions.length == 1 ? '' : ' )';
}
return content;
}
static autoCreateGateWay(xml, elementRegistry, reluData) {
let parser = new DOMParser();
let xmlDoc = parser.parseFromString(xml, 'text/xml');
let process = xmlDoc.querySelector('#Process_1');
let plane = xmlDoc.querySelector('#BPMNPlane_1');
let divideList = [];
let confluenceList = [];
const allList = elementRegistry.getAll() || [];
allList.map((item) => {
let groupId = item?.businessObject?.$attrs?.customGroupId;
if (item.incoming?.length > 1 && !groupId)
confluenceList.push({ key: item.id, gatewayType: 'inclusion' });
if (item.outgoing && item.outgoing.length > 1 && !groupId) {
divideList.push({
key: item.id,
gatewayType: reluData.data[item.id]?.divideRule || 'inclusion',
});
}
});
if (divideList?.length) {
divideList.map((item) => {
let targetElement = xmlDoc.querySelector(`#${item.key}`);
if (targetElement) {
let targeChildren = targetElement.children;
let outgoingList = [];
let incomingList = [];
for (var i = 0; i < targeChildren.length; i++) {
if (targeChildren[i].nodeName === bpmnOutgoing) {
outgoingList.push(targeChildren[i]);
}
else {
incomingList.push(targeChildren[i]);
}
}
let gatewayElement = NodeUtils.createGateway(xmlDoc, item.gatewayType);
let gatewayId = 'Gateway_' + buildBitUUID();
let flowId = 'flow_' + buildBitUUID();
gatewayElement.setAttribute('id', gatewayId);
let flowElement = xmlDoc.createElement('bpmn2:sequenceFlow');
flowElement.setAttribute('id', flowId);
flowElement.setAttribute('sourceRef', item.key);
flowElement.setAttribute('targetRef', gatewayId);
let conditionExpression = xmlDoc.createElement('bpmn2:conditionExpression');
conditionExpression.setAttribute('xsi:type', 'bpmn2:tFormalExpression');
let testText = xmlDoc.createTextNode('${' + `${flowId}` + '}');
conditionExpression.appendChild(testText);
let childElement = xmlDoc.createElement(bpmnIncoming);
let textNode = xmlDoc.createTextNode(flowId);
childElement.appendChild(textNode);
gatewayElement.appendChild(childElement);
if (outgoingList?.length) {
let set = new Set();
outgoingList.map((item) => {
let outgoingId = item.textContent;
let outgoingItemElementId = `#${outgoingId}`;
let outgoingItemElement = xmlDoc.querySelector(outgoingItemElementId);
outgoingItemElement.setAttribute('sourceRef', gatewayId);
allList.map((itemElement) => {
if (itemElement.id === outgoingId)
set.add(itemElement.source?.id);
});
gatewayElement.appendChild(item);
});
set.forEach((item) => {
let element = xmlDoc.getElementById(item);
let childElement = xmlDoc.createElement(bpmnOutgoing);
element.appendChild(childElement);
let textNode = xmlDoc.createTextNode(flowId);
childElement.appendChild(textNode);
});
}
flowElement.appendChild(conditionExpression);
process.appendChild(gatewayElement);
process.appendChild(flowElement);
this.handleCreateGatewayBounds(xmlDoc, gatewayId, plane);
}
});
}
if (confluenceList?.length) {
confluenceList.map((item) => {
let targetElement = xmlDoc.querySelector(`#${item.key}`);
if (targetElement) {
let targeChildren = targetElement.children;
let outgoingList = [];
let incomingList = [];
for (var i = 0; i < targeChildren.length; i++) {
if (targeChildren[i].nodeName === bpmnOutgoing) {
outgoingList.push(targeChildren[i]);
}
else {
incomingList.push(targeChildren[i]);
}
}
let gatewayElement = NodeUtils.createGateway(xmlDoc, item.gatewayType);
let gatewayId = 'Gateway_' + buildBitUUID();
let flowId = 'Flow_' + buildBitUUID();
gatewayElement.setAttribute('id', gatewayId);
let flowElement = xmlDoc.createElement('bpmn2:sequenceFlow');
let conditionExpression = xmlDoc.createElement('bpmn2:conditionExpression');
conditionExpression.setAttribute('xsi:type', 'bpmn2:tFormalExpression');
let testText = xmlDoc.createTextNode('${' + `${flowId}` + '}');
conditionExpression.appendChild(testText);
flowElement.setAttribute('id', flowId);
flowElement.setAttribute('sourceRef', gatewayId);
flowElement.setAttribute('targetRef', item.key);
let childElement = xmlDoc.createElement(bpmnOutgoing);
let textNode = xmlDoc.createTextNode(flowId);
childElement.appendChild(textNode);
gatewayElement.appendChild(childElement);
if (incomingList && incomingList.length) {
let set = new Set();
incomingList.map((item) => {
let incomingId = item.textContent;
let incomingItemElementId = `#${incomingId}`;
let incomingItemElement = xmlDoc.querySelector(incomingItemElementId);
incomingItemElement.setAttribute('targetRef', gatewayId);
allList.map((itemElement) => {
if (itemElement.id === incomingId)
set.add(itemElement.target?.id);
});
gatewayElement.appendChild(item);
});
set.forEach((item) => {
let element = xmlDoc.getElementById(item);
let childElement = xmlDoc.createElement(bpmnIncoming);
element.appendChild(childElement);
let textNode = xmlDoc.createTextNode(flowId);
childElement.appendChild(textNode);
});
}
flowElement.appendChild(conditionExpression);
process.appendChild(gatewayElement);
process.appendChild(flowElement);
this.handleCreateGatewayBounds(xmlDoc, gatewayId, plane);
}
});
}
const newXml = new XMLSerializer().serializeToString(xmlDoc);
return encodeURIComponent(newXml);
}
static autoDelGateWay(flowXml, type, nodeMap, isPreview) {
let parser = new DOMParser();
let xmlDoc = parser.parseFromString(decodeURIComponent(flowXml), 'text/xml');
let oldXmlDoc = parser.parseFromString(decodeURIComponent(flowXml), 'text/xml');
if (type != 1) {
let process = xmlDoc.querySelector('#Process_1');
let plane = xmlDoc.querySelector('#BPMNPlane_1');
let gatewayList = NodeUtils.getAllGateway(xmlDoc);
gatewayList.map((item) => {
let incoming = item.getElementsByTagName(bpmnIncoming) || [];
let outgoing = item.getElementsByTagName(bpmnOutgoing) || [];
let sourceElement = [];
let targetElement = [];
for (let i = 0; i < incoming.length; i++) {
let flowId = `#${incoming[i].innerText || incoming[i].textContent}`;
let connectElement = xmlDoc.querySelector(flowId);
let sourceElementId = connectElement.getAttribute('sourceRef');
sourceElement.push(xmlDoc.querySelector(`#${sourceElementId}`));
}
for (let i = 0; i < outgoing.length; i++) {
let flowId = `#${outgoing[i].innerText || outgoing[i].textContent}`;
let connectElement = xmlDoc.querySelector(flowId);
let targetElementId = connectElement.getAttribute('targetRef');
targetElement.push(xmlDoc.querySelector(`#${targetElementId}`));
}
if (sourceElement.length > 1 && targetElement.length === 1) {
let targetElementId = targetElement[0]?.id;
const incomingList = NodeUtils.getIncomingConnectByElement(targetElement[0]) || [];
incomingList.map((targetComingChildren) => {
targetElement[0].removeChild(targetComingChildren);
});
let list = [];
for (let i = 0; i < incoming.length; i++) {
let flowId = incoming[i].innerText || incoming[i].textContent;
let connectElement = xmlDoc.querySelector(`#${flowId}`);
let connectElementDi = xmlDoc.querySelector(`#${flowId}_di`);
let connectWaypoint = connectElementDi.getElementsByTagName('di:waypoint');
connectElement.setAttribute('targetRef', targetElementId);
list.push(incoming[i]);
let id = item.getAttribute('id');
if (id.includes('_isSimple')) {
let outGoingId = outgoing[0].innerText || outgoing[0].textContent;
let outGoingDi = xmlDoc.querySelector(`#${outGoingId}_di`);
let test = new Set();
let newWayList = this.getGatewayWaypoints(test, outGoingDi, outgoing, oldXmlDoc, connectWaypoint);
for (let i = 0; i < newWayList?.length; i++) {
if (!connectWaypoint[i]) {
let newWaypoint = xmlDoc.createElementNS('http://www.omg.org/spec/DD/20100524/DI', 'di:waypoint');
newWaypoint.setAttribute('x', newWayList[i].x);
newWaypoint.setAttribute('y', newWayList[i].y);
connectElementDi.appendChild(newWaypoint);
}
}
}
}
list.map((item) => {
targetElement[0]?.appendChild(item);
});
process.removeChild(item);
let flowId = outgoing[0].innerText || outgoing[0].textContent;
let connectElement = xmlDoc.querySelector(`#${flowId}`);
let connectElementDi = xmlDoc.querySelector(`#${flowId}_di`);
let itemDi = xmlDoc.querySelector(`#${item.getAttribute('id')}_di`);
process.removeChild(connectElement);
connectElementDi && plane.removeChild(connectElementDi);
itemDi && plane.removeChild(itemDi);
}
if (sourceElement.length === 1 && targetElement.length > 1) {
let sourceElementId = sourceElement[0].id;
const outgoingList = NodeUtils.getOutgoingConnectByElement(sourceElement[0]) || [];
outgoingList.map((sourceElementChildren) => {
sourceElement[0].removeChild(sourceElementChildren);
});
let list = [];
for (let i = 0; i < outgoing.length; i++) {
let flowId = outgoing[i].innerText || outgoing[i].textContent;
let incomingId = incoming[0].innerText || incoming[0].textContent;
let connectElement = xmlDoc.querySelector(`#${flowId}`);
connectElement.setAttribute('sourceRef', sourceElementId);
list.push(outgoing[i]);
let id = item.getAttribute('id');
if (id.includes('_isSimple')) {
let itemDi = xmlDoc.querySelector(`#${flowId}_di`);
let itemDiWaypoint = itemDi.getElementsByTagName('di:waypoint');
let incomingDi = xmlDoc.querySelector(`#${incomingId}_di`);
let waypoint = incomingDi.getElementsByTagName('di:waypoint');
let newWayList = [];
for (let i = 0; i < waypoint.length; i++) {
newWayList.push({
x: waypoint[i].getAttribute('x'),
y: i === waypoint.length - 1
? String(Number(waypoint[i].getAttribute('y')) + typeConfig[bpmnInclusive].renderer.attr.height / 2)
: waypoint[i].getAttribute('y'),
});
}
for (let i = 0; i < itemDiWaypoint.length; i++) {
i != 0 && newWayList.push({ x: itemDiWaypoint[i].getAttribute('x'), y: itemDiWaypoint[i].getAttribute('y') });
}
for (let i = 0; i < newWayList.length; i++) {
if (itemDiWaypoint[i]) {
itemDiWaypoint[i].setAttribute('x', newWayList[i].x);
itemDiWaypoint[i].setAttribute('y', newWayList[i].y);
}
else {
let newWaypoint = xmlDoc.createElementNS('http://www.omg.org/spec/DD/20100524/DI', 'di:waypoint');
newWaypoint.setAttribute('x', newWayList[i].x);
newWaypoint.setAttribute('y', newWayList[i].y);
itemDi.appendChild(newWaypoint);
}
}
}
}
list.map((item) => {
sourceElement[0].appendChild(item);
});
process.removeChild(item);
let flowId = incoming[0].innerText || incoming[0].textContent;
let connectElement = xmlDoc.querySelector(`#${flowId}`);
let connectElementDi = xmlDoc.querySelector(`#${flowId}_di`);
let itemDi = xmlDoc.querySelector(`#${item.getAttribute('id')}_di`);
process.removeChild(connectElement);
connectElementDi && plane.removeChild(connectElementDi);
itemDi && plane.removeChild(itemDi);
}
});
if (isPreview) {
let list = process.getElementsByTagName('bpmn2:sequenceFlow');
let newList = [];
for (let i = 0; i < list.length; i++) {
let sourceRef = list[i].getAttribute('sourceRef');
let targetRef = list[i].getAttribute('targetRef');
if (nodeMap &&
nodeMap.has(sourceRef) &&
nodeMap.has(targetRef) &&
nodeMap.get(sourceRef)?.type === '0' &&
(nodeMap.get(targetRef)?.type === '0' || nodeMap.get(targetRef)?.type === '1')) {
newList.push(list[i]);
}
}
newList.forEach((node) => {
process.removeChild(node);
process.appendChild(node);
});
}
}
return xmlDoc;
}
static createGateway(xmlDoc, type) {
if (type === 'inclusion' || type === 'choose')
return xmlDoc.createElement('bpmn2:inclusiveGateway');
if (type === 'parallel')
return xmlDoc.createElement('bpmn2:parallelGateway');
if (type === 'exclusive')
return xmlDoc.createElement('bpmn2:exclusiveGateway');
}
static getAllGateway(xmlDoc) {
let gateWayList = [];
let parallelGateways = xmlDoc.getElementsByTagName('bpmn2:parallelGateway');
let inclusiveGateways = xmlDoc.getElementsByTagName('bpmn2:inclusiveGateway');
let exclusiveGateways = xmlDoc.getElementsByTagName('bpmn2:exclusiveGateway');
for (let i = 0; i < parallelGateways.length; i++) {
gateWayList.push(parallelGateways[i]);
}
for (let i = 0; i < inclusiveGateways.length; i++) {
gateWayList.push(inclusiveGateways[i]);
}
for (let i = 0; i < exclusiveGateways.length; i++) {
gateWayList.push(exclusiveGateways[i]);
}
return gateWayList;
}
static getIncomingConnectByElement(element) {
let list = [];
let incomingElements = element?.getElementsByTagName(bpmnIncoming);
for (let i = 0; i < incomingElements?.length; i++) {
list.push(incomingElements[i]);
}
return list;
}
static getOutgoingConnectByElement(element) {
let list = [];
let outgoingElements = element?.getElementsByTagName(bpmnOutgoing);
for (let i = 0; i < outgoingElements?.length; i++) {
list.push(outgoingElements[i]);
}
return list;
}
static getLastElementList(element, allElements) {
let lastList = [];
if (element && element.incoming && element.incoming.length) {
element.incoming.forEach((item) => {
return allElements.forEach((last) => {
if (last.outgoing && last.outgoing.length) {
let nextElement = last.outgoing.find((outgoing) => {
return outgoing.id === item.id;
});
if (nextElement) {
lastList.push(last);
return element;
}
}
});
});
}
return lastList;
}
static getNextElementList = (element, allElements) => {
let lastList = [];
if (element && element.outgoing && element.outgoing.length) {
element.outgoing.forEach((item) => {
let list = allElements.forEach((last) => {
if (last.incoming && last.incoming.length) {
let nextElement = last.incoming.find((incoming) => {
return incoming.id === item.id;
});
if (nextElement) {
lastList.push(last);
return element;
}
}
});
return list;
});
}
return lastList;
};
static getEndlessLoop = (bpmn) => {
let elementRegistry = bpmn.get('elementRegistry');
let elements = elementRegistry.getAll();
let graph = {};
let edgeMap = {};
elements.forEach(element => {
if (element.type === 'bpmn:SequenceFlow') {
const sourceId = element.source.id;
const targetId = element.target.id;
const edgeId = element.id;
if (!graph[sourceId])
graph[sourceId] = [];
graph[sourceId].push(targetId);
if (!edgeMap[sourceId])
edgeMap[sourceId] = [];
edgeMap[sourceId].push({ targetId, edgeId });
}
});
function findAllCycles(graph, edgeMap) {
let visited = new Set();
let stack = [];
let stackSet = new Set();
let cycles = [];
function visit(node, startNode) {
if (stackSet.has(node)) {
let pathEdges = [];
let isCycle = false;
for (let i = stack.indexOf(startNode); i < stack.length - 1; i++) {
let source = stack[i];
let target = stack[i + 1];
let edge = edgeMap[source].find(edge => edge.targetId === target);
if (edge) {
pathEdges.push(edge.edgeId);
if (source === node) {
isCycle = true;
break;
}
}
}
if (isCycle)
cycles.push(pathEdges[pathEdges.length - 1]);
return;
}
if (visited.has(node))
return;
visited.add(node);
stack.push(node);
stackSet.add(node);
let neighbors = graph[node] || [];
for (const neighbor of neighbors) {
visit(neighbor, startNode);
}
stack.pop();
stackSet.delete(node);
}
for (const node in graph) {
visit(node, node);
}
return cycles;
}
return findAllCycles(graph, edgeMap);
};
static getGatewayWaypoints = (test, outGoingDi, outgoing, xmlDoc, connectWaypoint) => {
let newList = [];
let id = outGoingDi.getAttribute('bpmnElement');
let gateway = xmlDoc.querySelector(`#${id}`);
let itemDi = xmlDoc.querySelector(`#${id}_di`);
let itemDiWaypoint = itemDi.getElementsByTagName('di:waypoint');
for (let i = 0; i < itemDiWaypoint.length; i++) {
newList.push({
x: itemDiWaypoint[i].getAttribute('x'),
y: itemDiWaypoint[i].getAttribute('y'),
});
}
let childrenElementId = gateway.getAttribute('targetRef');
let childrenElement = xmlDoc.querySelector(`#${childrenElementId}`);
if (childrenElementId.includes('Gateway_')) {
let childrenOutGoingList = childrenElement.getElementsByTagName(bpmnOutgoing);
let childrenOutGoingId = outgoing[0].innerText || outgoing[0].textContent;
let childrenOutGoingDi = xmlDoc.querySelector(`#${childrenOutGoingId}_di`);
let childrenList = this.getGatewayWaypoints(test, childrenOutGoingDi, childrenOutGoingList, xmlDoc);
if (!test.has(id))
test.add(id);
else
newList.pop();
newList = newList.concat(childrenList);
}
else if (connectWaypoint?.length > 0) {
for (let i = 0; i < connectWaypoint.length - 1; i++) {
newList.unshift({
x: connectWaypoint[i].getAttribute('x'),
y: connectWaypoint[i].getAttribute('y'),
});
}
}
return newList;
};
static verificationConnect = bpmn => {
let elementRegistry = bpmn.get('elementRegistry');
let modeling = bpmn.get('modeling');
let moddle = bpmn.get('moddle');
let connect = elementRegistry.getAll().filter((element) => {
if (is(element, 'bpmn:SequenceFlow') && !element?.businessObject?.conditionExpression && element.type != 'label')
return element;
});
if (connect?.length > 0) {
connect.forEach(sequenceFlow => {
let conditionExpression = moddle.create('bpmn:FormalExpression', {
body: '${' + `${sequenceFlow.id}` + '}',
});
modeling.updateProperties(sequenceFlow, {
conditionExpression: conditionExpression,
});
if (sequenceFlow.label?.x) {
let label = elementRegistry.get(sequenceFlow.label.id);
label.x = sequenceFlow.label.x;
label.y = sequenceFlow.label.y;
modeling.updateProperties(label, {});
}
});
}
};
static gatewayTypeSettings = (bpmn, node) => {
let elementRegistry = bpmn.get('elementRegistry');
let allElement = elementRegistry.getAll();
let reluData = bpmn.get('reluData');
allElement.map((element) => {
if (hasGatewayType.has(element.wnType)) {
let sourceElement = element.incoming[0]?.source;
reluData.setValue(sourceElement.id, { divideRule: element.wnType });
node[sourceElement.id].divideRule = element.wnType;
}
else if (element.wnType != typeTrigger) {
let sourceElement = element.incoming[0]?.source;
if (sourceElement?.id && !hasGatewayType.has(sourceElement.wnType)) {
reluData.setValue(sourceElement.id, { divideRule: typeInclusion });
node[sourceElement.id].divideRule = typeInclusion;
}
}
});
return node;
};
static handleCreateGatewayBounds = (xmlDoc, gatewayId, plane) => {
let gatewayBpmnEdge = xmlDoc.createElement('bpmndi:BPMNShape');
let waypoint = xmlDoc.createElement('dc:Bounds');
gatewayBpmnEdge.setAttribute('id', gatewayId + '_di');
gatewayBpmnEdge.setAttribute('bpmnElement', gatewayId);
waypoint.setAttribute('x', '1');
waypoint.setAttribute('y', '1');
waypoint.setAttribute('width', '1');
waypoint.setAttribute('height', '1');
gatewayBpmnEdge.appendChild(waypoint);
plane.appendChild(gatewayBpmnEdge);
};
static updateLabelWaypoints = (connection, elementRegistry, reluData, type = 0) => {
let targetElement = elementRegistry.get(connection.target?.id);
let sourceElement = elementRegistry.get(connection.source?.id);
let labelCenter = getExternalLabelMid(connection);
if (connection?.label && targetElement && sourceElement)
labelCenter = this.updateLabelCenter(targetElement, sourceElement, labelCenter, connection, reluData.data?.layout?.value, type);
return labelCenter;
};
static getNewLabelWaypoints = (connection, elementRegistry, reluData, type = 0) => {
let targetElement = elementRegistry.get(connection.target.id);
let sourceElement = elementRegistry.get(connection.source.id);
let labelCenter = getExternalLabelMid(connection);
labelCenter = this.updateLabelCenter(targetElement, sourceElement, labelCenter, connection, reluData.data?.layout?.value, type);
return labelCenter;
};
static updateLabelCenter = (targetElement, sourceElement, labelCenter, connection, layoutType, type) => {
let connectWaypointsStart = connection.waypoints[0];
let connectWaypointsEnd = connection.waypoints[connection.waypoints.length - 1];
if (layoutType === 'horizontal' && type != 1) {
if (targetElement?.incoming?.length > 1) {
labelCenter = {
x: sourceElement.x + sourceElement.width + 16,
y: sourceElement.y + sourceElement.height / 2 - 35,
};
if (connectWaypointsEnd?.y === targetElement.y || connectWaypointsEnd?.y === targetElement.y + targetElement.height) {
labelCenter.y = connection.waypoints[1]?.y - 35;
}
if (connectWaypointsStart?.y === sourceElement.y) {
labelCenter = {
x: connectWaypointsStart.x - 70,
y: connectWaypointsStart.y - 35,
};
}
if (connectWaypointsStart.y === sourceElement.y + sourceElement.height) {
labelCenter = {
x: connectWaypointsStart.x - 70,
y: connectWaypointsStart.y + 10,
};
}
if (connectWaypointsStart.x === sourceElement.x) {
labelCenter = {
x: connectWaypointsStart.x - 140,
y: connectWaypointsStart.y - 35,
};
}
}
else {
labelCenter = {
x: targetElement.x - 140,
y: targetElement.y + targetElement.height / 2 - 35,
};
if (connectWaypointsEnd?.y === targetElement.y)
labelCenter = {
x: connectWaypointsEnd?.x - 70,
y: connectWaypointsEnd?.y - 35,
};
if (connectWaypointsEnd?.y === targetElement.y + targetElement.height)
labelCenter = {
x: connectWaypointsEnd?.x - 70,
y: connectWaypointsEnd?.y + 10,
};
if (connectWaypointsEnd?.x === targetElement.x + targetElement.width) {
labelCenter = {
x: connectWaypointsEnd?.x + 10,
y: connectWaypointsEnd?.y - 35,
};
}
if (connectWaypointsEnd?.x === targetElement.x) {
labelCenter = {
x: connectWaypointsEnd?.x - 140,
y: connectWaypointsEnd?.y - 35,
};
}
}
}
if ((layoutType === 'vertical' && type != 1) || type === 1) {
if (targetElement?.incoming?.length > 1) {
labelCenter = {
x: connectWaypointsStart.x - 70,
y: sourceElement.y + sourceElement.height + 10,
};
if (connectWaypointsStart?.x === sourceElement.x || connectWaypointsStart?.x === sourceElement.x + sourceElement.width) {
labelCenter = {
x: connection.waypoints[1].x - 70,
y: connection.waypoints[2]?.y > connection.waypoints[1]?.y ? connection.waypoints[1].y + 35 : connection.waypoints[1].y - 35,
};
}
if (connectWaypointsStart?.y === sourceElement.y) {
labelCenter = {
x: connectWaypointsStart.x - 70,
y: sourceElement.y - 35,
};
}
}
else {
labelCenter = {
x: targetElement.x + targetElement.width / 2 - 20,
y: targetElement.y - 60,
};
if (connectWaypointsEnd?.y === targetElement.y)
labelCenter = {
x: connectWaypointsEnd?.x - 70,
y: connectWaypointsEnd?.y - 35,
};
if (connectWaypointsEnd?.y === targetElement.y + targetElement.height)
labelCenter = {
x: connectWaypointsEnd?.x - 70,
y: connectWaypointsEnd?.y + 10,
};
if (connectWaypointsEnd?.x === targetElement.x)
labelCenter = {
x: targetElement.x - 140,
y: connectWaypointsEnd?.y - 35,
};
if (connectWaypointsEnd.x === targetElement?.x + targetElement.width) {
labelCenter = {
x: connectWaypointsEnd?.x + 10,
y: connectWaypointsEnd?.y - 35,
};
}
}
}
return labelCenter;
};
}