mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Merge pull request #3092 from mermaid-js/_3089_cluster_edge_self
Fix for case where a compound state has a transition to it self.
This commit is contained in:
commit
ef9740bb38
@ -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', () => {
|
it('v2 width of compond state should grow with title if title is wider', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
|
@ -139,18 +139,13 @@ requirementDiagram
|
|||||||
test_req - contains -> test_req3
|
test_req - contains -> test_req3
|
||||||
test_req <- copies - test_entity2
|
test_req <- copies - test_entity2
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 100%;">
|
<div class="mermaid" style="width: 100%;">
|
||||||
erDiagram
|
stateDiagram
|
||||||
accTitle: My er Diagram
|
state Active {
|
||||||
accDescr: My er Diagram Description
|
Idle
|
||||||
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
|
}
|
||||||
CUSTOMER ||--o{ ORDER : places
|
Inactive --> Idle: ACT
|
||||||
CUSTOMER ||--o{ INVOICE : "liable for"
|
Active --> Active: LOG
|
||||||
DELIVERY-ADDRESS ||--o{ ORDER : receives
|
|
||||||
INVOICE ||--|{ ORDER : covers
|
|
||||||
ORDER ||--|{ ORDER-ITEM : includes
|
|
||||||
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
|
|
||||||
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
|
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 100%;">
|
<div class="mermaid2" style="width: 100%;">
|
||||||
graph TB
|
graph TB
|
||||||
@ -160,47 +155,17 @@ requirementDiagram
|
|||||||
a1-->a2-->a3
|
a1-->a2-->a3
|
||||||
end
|
end
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid" style="width: 100%;">
|
<div class="mermaid2" style="width: 100%;">
|
||||||
gantt
|
sequenceDiagram
|
||||||
accTitle: My gantt chart
|
A ->> B: 1
|
||||||
accDescr: My my gantt chart Description
|
rect rgb(204, 0, 102)
|
||||||
dateFormat YYYY-MM-DD
|
break yes
|
||||||
axisFormat %d/%m
|
rect rgb(0, 204, 204)
|
||||||
title Adding GANTT diagram to mermaid
|
C ->> C: 0
|
||||||
excludes weekdays 2014-01-10
|
end
|
||||||
|
end
|
||||||
section A section
|
end
|
||||||
Completed task :done, des1, 2014-01-06,2014-01-08
|
B ->> A: Return
|
||||||
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>
|
</div>
|
||||||
<div class="mermaid2" style="width: 100%;">
|
<div class="mermaid2" style="width: 100%;">
|
||||||
classDiagram
|
classDiagram
|
||||||
|
@ -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) => {
|
const outsideNode = (node, point) => {
|
||||||
// log.warn('Checking bounds ', node, point);
|
// log.warn('Checking bounds ', node, point);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
@ -415,45 +402,7 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
|
|||||||
if (edge.fromCluster) {
|
if (edge.fromCluster) {
|
||||||
log.info('from cluster abc88', clusterDb[edge.fromCluster]);
|
log.info('from cluster abc88', clusterDb[edge.fromCluster]);
|
||||||
points = cutPathAtIntersect(points.reverse(), clusterDb[edge.fromCluster].node).reverse();
|
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;
|
pointsHasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,33 @@ export const adjustClustersAndEdges = (graph, depth) => {
|
|||||||
' --- ',
|
' --- ',
|
||||||
clusterDb[e.w]
|
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);
|
log.warn('Fixing and trixing - removing XXX', e.v, e.w, e.name);
|
||||||
v = getAnchorId(e.v);
|
v = getAnchorId(e.v);
|
||||||
w = getAnchorId(e.w);
|
w = getAnchorId(e.w);
|
||||||
|
@ -347,6 +347,39 @@ const rect = (parent, node) => {
|
|||||||
return shapeSvg;
|
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 rect
|
||||||
* @param borders
|
* @param borders
|
||||||
@ -976,6 +1009,7 @@ const class_box = (parent, node) => {
|
|||||||
const shapes = {
|
const shapes = {
|
||||||
question,
|
question,
|
||||||
rect,
|
rect,
|
||||||
|
labelRect,
|
||||||
rectWithTitle,
|
rectWithTitle,
|
||||||
choice,
|
choice,
|
||||||
circle,
|
circle,
|
||||||
|
@ -394,6 +394,9 @@ const traverseEdge = (points) => {
|
|||||||
* @returns {Point} Return result of `transverseEdge`
|
* @returns {Point} Return result of `transverseEdge`
|
||||||
*/
|
*/
|
||||||
const calcLabelPosition = (points) => {
|
const calcLabelPosition = (points) => {
|
||||||
|
if (points.length === 1) {
|
||||||
|
return points[0];
|
||||||
|
}
|
||||||
return traverseEdge(points);
|
return traverseEdge(points);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user