Duplicate Tasks Getting Created Sometimes

Hi everyone. I am getting an issue that happens only every now and then. I have tried to recreate the issue in the a snippet, but I am unable to do it. SO I figured if I provided all my JavaScript somebody might be able to see something. Note I am using an ASP.NET MVC framework, and everything is working fine, other than sometimes getting multiple of the same task getting written to the database, and then shown in the UI after it reloads.

Also note - this code that I have provided is in the same order as it is in my custom JavaScript file. I don’t know if that is causing an issue with the placement of the init values.

If someone could take a glance at this it would be greatly appreciated. Again - I have tried to recreate it in snippets, and I’m not sure what’s causing it. :open_mouth:

//Add task button We use this in our ASP controller to grab the correct id

gantt.attachEvent("onTaskCreated", function(task) { task.id = @int.MaxValue; return true; });

//This code looks kind of ugly, but the developer before me did not utilize the templates
// So i made a janky function to change the color depending if tasks are ‘feasible’ or not.

[code]
gantt.attachEvent(“onBeforeTaskDisplay”, // before the task is rendered in the chart
function(id) {
//debugger;
var t = gantt.getTask(id);
var e = t.enabled;

           //Switch statement changes the code dynamically.
           switch (e) {
               case ("true"):
                   t.textColor = "";
                   $(".gantt_task_content").css('color', 'white');
                   $( "#feasibleId" ).hide();
                   break;
               case ("true" && (t.workflowcomplete ===false || t.workflowitemcomplete ===false)):
                   t.textColor = "";
                   $(".gantt_task_content").css('color', 'white');
                   $( "#feasibleId" ).hide();
                   break;
               case ("false"):
                   t.textColor = "red";
                   $(".gantt_task_content").css('color', 'red');
                   $( "#feasibleId" ).show();
                   break;

               default:
                   t.textColor = "black";
                   break;
           }[/code]

//This is after you click the ‘save’ button on a new task.

[code]
gantt.attachEvent(“onAfterTaskAdd”,
function(id, task) {
gantt.getTask(task.id);
task.type = gantt.config.types.task; //task = 1 , project = 2
task.workflowcomplete = false;

        //Init some custom fields that I use in my controller on the ASP.NET side.
        getRootParentId(task);
       task.updatenewtask = true;           
    });[/code]

//This is the function I use to call my custom update parents and update children code

gantt.attachEvent("onAfterTaskUpdate", function(id, task) { if (!task.parent || task.parent <= 0) { $('#projectname_' + id).html(task.text); if (gantt.hasChild(task.id)) { // update all children feasibility gantt_updatechildrenfeasibility(task.id, task.enabled); } } gantt_updateparents(task, 'update'); });

//My init code is below

[code] if (!@(editor.ToString().ToLower())) {
gantt.config.readonly = true;
}
gantt.config.auto_scheduling = true; // when updating a task, linked tasks and parent tasks will also be updated
gantt.config.auto_scheduling_strict = true; // tasks are always scheduled on the earliest possible date based on their links
gantt.config.auto_scheduling_initial = true; // perform autoscheduling when data is first loaded
gantt.config.fit_tasks = true; // try to fit all tasks in the gantt chart without scrolling
gantt.config.lightbox_additional_height = 90; // for some reason the edit popup was not tall enough so we have to add a few pixels
gantt.config.scale_unit = ‘month’; // default scale
gantt.config.date_scale = “%M, %Y”; // default scale format
gantt.config.xml_date = “%Y-%m-%d %H:%i:%s”; // set the date format expected from data passed to gantt chart
gantt.config.types = { ‘task’: @((int) GanttTaskTypes.Task), ‘project’: @((int) GanttTaskTypes.Project), ‘milestone’: @((int) GanttTaskTypes.Milestone) } // custom item types so we can use an enum

$('#@ganttdivid').hide();                       // hide gantt chart until data is loaded
$('#@loadingid').show();

gantt.init("@ganttdivid");

isGanttInitialized = true;                      // only one gantt chart can be used at a time

gantt.load('@Url.Action("GetWorkflowGantt", "Workflow", new { area = "", roottaskid = Model.RootNodeId})', 'json', function() {
    $('#@loadingid').hide();
    $('#@ganttdivid').show();                     // show gantt chart now that data is loaded
    gantt.render();
});

var dp = new gantt.dataProcessor('@Url.Action("BaseUrl", "Workflow", new { area = ""})');

dp.init(gantt);
dp.setTransactionMode("REST", false);
});[/code]

The last three functions are my custom update parent and update children code.

//Update children feasibility

[code] function gantt_updatechildrenfeasibility(id, feasible) {
//debugger;
if (gantt.hasChild(id)) {
var children = gantt.getChildren(id);
children.forEach(function(cid) {
var child = gantt.getTask(cid);
child.enabled = feasible;
gantt.refreshTask(child.id);
gantt_updatechildrenfeasibility(child.id, feasible);

        });
    }
}[/code]

// Update parent code
[code]function gantt_updateparents(task, method) {
//debugger;
if (!task.parent || task.parent <= 0) {
var pctdone = Math.round(task.progress * 100);
$(’#taskpctdonediv_’ + task.id)
.css(‘background-color’, ‘hsl(’ + pctdone + ‘, 100%, 45%)’)
.css(‘width’, pctdone + ‘%’)
.html(pctdone + ‘%’); // update percentage in left menu of Index.cshtml
return;
}

    var p = gantt.getTask(gantt.getParent(task.id));

    var children = gantt.getChildren(p.id);

    if (!children || children.length <= 0 || (children.length == 1 && method == 'delete')) { // no children
        p.type = gantt.config.types.task; // make item a task
    }
    else { // has at least one child
        p.type = gantt.config.types.project; // make item a project
    }
    var durationcompleted = 0;
    var totalduration = 0;
    $.each(gantt.getChildren(p.id),
        function(index, t) {
            if (!(method == 'delete' && t == task.id)) {
                var child = gantt.getTask(t);
                if (!!child.duration) {
                    totalduration += child.duration;
                    if (!!child.progress) {
                        durationcompleted += child.duration * child.progress;
                    }
                }
            }
        });
    p.progress = totalduration > 0 ? durationcompleted / totalduration : 0;

    // update site project completion status
    if (p.$level == 0) {
        if (p.progress >= 1 && !p.workflowcomplete) {
            p.workflowcomplete = true;
            gantt_updateprojectcompletionstatus(p, true);
        } else if (p.progress < 1 && p.workflowcomplete) {
            p.workflowcomplete = false;
            gantt_updateprojectcompletionstatus(p, false);
        }
    }
    gantt.updateTask(p.id); // update parent task
    gantt.render(); // refresh gantt chart
}[/code]
// **** End update parents ****



// this is necessary to show all tasks are completed in the UI
[code]function gantt_updateprojectcompletionstatus(task, complete) {
    var children = gantt.getChildren(task.id);
    $.each(children,
        function(index, t) {
            var child = gantt.getTask(t);
            if (!child.workflowcomplete && complete) {
                child.workflowcomplete = true;
                gantt_updateprojectcompletionstatus(child, complete);
            } else if (child.workflowcomplete && !complete) {
                child.workflowcomplete = false;
                gantt_updateprojectcompletionstatus(child, complete);
            }
        });
};[/code]

I have a feeling that it has to do with my dp.init being in the middle of my javascript. Is there a recommended placement for this? Or does multiple gantt.render statements cause issues like this?

Could you describe why you’re changing task id in onTaskCreated handler? It doesn’t seem like thats it. But in this case when you’ll try to add several records at time and server response didn’t come, it could cause problems. Because you’re trying to add several tasks with same id.
Unfortunately, we can’t reproduce this issue. Could you provide sample where issue can be reproduced or link to problematic page?

Hey Sten,

Thanks for the reply. Although I haven’t fixed the issue. I know what it is coming from - My gantt chart is a part of a partial view that gets generated on an ajax call. The tasks only get created multiple times when I recall the partial view instead of reloading the entire page. So I need to find a way to ensure the JavaScript only runs once, but at least I found the culprit. Thanks!