Tasks how get assigned a default predecessor.

This commit is contained in:
Colin Dawson 2026-02-14 17:53:46 +00:00
parent ed2ed1ac6e
commit 69bb924510
2 changed files with 71 additions and 15 deletions

View File

@ -8,6 +8,7 @@ import { renderTaskField } from "../taskEditorHelpers";
import { TaskValidationResult } from "../TasksEditor";
import { Namespaces } from "../../../../../i18n/i18n";
import { useTranslation } from "react-i18next";
import { getAllDescendants } from "../workflowGraphUtils";
interface TaskCoreEditorProps {
task: TaskDefinition;
@ -58,6 +59,11 @@ export const TaskCoreEditor: React.FC<TaskCoreEditorProps> = ({
[allowedTasks, task.type, tTaskType],
);
useEffect(() => {
// Reset the guard when a new task is loaded
hasAssignedDefaultName.current = false;
}, [task.config.guid]);
useEffect(() => {
if (!hasAssignedDefaultName.current && !task.config.name) {
hasAssignedDefaultName.current = true;
@ -66,17 +72,27 @@ export const TaskCoreEditor: React.FC<TaskCoreEditorProps> = ({
(t) => t.taskType === task.type,
)?.displayName;
if (displayName) {
const newName = formatNewTaskName(allTasks);
const newConfig = { ...task.config };
onChange({
...task,
config: {
...task.config,
name: newName,
},
});
// Assign default name
if (displayName) {
newConfig.name = formatNewTaskName(allTasks);
}
// Assign default predecessor (the task immediately before this one)
const index = allTasks.findIndex(
(t) => t.config.guid === task.config.guid,
);
if (index > 0) {
const previousTask = allTasks[index - 1];
newConfig.predecessors = [previousTask.config.guid as string];
}
onChange({
...task,
config: newConfig,
});
}
}, [allTasks, allowedTasks, formatNewTaskName, onChange, task]);
@ -163,6 +179,21 @@ export const TaskCoreEditor: React.FC<TaskCoreEditorProps> = ({
onValidate,
]);
const currentGuid = task.config.guid as string;
const descendants = getAllDescendants(currentGuid, allTasks);
const allowedPredecessors = allTasks.filter((t) => {
const guid = t.config.guid as string;
// Exclude self
if (guid === currentGuid) return false;
// Exclude descendants (direct or indirect)
if (descendants.has(guid)) return false;
return true;
});
return (
<div>
{renderTaskField(
@ -193,12 +224,10 @@ export const TaskCoreEditor: React.FC<TaskCoreEditorProps> = ({
"",
0,
{
options: allTasks
.filter((t) => t.config.guid !== task.config.guid)
.map((t) => ({
value: t.config.guid as string,
label: t.config.name as string,
})),
options: allowedPredecessors.map((t) => ({
value: t.config.guid as string,
label: t.config.name as string,
})),
},
)}
</div>

View File

@ -0,0 +1,27 @@
import { TaskDefinition } from "../services/WorkflowTemplateService";
export const getAllDescendants = (
guid: string,
tasks: TaskDefinition[],
): Set<string> => {
const descendants = new Set<string>();
const visit = (current: string) => {
for (const t of tasks) {
const preds = (t.config.predecessors as string[]) ?? [];
// If t depends on current, it's a child
if (
preds.includes(current) &&
!descendants.has(t.config.guid as string)
) {
const childGuid = t.config.guid as string;
descendants.add(childGuid);
visit(childGuid); // recursively find grandchildren
}
}
};
visit(guid);
return descendants;
};