There's a slight overflow happening in case of ongoing tasks (reproducible in the dummy initial data itself)
I was looking at the implementation and was wondering the possible reason for chunkWidth
as follows
const chunkWidth =
(task.duration * unitWidth) / (MONTHS.length - task.start);
If we change the denominator to 4 then it starts fitting perfectly.
const chunkWidth = (task.duration * unitWidth) / (4);
I was also wondering why you had added Math.min
check while drawing the rect. Is it to account for the fact that last month's width may not be equal to unitWidth
because we do Math.floor
in determining unitWidth
?
I was also looking at the implementation and found the sorting logic a little complicated to follow along. Instead of looping through all the tasks for a dependent task and then sorting them in-place via splicing (mutating props too), can't we use the following logic:
1. Loop through all the tasks and maintain `idToTaskMap` and `dependenciesMap`.
2. Initialise a new empty array called `sortedTasks`.
3. Filter out all the parent level tasks out of all tasks and then for each of those parent task, push the parent task itself in the `sortedTasks` first and then if `dependenciesMap.get(task)?.length` then put all the dependent tasks in `sortedTasks` after sorting them.
In code it would translate to something like this:
const sortedTasks = [];
const dependenciesMap = new Map();
const idToTaskMap = new Map();
tasks.forEach((task) => {
idToTaskMap.set(task.id, task);
if (task.dependency != null) {
const dependencyId = task.dependency;
const dependency = idToTaskMap.get(dependencyId);
if (dependency == null) {
console.warn(
`Invalid dependency; no parent task found with id ${dependencyId}`
);
} else {
if (!dependenciesMap.has(dependency)) {
dependenciesMap.set(dependency, []);
}
dependenciesMap.get(dependency).push(idToTaskMap.get(task.id));
}
}
});
tasks
.filter((task) => !task.dependency)
.forEach((task) => {
sortedTasks.push(task);
const dependentTasks = dependenciesMap.get(task);
if (dependentTasks?.length) {
const sortedDependentTasks = [...dependentTasks].sort((a, b) => {
if (a.start < b.start) return -1;
if (a.start === b.start) {
if (a.duration < b.duration) return -1;
if (!a.isOngoing && b.isOngoing) return -1;
}
return 1;
});
sortedTasks.push(...sortedDependentTasks);
}
}, []);
Will be happy to open a PR incorporating either or both of the changes as per your suggestions. Thanks in advance!