Constrained children position change upon parent task move

Discuss issues related to v5.x
User avatar
arcady
Core Developer
Core Developer
Posts: 2380
Joined: Wed Mar 20, 2013 6:57 am

Re: Constrained children position change upon parent task move

Post by arcady »

Sorry we've mistakenly used the latest 5.x version of the method. Here is the correct override:

Code: Select all

Ext.define('MyTask', {

extend                 : 'Gnt.model.Task',

processTaskConstraints : function(linearWalkingSequence, linearWalkingIndex, taskStore, cascadeBatch, propagationSources, forceCascadeChanges, affectedTasks, callback) {
    var me                             = this,
        step                           = linearWalkingSequence[linearWalkingIndex],
        task                           = step[0],
        color                          = step[1],
        isParent                       = task.hasChildNodes(),
        isLeaf                         = !isParent,
        needsReScheduling              = task.get('needsReScheduling'),
        autoScheduled                  = /*needsReScheduling || */ !(task.isManuallyScheduled() || task.isReadOnly() || Ext.Array.contains(propagationSources, task)),
        cascadeChanges                 = forceCascadeChanges || taskStore.cascadeChanges,
        scheduleByConstraints          = taskStore.scheduleByConstraints,
        recalculateParents             = taskStore.recalculateParents,
        moveParentAsGroup              = taskStore.moveParentAsGroup,
        parentNode                     = task.parentNode,
        parentNodeStartDate            = parentNode && (parentNode.getStartDate()),
        parentNodeUnprojectedStartDate = parentNode && (parentNode.getUnprojected(parentNode.startDateField)),
        parentNodeDateOffset           = parentNode && (parentNodeStartDate - parentNodeUnprojectedStartDate),
        skipConstraintsVerification    = false,
        offsetFromParent;

    function areIncomingDependenciesAffectedOrPropagationSourcesIncoming(task, affectedTasks, propagationSources) {
        var incomingDeps = task.getIncomingDependencies(true),
            result = false,
            i, len, dep, fromTask;
        // PATCH - vvv
        if (cascadeChanges)
            for (i = 0, len = incomingDeps.length; !result && i < len; ++i) {
                dep = incomingDeps[i];
                fromTask = dep.getSourceTask();
                result = fromTask && affectedTasks.hasOwnProperty(fromTask.getId()) ||
                                     Ext.Array.contains(propagationSources, fromTask);
            }

        return result;
    }

    switch (true) {
        case autoScheduled && isLeaf   && color == 'green'  && parentNodeDateOffset && moveParentAsGroup:
        case autoScheduled && isParent && color == 'yellow' && parentNodeDateOffset && moveParentAsGroup:
            // TODO: we ignore case when parent StartDate set to NULL
            // since we cannot calculate proper dates to shift child tasks at
            if (parentNodeStartDate) {

                if (scheduleByConstraints) {
                    task.scheduleWithoutPropagation({ taskStore : taskStore });

                // TODO: BW compat ..this case can be removed when we make aligning by constraints non-optional
                } else {
                    var startDate = task.getStartDate();

                    if (startDate >= parentNodeUnprojectedStartDate) {
                        offsetFromParent = task.calculateDuration(parentNodeUnprojectedStartDate, startDate, null, { segments : false });
                        task.setStartDateWithoutPropagation(task.calculateEndDate(parentNodeStartDate, offsetFromParent, null, { segments : false }), true, taskStore.skipWeekendsDuringDragDrop);

                    // if the summary task starts after this one
                    } else {
                        // force to not take segments into account during new start date calculating
                        offsetFromParent = task.calculateDuration(startDate, parentNodeUnprojectedStartDate, null, { segments : false });
                        task.setStartDateWithoutPropagation(task.calculateStartDate(parentNodeStartDate, offsetFromParent, null, { segments : false }), true, taskStore.skipWeekendsDuringDragDrop);
                    }

                    // Passing a parent node here limits the constraining to incoming dependencies incoming from
                    // that parent node descendants only, outer nodes are not taken into account
                    areIncomingDependenciesAffectedOrPropagationSourcesIncoming(task, affectedTasks, propagationSources) &&
                        task.scheduleWithoutPropagation({ taskStore : taskStore, parentNode : parentNode });
                }

            }

            break;

        case isLeaf   && color == 'green'  && needsReScheduling:
        case isParent && color == 'yellow' && needsReScheduling:

            task.scheduleWithoutPropagation({ taskStore : taskStore });
            break;

        case autoScheduled && isLeaf   && color == 'green'  && cascadeChanges:
        case autoScheduled && isParent && color == 'yellow' && cascadeChanges:

            if (areIncomingDependenciesAffectedOrPropagationSourcesIncoming(task, affectedTasks, propagationSources)) {
                task.scheduleWithoutPropagation({ taskStore : taskStore });

            // If it's a parent task then we haven't finished w/ the task positioning yet.
            // So let's skip the task constraints check at this step. We can do it later.
            } else if (isParent && recalculateParents) {
                skipConstraintsVerification = true;
            }

            break;

        case isParent && color == 'green' && recalculateParents:

            task.refreshCalculatedParentNodeData();
            break;
    }

    if (task.isProjected()) {
        cascadeBatch.addAffected(task);
        affectedTasks[task.getId()] = task;
    }

    var proceedOnVerificationIsDoneCallback = function (constraintSatisfied, propagationCanceled) {
        var yellowStep,
            yellowStepIdx;

        // In case a parent node is adjusted according to it's children and such an adjustment violates
        // the parent node constraint then we rewind back to the same parent node yellow step to readjust
        // it and it's children once again allowing a user to reconsider (by showing him constraint violation
        // dialog, for example). We rewind by calling a callback with adjusted step index.
        if (!constraintSatisfied && isParent && autoScheduled && taskStore.recalculateParents && color == 'green') {
            yellowStep = Ext.Array.findBy(linearWalkingSequence, function(step, index) {
                var stepTask  = step[0],
                    stepColor = step[1];

                yellowStepIdx = index;

                return task === stepTask && stepColor == 'yellow';
            });
            // yellowStep must always be present in the linear walking sequence.
            callback(yellowStepIdx, constraintSatisfied, !!propagationCanceled, affectedTasks);
        }
        else {
            callback(linearWalkingIndex, constraintSatisfied, !!propagationCanceled, affectedTasks);
        }
    };

    // if verification should be skipped we proceed to the next step by calling "proceedOnVerificationIsDoneCallback" manually
    if (skipConstraintsVerification) {
        proceedOnVerificationIsDoneCallback(true, false);
    }

    // otherwise we do verification by calling "task.verifyConstraints()" and "proceedOnVerificationIsDoneCallback" will be called there
    return skipConstraintsVerification || task.verifyConstraints(proceedOnVerificationIsDoneCallback);
}

});

User avatar
gpa
Posts: 15
Joined: Fri Jul 14, 2017 12:46 pm

Re: Constrained children position change upon parent task move

Post by gpa »

Good morning,
thanks a lot for the fix, it worked. We applied that as a patch in our code for the moment. We'll try to bump the version of the library when available.

Again, thanks for the support.
Gaetano


Post Reply