Our state of the art Gantt chart


Post by victor_bezak »

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:
    1. you may NOT drag and drop any child task to have a startDate earlier than it's parent PROJECT task (the top-level task)
    2. 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


Post by victor_bezak »

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

https://bryntum.com/products/gantt/docs/api/Gantt/model/TaskModel#field-earlyStartDate


Post by victor_bezak »

Also, what about autoSetConstraints? https://bryntum.com/products/gantt/docs/api/Gantt/model/ProjectModel#config-autoSetConstraints

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


Post by victor_bezak »

I also just learned about includeAsapAlapAsConstraints, but setting this to false doesn't seem to be helping (ie. my project task is still getting its endDate cut-short because of its children): https://www.bryntum.com/products/gantt/docs/api/Gantt/model/ProjectModel#config-includeAsapAlapAsConstraints


Post by victor_bezak »

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:

Demo: https://bryntum.com/products/gantt/examples/auto-constraints/
Data for demo: https://bryntum.com/products/gantt/examples/_datasets/basic.json

  • 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

Post by arcady »

Hello,

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.

Best regards,
Arcady


Post by victor_bezak »

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?


Post by arcady »

Hello,

victor_bezak wrote: Wed Aug 14, 2024 11:33 pm

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
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.

Best regards,
Arcady


Post by victor_bezak »

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


Post by arcady »

Hello,

victor_bezak wrote: Thu Aug 15, 2024 6:24 pm

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.

victor_bezak wrote: Thu Aug 15, 2024 6:24 pm

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.

https://github.com/bryntum/support/issues/5801

Best regards,
Arcady


Post Reply