Move work on the visualiser

This commit is contained in:
Colin Dawson 2026-02-26 11:11:39 +00:00
parent e867e530b4
commit 6e9088a7da

View File

@ -557,6 +557,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
targetX: number;
sourceY: number;
targetY: number;
curveOffset: number;
}> => {
const connections: Array<{
sourceGuid: string;
@ -566,6 +567,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
targetX: number;
sourceY: number;
targetY: number;
curveOffset: number;
}> = [];
tasks.forEach((task) => {
@ -589,12 +591,35 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
sourceY: sourcePos.y,
targetX: targetPos.x,
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;
};
@ -795,19 +820,27 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
preserveAspectRatio="none"
>
{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 =
(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)
const t = 0.5;
const p0 = { x: conn.sourceX, y: conn.sourceY };
const p1 = {
x: conn.sourceX - controlOffsetX,
x: conn.sourceX + baseControlOffsetX * curveDirection + offsetX,
y: conn.sourceY + controlOffsetY,
};
const p2 = {
x: conn.targetX - controlOffsetX,
x: conn.targetX + baseControlOffsetX * curveDirection + offsetX,
y: conn.targetY - controlOffsetY,
};
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 +
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 (
<g
key={`outcome-${idx}`}
@ -832,10 +894,17 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
<path
className="visualiser-outcome-connector-line"
d={`M ${conn.sourceX} ${conn.sourceY}
C ${conn.sourceX - controlOffsetX} ${conn.sourceY + controlOffsetY},
${conn.targetX - controlOffsetX} ${conn.targetY - controlOffsetY},
C ${p1.x} ${p1.y},
${p2.x} ${p2.y},
${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
className="visualiser-outcome-connector-arrow"
points={`${conn.targetX - 1},${conn.targetY - 3} ${conn.targetX + 1},${conn.targetY - 3} ${conn.targetX},${conn.targetY}`}