Verschieben von Aufgaben zusammen mit ihren abhängigen Aufgaben

Hier ist ein Überblick über verschiedene Möglichkeiten, Aufgaben zusammen mit ihren abhängigen Aufgaben zu verschieben.

Verwendung der Auto Scheduling Erweiterung

Eine Option ist die Verwendung der Erweiterung Automatische Planung. Diese Funktion plant Aufgaben automatisch basierend auf ihren Beziehungen.

Um die automatische Planung zu aktivieren, aktivieren Sie sie mit der Methode gantt.plugins:

gantt.plugins({
    auto_scheduling: true
});

Setzen Sie dann die auto_scheduling Eigenschaft auf true:

gantt.config.auto_scheduling = true;

Manuelles Verschieben von Aufgaben

Inhaltsverzeichnis

Die Hauptidee

Beim manuellen Ziehen von abhängigen Aufgaben ist der allgemeine Ansatz:

  • Erkennen, wann eine Aufgabe verschoben wird.
  • Durchlaufen aller abhängigen Aufgaben und entsprechende Anpassung ihrer Positionen.

Sie können zwischen zwei Methoden wählen:

In jedem Fall besteht der erste Schritt darin, alle verknüpften Aufgaben abzurufen.

Ermitteln aller verknüpften Aufgaben

Um Aufgaben zu identifizieren, die verknüpft sind, verwenden Sie die Eigenschaften $source und $target in einem Aufgabenobjekt. Diese Eigenschaften werden automatisch generiert und enthalten die IDs der zugehörigen Verknüpfungen:

  • $source - Verknüpfungen, die von der Aufgabe ausgehen.
  • $target - Verknüpfungen, die in die Aufgabe hineinkommen.
var taskObj = gantt.getTask("t1");
 
var sourceLinks = taskObj.$source;        //-> ["l1","l4"] - IDs der ausgehenden Verknüpfungen  
var targetLinks = taskObj.$target;       //-> ["l5","l8"] - IDs der eingehenden Verknüpfungen

Sobald Sie die Verknüpfungen haben, können Sie die abhängigen Aufgaben identifizieren.

Um durch die verknüpften Aufgaben zu iterieren, können Sie den folgenden Iterator verwenden:

gantt.eachSuccessor = function(callback, root){
  if(!this.isTaskExists(root))
    return;
 
  // Unendliche Schleifen vermeiden, indem besuchte Aufgaben nachverfolgt werden
  var traversedTasks = arguments[2] || {};
  if(traversedTasks[root])
    return;
  traversedTasks[root] = true;
 
  var rootTask = this.getTask(root);
  var links = rootTask.$source;
  if(links){
    for(var i=0; i < links.length; i++){
      var link = this.getLink(links[i]);
      if(this.isTaskExists(link.target) && !traversedTasks[link.target]){
        callback.call(this, this.getTask(link.target));
 
        // Den gesamten Zweig durchlaufen, nicht nur erststufige Abhängigkeiten
        this.eachSuccessor(callback, link.target, traversedTasks);
      }
    }
  }
};

Synchrones Verschieben von Nachkommen mit der Hauptaufgabe

Abhängige Aufgaben können gleichzeitig mit der Hauptaufgabe verschoben werden, während sie gezogen wird. Dies erzeugt einen flüssigen visuellen Effekt, kann jedoch die Leistung beeinträchtigen, wenn viele Aufgaben gleichzeitig verschoben werden.

Schritt 1

Beginnen Sie mit der Einrichtung des Iterators, wie oben gezeigt above.

Schritt 2

Befestigen Sie als Nächstes einen Handler an das Ereignis onTaskDrag. Dieser Handler wird während jedes Drag-and-Drop-Frames ausgeführt und passt die Positionen der verknüpften Aufgaben an.

