There's a very good explanation of how startDate's, manuallyScheduled, and constraints work here: viewtopic.php?p=63878#p63878
However, I'm still unsure of how to support my particular use-case. We have project tasks, assignment category tasks, and assignment tasks.
There is a hierarchical structure like so that provides us the ability to expand/collapse different tree groups:
project A
---- category A
-------- assignment 1
-------- assignment 2
---- category B
-------- assignment 1
-------- assignment 2
project B
etc.
What I want to be able to do is this:
all tasks have a specified start and end date that they should respect when rendered on the gantt (basically what you would get if you were to set manuallyScheduled to true)
however, if you resize or drag and drop a child task before the startDate or beyond the endDate of a parent task, then I want the child and affected parents to autoSync to gain this new startDate/endDate (ie. even though the parents originally had their own start and end dates, I want them to update if their child goes beyond it. basically the update behavior you'd get if manuallyScheduled was false). Another way of putting it: parents should always use the minimum startDate among its own plus that of its children, and the maximum endDate among its own plus that of its children
the only 2 real business logic constraints I have are as follows:
you may NOT drag and drop any child task to have a startDate earlier than it's parent PROJECT task (the top-level task)
If a project has already begun (it's startDate is before current day), you may NOT drag-and-drop that project task to change its startDate
TLDR: I'm confused in how to achieve this behavior where all tasks user their own start/end dates to render on the gantt, but then will still get dynamically updated with autoSync whenever one of their children get moved beyond that parent's start/end date
I'm just now reading about earlyStartDate, lateStartDate, earlyEndDate, and lateEndDate. These must come into play for me somehow, no? They sound like they're on the right track
It seems to work for my assignment tasks, but not the parent (top-level) project tasks which still are having their end-date curtailed to match that of its latest child. I even tried setting earlyEndDate on my project task and also tried using constraintType: "finishnoearlierthan" with contraintDate: projectEndDate, but neither one of those worked
This example is almost perfect to demonstrate what I'm looking for. Only problem with this demo is that Project X has no endDate specified. I want exactly this behavior, except I also want Project X to have an endDate that is respected and not solely determined by its children:
If Project X has an endDate that is later than all of its children, it will keep its own endDate
If you then drag-and-drop one of the children beyond the endDate of the project, the project's endDate will be updated to match the now later endDate of the child
What you describe sounds like a normal tasks behavior except the root level parent's ability to have its endDate greater than its children max endDate.
But that's solvable. Try using this override for example:
class Task extends TaskModel {
* calculateEndDatePure() {
const proposedValue = yield ProposedOrPrevious;
const manuallyScheduled = yield * this.isManuallyScheduled();
const hasSubEvents = yield * this.hasSubEvents();
// if that's a root level task w/ sub-events (not manually scheduled)
if (this.parent.isRoot && !manuallyScheduled && hasSubEvents) {
const childrenDate = yield * this.calculateMaxChildrenEndDate();
// if its max children endDate > its own endDate value - use children's value
return !proposedValue || proposedValue < childrenDate ? childrenDate : proposedValue;
}
return yield * super.calculateEndDatePure();
}
* calculateEndDateProposed() {
const proposedValue = yield ProposedValueOf(this.$.endDate);
const manuallyScheduled = yield * this.isManuallyScheduled();
const hasSubEvents = yield * this.hasSubEvents();
// if that's a root level task w/ sub-events (not manually scheduled)
if (this.parent.isRoot && !manuallyScheduled && hasSubEvents) {
const childrenDate = yield * this.calculateMaxChildrenEndDate();
// if its max children endDate > its own endDate value - use children's value
return !proposedValue || proposedValue < childrenDate ? childrenDate : proposedValue
}
return yield * super.calculateEndDateProposed();
}
}
The overridden methods original code can be seen in Engine/quark/model/scheduler_basic/HasSubEventsMixin.ts file.
Great, I'll give this a shot! Question for you: Is there a reason Bryntum doesn't support constraints for parent/project tasks? I'm surprised to see that in order to support this we have to do so much manual work, versus just being able to put a contraintType on a parent/project task. Is this something y'all could add support for?
Great, I'll give this a shot! Question for you: Is there a reason Bryntum doesn't support constraints for parent/project tasks? I'm surprised to see that in order to support this we have to do so much manual work, versus just being able to put a contraintType on a parent/project task. Is this something y'all could add support for?
Parent tasks do support constraints:
2.png (85.75 KiB) Viewed 133 times
Yet the list of constraints that can be used for them is a bit limited. We basically copy that behavior from MS Project which is treated as the industry standard for PM tools by the most of our customers. And my guess why MS Project does that is to just avoid extra scheduling conflicts. Regarding your case setting Start No Earlier Than constraint on projects (root level parent tasks) should do what you want and that constraint is supported.
Is that the comprehensive list of constraints that a parent task supports? The one I'd need is "finishnoearlierthan", because in theory this should enable the parent task to use it's own startDate if it exceeds that of its children. Could we potentially add support for this?
Second question, is there a why to provide multiple constraints for a task? It would be nice to have "startnolaterthan" and "finishnoearlierthan" applied at the same time with startDate and endDate respectively
Is that the comprehensive list of constraints that a parent task supports? The one I'd need is "finishnoearlierthan", because in theory this should enable the parent task to use it's own startDate if it exceeds that of its children. Could we potentially add support for this?
TaskModel has isConstraintTypeApplicable method that looks like this:
* isConstraintTypeApplicable (constraintType : ConstraintType) : CalculationIterator<boolean> {
// Take into account if the event is leaf
const hasSubEvents = yield* this.hasSubEvents()
switch (constraintType) {
// these constraints are applicable to leaves only
case ConstraintType.FinishNoEarlierThan :
case ConstraintType.StartNoLaterThan :
case ConstraintType.MustFinishOn :
case ConstraintType.MustStartOn :
return !hasSubEvents
}
return true
}
You can find this code in Engine/quark/model/scheduler_pro/HasDateConstraintMixin.ts file. So you can override the method to allow any constraints to any kind of task you need.
But allowing that constraint to summary tasks is not tested so there is a 100% chance of facing issues.
Second question, is there a why to provide multiple constraints for a task? It would be nice to have "startnolaterthan" and "finishnoearlierthan" applied at the same time with startDate and endDate respectively
It's a very rare request popping up once every few years. So it makes no sense implementing this in our codebase. We had a project once where we implemented multiple constraints support in a customer application. Yet that was made for Gantt for Ext JS quite old time ago.