Skip to content

Commit

Permalink
Merge pull request #3092 from mermaid-js/_3089_cluster_edge_self
Browse files Browse the repository at this point in the history
Fix for case where a compound state has a transition to it self.
  • Loading branch information
knsv committed May 31, 2022
2 parents bb5baa6 + bd459fa commit ef9740b
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 105 deletions.
15 changes: 15 additions & 0 deletions cypress/integration/rendering/stateDiagram-v2.spec.js
Expand Up @@ -346,6 +346,21 @@ describe('State diagram', () => {
}
);
});
it('v2 A compound state should be able to link to itself', () => {
imgSnapshotTest(
`
stateDiagram
state Active {
Idle
}
Inactive --> Idle: ACT
Active --> Active: LOG
`,
{
logLevel: 0,
}
);
});
it('v2 width of compond state should grow with title if title is wider', () => {
imgSnapshotTest(
`
Expand Down
71 changes: 18 additions & 53 deletions cypress/platform/knsv.html
Expand Up @@ -139,18 +139,13 @@
test_req - contains -> test_req3
test_req <- copies - test_entity2
</div>
<div class="mermaid2" style="width: 100%;">
erDiagram
accTitle: My er Diagram
accDescr: My er Diagram Description
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
CUSTOMER ||--o{ ORDER : places
CUSTOMER ||--o{ INVOICE : "liable for"
DELIVERY-ADDRESS ||--o{ ORDER : receives
INVOICE ||--|{ ORDER : covers
ORDER ||--|{ ORDER-ITEM : includes
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
<div class="mermaid" style="width: 100%;">
stateDiagram
state Active {
Idle
}
Inactive --> Idle: ACT
Active --> Active: LOG
</div>
<div class="mermaid2" style="width: 100%;">
graph TB
Expand All @@ -160,47 +155,17 @@
a1-->a2-->a3
end
</div>
<div class="mermaid" style="width: 100%;">
gantt
accTitle: My gantt chart
accDescr: My my gantt chart Description
dateFormat YYYY-MM-DD
axisFormat %d/%m
title Adding GANTT diagram to mermaid
excludes weekdays 2014-01-10

section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d

section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d

section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h

section Clickable
Visit mermaidjs :active, cl1, 2014-01-07,2014-01-10
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d

click cl1 href "https://mermaid-js.github.io/mermaid/#/"
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)

section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
<div class="mermaid2" style="width: 100%;">
sequenceDiagram
A ->> B: 1
rect rgb(204, 0, 102)
break yes
rect rgb(0, 204, 204)
C ->> C: 0
end
end
end
B ->> A: Return
</div>
<div class="mermaid2" style="width: 100%;">
classDiagram
Expand Down
51 changes: 0 additions & 51 deletions src/dagre-wrapper/edges.js
Expand Up @@ -192,19 +192,6 @@ export const positionEdgeLabel = (edge, paths) => {
}
};

// const getRelationType = function(type) {
// switch (type) {
// case stateDb.relationType.AGGREGATION:
// return 'aggregation';
// case stateDb.relationType.EXTENSION:
// return 'extension';
// case stateDb.relationType.COMPOSITION:
// return 'composition';
// case stateDb.relationType.DEPENDENCY:
// return 'dependency';
// }
// };

const outsideNode = (node, point) => {
// log.warn('Checking bounds ', node, point);
const x = node.x;
Expand Down Expand Up @@ -415,45 +402,7 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
if (edge.fromCluster) {
log.info('from cluster abc88', clusterDb[edge.fromCluster]);
points = cutPathAtIntersect(points.reverse(), clusterDb[edge.fromCluster].node).reverse();
// log.warn('edge', edge);
// log.warn('from cluster', clusterDb[edge.fromCluster], points);
// const updatedPoints = [];
// let lastPointOutside = edge.points[edge.points.length - 1];
// let isInside = false;
// for (let i = points.length - 1; i >= 0; i--) {
// const point = points[i];
// const node = clusterDb[edge.fromCluster].node;
// log.warn('checking to', edge.fromCluster, point, node);

// if (!outsideNode(node, point) && !isInside) {
// log.warn('inside', edge.fromCluster, point, node);

// // First point inside the rect
// const inter = intersection(node, lastPointOutside, point);
// log.warn('intersect', intersection(node, lastPointOutside, point));
// let pointPresent = false;
// points.forEach(p => {
// pointPresent = pointPresent || (p.x === inter.x && p.y === inter.y);
// });
// // if (!pointPresent) {
// if (!points.find(e => e.x === inter.x && e.y === inter.y)) {
// updatedPoints.unshift(inter);
// log.warn('Adding point -updated = ', updatedPoints);
// } else {
// log.warn('no intersect', inter, points);
// }
// // points.push(insterection);
// isInside = true;
// } else {
// // at the outside
// // if (!isInside) updatedPoints.unshift(point);
// updatedPoints.unshift(point);
// log.warn('Outside point', point, updatedPoints);
// }
// lastPointOutside = point;
// }
// points = updatedPoints;
// points = edge.points;
pointsHasChanged = true;
}

Expand Down
28 changes: 27 additions & 1 deletion src/dagre-wrapper/mermaid-graphlib.js
Expand Up @@ -277,7 +277,33 @@ export const adjustClustersAndEdges = (graph, depth) => {
' --- ',
clusterDb[e.w]
);
if (clusterDb[e.v] || clusterDb[e.w]) {
if (clusterDb[e.v] && clusterDb[e.w] && clusterDb[e.v] === clusterDb[e.w]) {
log.warn('Fixing and trixing link to self - removing XXX', e.v, e.w, e.name);
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
v = getAnchorId(e.v);
w = getAnchorId(e.w);
graph.removeEdge(e.v, e.w, e.name);
const specialId = e.w + '---' + e.v;
graph.setNode(specialId, {
domId: specialId,
id: specialId,
labelStyle: '',
labelText: edge.label,
padding: 0,
shape: 'labelRect',
style: '',
});
const edge1 = JSON.parse(JSON.stringify(edge));
const edge2 = JSON.parse(JSON.stringify(edge));
edge1.label = '';
edge1.arrowTypeEnd = 'none';
edge2.label = '';
edge1.fromCluster = e.v;
edge2.toCluster = e.v;

graph.setEdge(v, specialId, edge1, e.name + '-cyclic-special');
graph.setEdge(specialId, w, edge2, e.name + '-cyclic-special');
} else if (clusterDb[e.v] || clusterDb[e.w]) {
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
v = getAnchorId(e.v);
w = getAnchorId(e.w);
Expand Down
34 changes: 34 additions & 0 deletions src/dagre-wrapper/nodes.js
Expand Up @@ -347,6 +347,39 @@ const rect = (parent, node) => {
return shapeSvg;
};

const labelRect = (parent, node) => {
const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'label', true);

log.trace('Classes = ', node.classes);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');

// Hide the rect we are only after the label
const totalWidth = 0;
const totalHeight = 0;
rect.attr('width', totalWidth).attr('height', totalHeight);
shapeSvg.attr('class', 'label edgeLabel');

if (node.props) {
const propKeys = new Set(Object.keys(node.props));
if (node.props.borders) {
applyNodePropertyBorders(rect, node.props.borders, totalWidth, totalHeight);
propKeys.delete('borders');
}
propKeys.forEach((propKey) => {
log.warn(`Unknown node property ${propKey}`);
});
}

updateNodeBounds(node, rect);

node.intersect = function (point) {
return intersect.rect(node, point);
};

return shapeSvg;
};

/**
* @param rect
* @param borders
Expand Down Expand Up @@ -976,6 +1009,7 @@ const class_box = (parent, node) => {
const shapes = {
question,
rect,
labelRect,
rectWithTitle,
choice,
circle,
Expand Down
3 changes: 3 additions & 0 deletions src/utils.js
Expand Up @@ -394,6 +394,9 @@ const traverseEdge = (points) => {
* @returns {Point} Return result of `transverseEdge`
*/
const calcLabelPosition = (points) => {
if (points.length === 1) {
return points[0];
}
return traverseEdge(points);
};

Expand Down

0 comments on commit ef9740b

Please sign in to comment.