gantt.attachEvent("onTaskDrag", function(id, mode, task, original){
  var modes = gantt.config.drag_mode;
  if(mode == modes.move){
    var diff = task.start_date - original.start_date;
    gantt.eachSuccessor(function(child){
      child.start_date = new Date(+child.start_date + diff);
      child.end_date = new Date(+child.end_date + diff);
      gantt.refreshTask(child.id, true);
    },id );
  }
  return true;
});

Schritt 3

Schließlich, wenn das Drag-and-Drop abgeschlossen ist, runden Sie die Positionen der abhängigen Aufgaben auf die Skala. Dies kann mit dem Ereignis onAfterTaskDrag erfolgen:

gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
  var modes = gantt.config.drag_mode;
  if(mode == modes.move ){
    gantt.eachSuccessor(function(child){
      child.start_date = gantt.roundDate(child.start_date);
      child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
      gantt.updateTask(child.id);
    },id );
  }
});

Diese Methode funktioniert gut, es sei denn, es gibt zu viele verknüpfte Aufgaben.

Verschieben von Nachkommen nach Abschluss der Bewegung der Hauptaufgabe

Eine andere Möglichkeit besteht darin, abhängige Aufgaben erst nach der Verschiebung der Hauptaufgabe anzupassen. Dieser Ansatz vereinfacht den Prozess und verbessert die Leistung.

So kann es gemacht werden:

Schritt 1

Beginnen Sie mit der Einrichtung des Iterators, wie oben gezeigt above.

Schritt 2

Sobald die Drag-and-Drop-Aktion abgeschlossen ist, verwenden Sie das Ereignis onBeforeTaskChanged, um den Unterschied in den Daten zwischen den ursprünglichen und geänderten Aufgabeninstanzen zu erfassen.

Beachten Sie, dass Drag-and-Drop zu diesem Zeitpunkt noch abgebrochen werden kann, da onBeforeTaskChanged eine Stornierung ermöglicht. Vermeiden Sie es, zu diesem Zeitpunkt abhängige Aufgaben zu ändern.

Speichern Sie stattdessen den berechneten Unterschied in einer Variablen zur späteren Verwendung.

var diff = 0;
 
gantt.attachEvent("onBeforeTaskChanged", function(id, mode, originalTask){
  var modes = gantt.config.drag_mode;
  if(mode == modes.move ){
    var modifiedTask = gantt.getTask(id);
    diff = modifiedTask.start_date - originalTask.start_date;
  }
  return true;
});

Schritt 3

Verwenden Sie schließlich das Ereignis onAfterTaskDrag, um den berechneten Unterschied auf alle abhängigen Aufgaben anzuwenden, sobald das Drag-and-Drop bestätigt ist:

// Positionen der untergeordneten Elemente auf die Skala runden
gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
    var modes = gantt.config.drag_mode;
    if(mode == modes.move ){
      gantt.eachSuccessor(function(child){
        child.start_date = gantt.roundDate(new Date(child.start_date.valueOf() + diff));
        child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
        gantt.updateTask(child.id);
      },id );
    }
});

Hier ist der vollständige Code für diesen Ansatz:

(function(){
 
  var diff = 0;
 
  gantt.attachEvent("onBeforeTaskChanged", function(id, mode, originalTask){
    var modes = gantt.config.drag_mode;
    if(mode == modes.move ){
      var modifiedTask = gantt.getTask(id);
      diff = modifiedTask.start_date - originalTask.start_date;
    }
    return true;
  });
 
  // Positionen der untergeordneten Elemente auf die Skala runden
  gantt.attachEvent("onAfterTaskDrag", function(id, mode, e){
    var modes = gantt.config.drag_mode;
    if(mode == modes.move ){
      gantt.eachSuccessor(function(child){
        child.start_date = gantt.roundDate(new Date(child.start_date.valueOf() + diff));
        child.end_date = gantt.calculateEndDate(child.start_date, child.duration);
        gantt.updateTask(child.id);
      },id );
    }
  });
})();
Zurück nach oben