Move work on the visualiser
This commit is contained in:
parent
e867e530b4
commit
6e9088a7da
@ -557,6 +557,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
targetX: number;
|
targetX: number;
|
||||||
sourceY: number;
|
sourceY: number;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
|
curveOffset: number;
|
||||||
}> => {
|
}> => {
|
||||||
const connections: Array<{
|
const connections: Array<{
|
||||||
sourceGuid: string;
|
sourceGuid: string;
|
||||||
@ -566,6 +567,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
targetX: number;
|
targetX: number;
|
||||||
sourceY: number;
|
sourceY: number;
|
||||||
targetY: number;
|
targetY: number;
|
||||||
|
curveOffset: number;
|
||||||
}> = [];
|
}> = [];
|
||||||
|
|
||||||
tasks.forEach((task) => {
|
tasks.forEach((task) => {
|
||||||
@ -589,12 +591,35 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
sourceY: sourcePos.y,
|
sourceY: sourcePos.y,
|
||||||
targetX: targetPos.x,
|
targetX: targetPos.x,
|
||||||
targetY: targetPos.y,
|
targetY: targetPos.y,
|
||||||
|
curveOffset: 0, // Will be calculated below
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Detect overlapping connections to the same target and offset them
|
||||||
|
const targetGroups = new Map<string, typeof connections>();
|
||||||
|
connections.forEach((conn) => {
|
||||||
|
const key = conn.targetGuid;
|
||||||
|
const group = targetGroups.get(key) ?? [];
|
||||||
|
group.push(conn);
|
||||||
|
targetGroups.set(key, group);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assign offsets to overlapping connections
|
||||||
|
targetGroups.forEach((group) => {
|
||||||
|
if (group.length > 1) {
|
||||||
|
group.forEach((conn, idx) => {
|
||||||
|
// Spread offsets: -10, 0, 10 for 3 connections, etc.
|
||||||
|
const totalOffsets = group.length;
|
||||||
|
const offsetStep = 15;
|
||||||
|
const baseOffset = -((totalOffsets - 1) * offsetStep) / 2;
|
||||||
|
conn.curveOffset = baseOffset + idx * offsetStep;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return connections;
|
return connections;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -795,19 +820,27 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
preserveAspectRatio="none"
|
preserveAspectRatio="none"
|
||||||
>
|
>
|
||||||
{getOutcomeConnections().map((conn, idx) => {
|
{getOutcomeConnections().map((conn, idx) => {
|
||||||
const controlOffsetX = 20;
|
// Determine curve direction based on flow direction
|
||||||
|
// Backward flow (higher Y to lower Y) curves left, forward flow curves right
|
||||||
|
const isBackwardFlow = conn.sourceY > conn.targetY;
|
||||||
|
const curveDirection = isBackwardFlow ? -1 : 1;
|
||||||
|
|
||||||
|
const baseControlOffsetX = 20 + Math.abs(conn.curveOffset) * 0.3;
|
||||||
const controlOffsetY =
|
const controlOffsetY =
|
||||||
(Math.abs(conn.targetY - conn.sourceY) / 2) * 0.3;
|
(Math.abs(conn.targetY - conn.sourceY) / 2) * 0.3;
|
||||||
|
|
||||||
|
// Apply horizontal offset to spread overlapping curves
|
||||||
|
const offsetX = conn.curveOffset;
|
||||||
|
|
||||||
// Calculate text position at the curve's midpoint (t=0.5 on Bezier curve)
|
// Calculate text position at the curve's midpoint (t=0.5 on Bezier curve)
|
||||||
const t = 0.5;
|
const t = 0.5;
|
||||||
const p0 = { x: conn.sourceX, y: conn.sourceY };
|
const p0 = { x: conn.sourceX, y: conn.sourceY };
|
||||||
const p1 = {
|
const p1 = {
|
||||||
x: conn.sourceX - controlOffsetX,
|
x: conn.sourceX + baseControlOffsetX * curveDirection + offsetX,
|
||||||
y: conn.sourceY + controlOffsetY,
|
y: conn.sourceY + controlOffsetY,
|
||||||
};
|
};
|
||||||
const p2 = {
|
const p2 = {
|
||||||
x: conn.targetX - controlOffsetX,
|
x: conn.targetX + baseControlOffsetX * curveDirection + offsetX,
|
||||||
y: conn.targetY - controlOffsetY,
|
y: conn.targetY - controlOffsetY,
|
||||||
};
|
};
|
||||||
const p3 = { x: conn.targetX, y: conn.targetY };
|
const p3 = { x: conn.targetX, y: conn.targetY };
|
||||||
@ -824,6 +857,35 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
3 * (1 - t) * Math.pow(t, 2) * p2.y +
|
3 * (1 - t) * Math.pow(t, 2) * p2.y +
|
||||||
Math.pow(t, 3) * p3.y;
|
Math.pow(t, 3) * p3.y;
|
||||||
|
|
||||||
|
// Calculate arrow position at t=0.3 for directional indicator
|
||||||
|
const tArrow = 0.3;
|
||||||
|
const arrowX =
|
||||||
|
Math.pow(1 - tArrow, 3) * p0.x +
|
||||||
|
3 * Math.pow(1 - tArrow, 2) * tArrow * p1.x +
|
||||||
|
3 * (1 - tArrow) * Math.pow(tArrow, 2) * p2.x +
|
||||||
|
Math.pow(tArrow, 3) * p3.x;
|
||||||
|
const arrowY =
|
||||||
|
Math.pow(1 - tArrow, 3) * p0.y +
|
||||||
|
3 * Math.pow(1 - tArrow, 2) * tArrow * p1.y +
|
||||||
|
3 * (1 - tArrow) * Math.pow(tArrow, 2) * p2.y +
|
||||||
|
Math.pow(tArrow, 3) * p3.y;
|
||||||
|
|
||||||
|
// Calculate tangent for arrow rotation
|
||||||
|
const tArrowDelta = 0.31;
|
||||||
|
const arrowX2 =
|
||||||
|
Math.pow(1 - tArrowDelta, 3) * p0.x +
|
||||||
|
3 * Math.pow(1 - tArrowDelta, 2) * tArrowDelta * p1.x +
|
||||||
|
3 * (1 - tArrowDelta) * Math.pow(tArrowDelta, 2) * p2.x +
|
||||||
|
Math.pow(tArrowDelta, 3) * p3.x;
|
||||||
|
const arrowY2 =
|
||||||
|
Math.pow(1 - tArrowDelta, 3) * p0.y +
|
||||||
|
3 * Math.pow(1 - tArrowDelta, 2) * tArrowDelta * p1.y +
|
||||||
|
3 * (1 - tArrowDelta) * Math.pow(tArrowDelta, 2) * p2.y +
|
||||||
|
Math.pow(tArrowDelta, 3) * p3.y;
|
||||||
|
|
||||||
|
const angle =
|
||||||
|
Math.atan2(arrowY2 - arrowY, arrowX2 - arrowX) * (180 / Math.PI);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
key={`outcome-${idx}`}
|
key={`outcome-${idx}`}
|
||||||
@ -832,10 +894,17 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
|||||||
<path
|
<path
|
||||||
className="visualiser-outcome-connector-line"
|
className="visualiser-outcome-connector-line"
|
||||||
d={`M ${conn.sourceX} ${conn.sourceY}
|
d={`M ${conn.sourceX} ${conn.sourceY}
|
||||||
C ${conn.sourceX - controlOffsetX} ${conn.sourceY + controlOffsetY},
|
C ${p1.x} ${p1.y},
|
||||||
${conn.targetX - controlOffsetX} ${conn.targetY - controlOffsetY},
|
${p2.x} ${p2.y},
|
||||||
${conn.targetX} ${conn.targetY}`}
|
${conn.targetX} ${conn.targetY}`}
|
||||||
/>
|
/>
|
||||||
|
{/* Directional arrow along curve */}
|
||||||
|
<polygon
|
||||||
|
className="visualiser-outcome-connector-arrow"
|
||||||
|
points={`-3,-1.5 -3,1.5 0,0`}
|
||||||
|
transform={`translate(${arrowX},${arrowY}) rotate(${angle})`}
|
||||||
|
/>
|
||||||
|
{/* End arrow */}
|
||||||
<polygon
|
<polygon
|
||||||
className="visualiser-outcome-connector-arrow"
|
className="visualiser-outcome-connector-arrow"
|
||||||
points={`${conn.targetX - 1},${conn.targetY - 3} ${conn.targetX + 1},${conn.targetY - 3} ${conn.targetX},${conn.targetY}`}
|
points={`${conn.targetX - 1},${conn.targetY - 3} ${conn.targetX + 1},${conn.targetY - 3} ${conn.targetX},${conn.targetY}`}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user