Looking even better
This commit is contained in:
parent
b1f502f8d7
commit
e867e530b4
@ -85,8 +85,25 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
|
||||
const predecessors = task.config.predecessors as string[] | undefined;
|
||||
if (!predecessors || predecessors.length === 0) {
|
||||
columnByGuid.set(guid, 0);
|
||||
return 0;
|
||||
// Spread root tasks across columns when there are multiple starts
|
||||
const rootTasks = tasks.filter((t) => {
|
||||
const preds = t.config.predecessors as string[] | undefined;
|
||||
return !preds || preds.length === 0;
|
||||
});
|
||||
|
||||
rootTasks.sort((a, b) => {
|
||||
const nameA = (a.config.name as string) || a.type || "";
|
||||
const nameB = (b.config.name as string) || b.type || "";
|
||||
return nameA.localeCompare(nameB);
|
||||
});
|
||||
|
||||
const rootIndex = rootTasks.findIndex(
|
||||
(t) => (t.config.guid as string) === guid,
|
||||
);
|
||||
|
||||
const column = Math.max(0, rootIndex);
|
||||
columnByGuid.set(guid, column);
|
||||
return column;
|
||||
}
|
||||
|
||||
// If multiple predecessors, position task at the average of their columns
|
||||
@ -241,6 +258,13 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
return found?.positions ?? [];
|
||||
};
|
||||
|
||||
const getColumnPercent = (column: number): number => {
|
||||
const numColumns = columnRange.max - columnRange.min + 1;
|
||||
if (numColumns <= 1) return 50;
|
||||
const gridCol = column - columnRange.min;
|
||||
return ((gridCol + 0.5) / numColumns) * 100;
|
||||
};
|
||||
|
||||
// Calculate connector positions based on grid columns
|
||||
const getConnectorPositionsByColumn = (
|
||||
levelTasks: CreateWorkflowTemplateVersion["tasks"][],
|
||||
@ -275,6 +299,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
|
||||
const getPredecessorPositionsByColumn = (
|
||||
levelTasks: CreateWorkflowTemplateVersion["tasks"][],
|
||||
excludeTasks?: Set<string>,
|
||||
): number[] => {
|
||||
const numColumns = columnRange.max - columnRange.min + 1;
|
||||
if (numColumns <= 1) return [50];
|
||||
@ -284,6 +309,9 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
levelTasks.forEach((task) => {
|
||||
const preds = (task.config.predecessors as string[]) ?? [];
|
||||
preds.forEach((predGuid) => {
|
||||
// Skip excluded tasks (e.g., those with override)
|
||||
if (excludeTasks && excludeTasks.has(predGuid)) return;
|
||||
|
||||
const predColumn = taskColumnMap.current.get(predGuid);
|
||||
if (predColumn !== undefined) {
|
||||
predColumns.add(predColumn);
|
||||
@ -291,10 +319,9 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(predColumns).map((predColumn) => {
|
||||
const gridCol = predColumn - columnRange.min;
|
||||
return ((gridCol + 0.5) / numColumns) * 100;
|
||||
});
|
||||
return Array.from(predColumns).map((predColumn) =>
|
||||
getColumnPercent(predColumn),
|
||||
);
|
||||
};
|
||||
|
||||
const renderConnector = (
|
||||
@ -402,7 +429,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
// Otherwise render SVG with line from start to end (always, even if vertical)
|
||||
// Render orthogonal connector (vertical-horizontal-vertical)
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@ -410,12 +437,31 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
viewBox="0 0 100 40"
|
||||
preserveAspectRatio="none"
|
||||
>
|
||||
{/* Vertical line from predecessor */}
|
||||
<line
|
||||
className="visualiser-connector-branch-line"
|
||||
x1={startX}
|
||||
y1="0"
|
||||
x2={startX}
|
||||
y2="14"
|
||||
/>
|
||||
{/* Horizontal line connecting to child column */}
|
||||
{startX !== endX && (
|
||||
<line
|
||||
className="visualiser-connector-branch-line"
|
||||
x1={startX}
|
||||
y1="14"
|
||||
x2={endX}
|
||||
y2="40"
|
||||
y2="14"
|
||||
/>
|
||||
)}
|
||||
{/* Vertical line down to child */}
|
||||
<line
|
||||
className="visualiser-connector-branch-line"
|
||||
x1={endX}
|
||||
y1="14"
|
||||
x2={endX}
|
||||
y2="34"
|
||||
/>
|
||||
<polygon
|
||||
className="visualiser-connector-branch-arrow"
|
||||
@ -457,6 +503,11 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
const topX =
|
||||
predecessorPositions && predecessorPositions.length > 0
|
||||
? predecessorPositions[0]
|
||||
: 50;
|
||||
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
@ -466,9 +517,9 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
>
|
||||
<line
|
||||
className="visualiser-connector-branch-line"
|
||||
x1="50"
|
||||
x1={topX}
|
||||
y1="0"
|
||||
x2="50"
|
||||
x2={topX}
|
||||
y2="14"
|
||||
/>
|
||||
<line
|
||||
@ -547,6 +598,11 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
return connections;
|
||||
};
|
||||
|
||||
const rootTaskCount = tasks.filter((task) => {
|
||||
const preds = task.config.predecessors as string[] | undefined;
|
||||
return !preds || preds.length === 0;
|
||||
}).length;
|
||||
|
||||
return (
|
||||
<div className="visualiser-root">
|
||||
<div className="visualiser-container" ref={visualiserContainerRef}>
|
||||
@ -585,7 +641,7 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
|
||||
let styleObj: React.CSSProperties = {};
|
||||
|
||||
if (isRootTask && numColumns > 1) {
|
||||
if (isRootTask && numColumns > 1 && rootTaskCount === 1) {
|
||||
// Root tasks span all columns and center their content
|
||||
styleObj = {
|
||||
gridColumn: `1 / -1`,
|
||||
@ -644,12 +700,89 @@ const VisualiserTab: React.FC<VisualiserTabProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
{index < levels.length - 1
|
||||
? renderConnector(
|
||||
levels[index + 1].length,
|
||||
getConnectorPositionsByColumn(levels[index + 1]),
|
||||
getPredecessorPositionsByColumn(levels[index + 1]),
|
||||
levels[index + 1],
|
||||
? (() => {
|
||||
const currentLevel = levels[index];
|
||||
const nextLevel = levels[index + 1];
|
||||
|
||||
// Tasks with override should not have normal progression connectors
|
||||
const overrideTasks = new Set(
|
||||
currentLevel
|
||||
.filter(
|
||||
(task) =>
|
||||
task.config.overrideDefaultTaskProgression === true,
|
||||
)
|
||||
.map((task) => task.config.guid as string),
|
||||
);
|
||||
|
||||
const hasMergeTask = nextLevel.some((task) => {
|
||||
const preds =
|
||||
(task.config.predecessors as string[]) ?? [];
|
||||
// Only consider predecessors without override
|
||||
const validPreds = preds.filter(
|
||||
(predGuid) => !overrideTasks.has(predGuid),
|
||||
);
|
||||
if (validPreds.length <= 1) return false;
|
||||
|
||||
const predColumns = validPreds
|
||||
.map((predGuid) => taskColumnMap.current.get(predGuid))
|
||||
.filter((col) => col !== undefined) as number[];
|
||||
|
||||
return new Set(predColumns).size > 1;
|
||||
});
|
||||
|
||||
if (hasMergeTask) {
|
||||
// Filter to tasks with at least one valid predecessor
|
||||
const tasksWithValidPreds = nextLevel.filter((task) => {
|
||||
const preds =
|
||||
(task.config.predecessors as string[]) ?? [];
|
||||
return preds.some(
|
||||
(predGuid) => !overrideTasks.has(predGuid),
|
||||
);
|
||||
});
|
||||
|
||||
return renderConnector(
|
||||
tasksWithValidPreds.length,
|
||||
getConnectorPositionsByColumn(tasksWithValidPreds),
|
||||
getPredecessorPositionsByColumn(
|
||||
tasksWithValidPreds,
|
||||
overrideTasks,
|
||||
),
|
||||
tasksWithValidPreds,
|
||||
);
|
||||
}
|
||||
|
||||
const groups = new Map<
|
||||
string,
|
||||
CreateWorkflowTemplateVersion["tasks"][]
|
||||
>();
|
||||
|
||||
nextLevel.forEach((task) => {
|
||||
const preds =
|
||||
(task.config.predecessors as string[]) ?? [];
|
||||
preds.forEach((predGuid) => {
|
||||
// Skip predecessors with override
|
||||
if (overrideTasks.has(predGuid)) return;
|
||||
|
||||
const list = groups.get(predGuid) ?? [];
|
||||
list.push(task);
|
||||
groups.set(predGuid, list);
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(groups.entries()).map(
|
||||
([predGuid, children]) => {
|
||||
const predColumn = taskColumnMap.current.get(predGuid);
|
||||
if (predColumn === undefined) return null;
|
||||
|
||||
return renderConnector(
|
||||
children.length,
|
||||
getConnectorPositionsByColumn(children),
|
||||
[getColumnPercent(predColumn)],
|
||||
children,
|
||||
);
|
||||
},
|
||||
);
|
||||
})()
|
||||
: null}
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user