Compare commits
3 Commits
fc8d736127
...
0b43e4ecd7
Author | SHA1 | Date | |
---|---|---|---|
0b43e4ecd7 | |||
|
62c1917b80 | ||
|
2b8baa0c3c |
21
demo.html
21
demo.html
@ -138,15 +138,16 @@ textarea {
|
|||||||
window.project1.Clear();
|
window.project1.Clear();
|
||||||
|
|
||||||
var tasks = [
|
var tasks = [
|
||||||
{"Order":1,"ID":1,"Name":"Task A","Description":"","Tag":null,"StartDate":"2024-08-11T23:00:00.000Z","FinishDate":"2024-08-14T23:00:00.000Z","StartDelay":0,"Duration":3,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":null,"CalcWorkHours":22.5,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":0,"PredecessorTaskNo":null},
|
{"ID":1,"Name":"Task A","Description":"","Tag":null,"StartDate":"2024-08-11T23:00:00.000Z","StartDelay":0,"Duration":3,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":2,"ID":2,"Name":"Task B","Description":"","Tag":null,"StartDate":"2024-08-14T23:00:00.000Z","FinishDate":"2024-08-28T23:00:00.000Z","StartDelay":0,"Duration":14,"PredecessorTaskID":1,"IsCollated":false,"CollatedTaskID":null,"CalcWorkHours":105,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":0,"PredecessorTaskNo":1},
|
{"ID":2,"Name":"Task B","Description":"","Tag":null,"StartDate":"2024-08-14T23:00:00.000Z","StartDelay":0,"Duration":14,"PredecessorTaskID":1,"IsCollated":false,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":3,"ID":5,"Name":"Task B1","Description":"","Tag":null,"StartDate":"2024-08-29T23:00:00.000Z","FinishDate":"2024-09-26T23:00:00.000Z","StartDelay":1,"Duration":28,"PredecessorTaskID":2,"IsCollated":true,"CollatedTaskID":null,"CalcWorkHours":210,"ActuWorkHours":null,"Progress":25,"Resources":[],"Level":0,"PredecessorTaskNo":2},
|
{"ID":5,"Name":"Task B1","Description":"","Tag":null,"StartDate":"2024-08-29T23:00:00.000Z","StartDelay":1,"Duration":28,"PredecessorTaskID":2,"IsCollated":true,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":25,"Resources":[]},
|
||||||
{"Order":4,"ID":6,"Name":"Task B11","Description":"","Tag":null,"StartDate":"2024-09-02T23:00:00.000Z","FinishDate":"2024-09-26T23:00:00.000Z","StartDelay":4,"Duration":24,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":5,"CalcWorkHours":180,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":1,"PredecessorTaskNo":null},
|
{"ID":6,"Name":"Task B11","Description":"","Tag":null,"StartDate":"2024-09-02T23:00:00.000Z","StartDelay":4,"Duration":24,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":5,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":5,"ID":7,"Name":"Task B12","Description":"","Tag":null,"StartDate":"2024-08-30T23:00:00.000Z","FinishDate":"2024-09-25T23:00:00.000Z","StartDelay":1,"Duration":26,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":5,"CalcWorkHours":0,"ActuWorkHours":null,"Progress":50,"Resources":[],"Level":1,"PredecessorTaskNo":null},
|
{"ID":7,"Name":"Task B12","Description":"","Tag":null,"StartDate":"2024-08-30T23:00:00.000Z","StartDelay":1,"Duration":26,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":5,"ActuWorkHours":null,"Progress":50,"Resources":[]},
|
||||||
{"Order":6,"ID":8,"Name":"Task E","Description":"","Tag":null,"StartDate":"2024-08-11T23:00:00.000Z","FinishDate":"2024-08-26T23:00:00.000Z","StartDelay":0,"Duration":15,"PredecessorTaskID":null,"IsCollated":true,"CollatedTaskID":null,"CalcWorkHours":112.5,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":0,"PredecessorTaskNo":null},
|
{"ID":8,"Name":"Task E","Description":"","Tag":null,"StartDate":"2024-08-11T23:00:00.000Z","StartDelay":0,"Duration":15,"PredecessorTaskID":null,"IsCollated":true,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":7,"ID":3,"Name":"Task C","Description":"","Tag":null,"StartDate":"2024-08-26T23:00:00.000Z","FinishDate":"2024-09-13T23:00:00.000Z","StartDelay":0,"Duration":18,"PredecessorTaskID":8,"IsCollated":false,"CollatedTaskID":null,"CalcWorkHours":135,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":0,"PredecessorTaskNo":6},
|
{"ID":3,"Name":"Task C","Description":"","Tag":null,"StartDate":"2024-08-26T23:00:00.000Z","StartDelay":0,"Duration":18,"PredecessorTaskID":8,"IsCollated":false,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":8,"ID":4,"Name":"Task D","Description":"","Tag":null,"StartDate":"2024-09-14T23:00:00.000Z","FinishDate":"2024-09-24T23:00:00.000Z","StartDelay":1,"Duration":10,"PredecessorTaskID":3,"IsCollated":false,"CollatedTaskID":null,"CalcWorkHours":0,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":0,"PredecessorTaskNo":7},
|
{"ID":4,"Name":"Task D","Description":"","Tag":null,"StartDate":"2024-09-14T23:00:00.000Z","StartDelay":1,"Duration":10,"PredecessorTaskID":3,"IsCollated":false,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
{"Order":9,"ID":9,"Name":"Task E1","Description":"","Tag":null,"StartDate":"2024-08-14T23:00:00.000Z","FinishDate":"2024-08-26T23:00:00.000Z","StartDelay":3,"Duration":12,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":8,"CalcWorkHours":90,"ActuWorkHours":null,"Progress":0,"Resources":[],"Level":1,"PredecessorTaskNo":null}
|
{"ID":9,"Name":"Task E1","Description":"","Tag":null,"StartDate":"2024-08-14T23:00:00.000Z","StartDelay":3,"Duration":12,"PredecessorTaskID":null,"IsCollated":false,"CollatedTaskID":8,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
|
{"ID":10,"Name":"Task C2","Description":"","Tag":null,"StartDate":"2024-08-26T23:00:00.000Z","StartDelay":0,"Duration":18,"PredecessorTaskID":8,"IsCollated":false,"CollatedTaskID":null,"ActuWorkHours":null,"Progress":0,"Resources":[]},
|
||||||
];
|
];
|
||||||
|
|
||||||
tasks.forEach((e, i) => {
|
tasks.forEach((e, i) => {
|
||||||
@ -182,7 +183,7 @@ textarea {
|
|||||||
window.project1.Clear();
|
window.project1.Clear();
|
||||||
|
|
||||||
var tasks = [
|
var tasks = [
|
||||||
{"ID": 1, "Name": "task a","StartDelay": 0,"Duration": Math.randomN(0, 28),"PredecessorTaskID": null,"IsCollated": false,"CollatedTaskID": null},
|
{"ID": 1, "Name": "task a","StartDelay": 0,"Duration": Math.randomN(0, 28),"PredecessorTaskID": null,"IsCollated": false,"CollatedTaskID": null},
|
||||||
{"ID": 2,"Name": "task b","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": 1,"IsCollated": false,"CollatedTaskID": null},
|
{"ID": 2,"Name": "task b","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": 1,"IsCollated": false,"CollatedTaskID": null},
|
||||||
{"ID": 5,"Name": "task b1","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": 2,"IsCollated": true,"CollatedTaskID": null},
|
{"ID": 5,"Name": "task b1","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": 2,"IsCollated": true,"CollatedTaskID": null},
|
||||||
{"ID": 6,"Name": "task b11","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": null,"IsCollated": false,"CollatedTaskID": 5},
|
{"ID": 6,"Name": "task b11","StartDelay": Math.randomN(0, 5),"Duration": Math.randomN(0, 28),"PredecessorTaskID": null,"IsCollated": false,"CollatedTaskID": 5},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "LiteRyzJS/Project",
|
"name": "LiteRyzJS/Project",
|
||||||
"version": "0.2.0.256",
|
"version": "0.2.0.508",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"css-loader": "^7.1.2",
|
"css-loader": "^7.1.2",
|
||||||
"sass": "^1.77.8",
|
"sass": "^1.77.8",
|
||||||
|
@ -298,7 +298,7 @@ class GanttChart {
|
|||||||
style = a.Options.Row.CollatedTask;
|
style = a.Options.Row.CollatedTask;
|
||||||
} else if (a.Tasks[i].CollatedTaskID != null) {
|
} else if (a.Tasks[i].CollatedTaskID != null) {
|
||||||
style = a.Options.Row.ChildTask;
|
style = a.Options.Row.ChildTask;
|
||||||
} else if (a.Tasks[i].PredecessorTaskNo == null) {
|
} else if (a.Tasks[i].PredecessorTaskID == null) {
|
||||||
style = a.Options.Row.OrphanTask;
|
style = a.Options.Row.OrphanTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ class GanttChart {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (a.Tasks[i].PredecessorTaskNo == null) {
|
if (a.Tasks[i].PredecessorTaskID == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +329,7 @@ class GanttChart {
|
|||||||
const paddingX = (a.Options.Row.CollatedTask.Height + a.Options.BorderWidth);
|
const paddingX = (a.Options.Row.CollatedTask.Height + a.Options.BorderWidth);
|
||||||
const offsetX = (rectangle.X + paddingX);
|
const offsetX = (rectangle.X + paddingX);
|
||||||
|
|
||||||
const predecessorTask = a.Tasks.first("Order", a.Tasks[i].PredecessorTaskNo);
|
const predecessorTask = a.Tasks.first("ID", a.Tasks[i].PredecessorTaskID);
|
||||||
if (predecessorTask == null) {
|
if (predecessorTask == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
24
src/project/project-node-model.js
Normal file
24
src/project/project-node-model.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import ProjectTaskModel from './project-task-model.js';
|
||||||
|
|
||||||
|
import '../references/extensions.dist.js';
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectNodeModel extends ProjectTaskModel{
|
||||||
|
Order = null;
|
||||||
|
StartDate = null;
|
||||||
|
FinishDate = null;
|
||||||
|
CalcWorkHours = 0;
|
||||||
|
Level = 0;
|
||||||
|
Tasks = [];
|
||||||
|
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
Object.assign(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ProjectNodeModel;
|
@ -8,7 +8,6 @@ class ProjectPlanner {
|
|||||||
const a = this;
|
const a = this;
|
||||||
|
|
||||||
a.Container = el;
|
a.Container = el;
|
||||||
|
|
||||||
a.Columns = [
|
a.Columns = [
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -20,6 +19,7 @@ class ProjectPlanner {
|
|||||||
"Resource Names",
|
"Resource Names",
|
||||||
null
|
null
|
||||||
];
|
];
|
||||||
|
a.Tasks = [];
|
||||||
|
|
||||||
a.#initialiseComponents();
|
a.#initialiseComponents();
|
||||||
}
|
}
|
||||||
@ -52,6 +52,8 @@ class ProjectPlanner {
|
|||||||
Load(tasks) {
|
Load(tasks) {
|
||||||
const a = this;
|
const a = this;
|
||||||
|
|
||||||
|
a.Tasks = tasks;
|
||||||
|
|
||||||
if (!a.Container.classList.contains("literyzjs-project")) {
|
if (!a.Container.classList.contains("literyzjs-project")) {
|
||||||
a.Container.classList.add("literyzjs-project");
|
a.Container.classList.add("literyzjs-project");
|
||||||
}
|
}
|
||||||
@ -125,7 +127,7 @@ class ProjectPlanner {
|
|||||||
htmlContent += "<td>" + task.Duration + " day" + (parseInt(task.Duration) == 1 ? "" : "s") + "</td>";
|
htmlContent += "<td>" + task.Duration + " day" + (parseInt(task.Duration) == 1 ? "" : "s") + "</td>";
|
||||||
htmlContent += "<td class='c'>" + new Date(task.StartDate).toLocaleDateString() + "</td>";
|
htmlContent += "<td class='c'>" + new Date(task.StartDate).toLocaleDateString() + "</td>";
|
||||||
htmlContent += "<td class='c'>" + new Date(task.FinishDate).toLocaleDateString() + "</td>";
|
htmlContent += "<td class='c'>" + new Date(task.FinishDate).toLocaleDateString() + "</td>";
|
||||||
htmlContent += "<td class='c'>" + (task.PredecessorTaskNo ?? "") + "</td>";
|
htmlContent += "<td class='c'>" + a.#findTaskNo(task.PredecessorTaskID) + "</td>";
|
||||||
htmlContent += "<td></td>";
|
htmlContent += "<td></td>";
|
||||||
htmlContent += "<td></td>";
|
htmlContent += "<td></td>";
|
||||||
htmlContent += "</tr>";
|
htmlContent += "</tr>";
|
||||||
@ -133,6 +135,18 @@ class ProjectPlanner {
|
|||||||
return htmlContent;
|
return htmlContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#findTaskNo(id) {
|
||||||
|
const a = this;
|
||||||
|
|
||||||
|
if (id == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = a.Tasks.first("ID", id);
|
||||||
|
|
||||||
|
return (item == null) ? "" : item.Order;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
26
src/project/project-task-model.js
Normal file
26
src/project/project-task-model.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import '../references/extensions.dist.js';
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTaskModel {
|
||||||
|
ID = null;
|
||||||
|
Name = "";
|
||||||
|
Description = "";
|
||||||
|
Tag = null;
|
||||||
|
StartDelay = 0; // Days
|
||||||
|
Duration = 1; // Days
|
||||||
|
PredecessorTaskID = null;
|
||||||
|
IsCollated = false;
|
||||||
|
CollatedTaskID = null;
|
||||||
|
ActuWorkHours = null;
|
||||||
|
Progress = 0;
|
||||||
|
Resources = [];
|
||||||
|
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
Object.assign(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ProjectTaskModel;
|
@ -1,3 +1,6 @@
|
|||||||
|
import ProjectTaskModel from './project-task-model.js';
|
||||||
|
import ProjectNodeModel from './project-node-model.js';
|
||||||
|
|
||||||
import '../references/extensions.dist.js';
|
import '../references/extensions.dist.js';
|
||||||
|
|
||||||
|
|
||||||
@ -6,33 +9,12 @@ class Project {
|
|||||||
const a = this;
|
const a = this;
|
||||||
const _options = Object.assign(a.DefaultOptions, options);
|
const _options = Object.assign(a.DefaultOptions, options);
|
||||||
|
|
||||||
a.Debug = false;
|
a.Debug = true;
|
||||||
a.Project = _options;
|
a.Project = _options;
|
||||||
a.Tasks = [];
|
a.Tasks = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
get NewTask() {
|
|
||||||
return {
|
|
||||||
// Order: null,
|
|
||||||
ID: null,
|
|
||||||
Name: "",
|
|
||||||
Description: "",
|
|
||||||
Tag: null,
|
|
||||||
// StartDate: null, // new Date(),
|
|
||||||
// FinishDate: null, // new Date(),
|
|
||||||
StartDelay: 0, // Days
|
|
||||||
Duration: 1, // Days
|
|
||||||
PredecessorTaskID: null,
|
|
||||||
IsCollated: false,
|
|
||||||
CollatedTaskID: null,
|
|
||||||
// CalcWorkHours: 0,
|
|
||||||
ActuWorkHours: null,
|
|
||||||
Progress: 0,
|
|
||||||
Resources: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get StartDate() {
|
get StartDate() {
|
||||||
const a = this;
|
const a = this;
|
||||||
|
|
||||||
@ -72,35 +54,11 @@ class Project {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get #newTaskNode() {
|
|
||||||
return {
|
|
||||||
Order: null,
|
|
||||||
ID: null,
|
|
||||||
Name: "",
|
|
||||||
Description: "",
|
|
||||||
Tag: null,
|
|
||||||
StartDate: null, // new Date(),
|
|
||||||
FinishDate: null, // new Date(),
|
|
||||||
StartDelay: 0, // Days
|
|
||||||
Duration: 1, // Days
|
|
||||||
PredecessorTaskID: null,
|
|
||||||
IsCollated: false,
|
|
||||||
CollatedTaskID: null,
|
|
||||||
CalcWorkHours: 0,
|
|
||||||
ActuWorkHours: null,
|
|
||||||
Progress: 0,
|
|
||||||
Resources: [],
|
|
||||||
Level: 0,
|
|
||||||
PredecessorTaskNo: null,
|
|
||||||
Tasks: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AddTask(task) {
|
AddTask(task) {
|
||||||
const a = this;
|
const a = this;
|
||||||
const newTask = Object.assign(a.NewTask, task);
|
const newTask = new ProjectTaskModel(task);
|
||||||
const newTaskNode = Object.assign(a.#newTaskNode, newTask);
|
const newTaskNode = new ProjectNodeModel(newTask);
|
||||||
|
|
||||||
if ((newTaskNode.PredecessorTaskID == null) && (newTaskNode.CollatedTaskID == null)) {
|
if ((newTaskNode.PredecessorTaskID == null) && (newTaskNode.CollatedTaskID == null)) {
|
||||||
a.Tasks.push(newTaskNode);
|
a.Tasks.push(newTaskNode);
|
||||||
@ -232,19 +190,18 @@ class Project {
|
|||||||
a.Sort();
|
a.Sort();
|
||||||
|
|
||||||
// Get flat references
|
// Get flat references
|
||||||
let result = a.Tasks.flatten("Tasks");
|
let allTasks = a.Tasks.flatten("Tasks");
|
||||||
|
|
||||||
// Reset calculated values
|
// Reset calculated values
|
||||||
for (var i=0; i<result.length; i++) {
|
for (var i=0; i<allTasks.length; i++) {
|
||||||
result[i].Order = (i + 1);
|
allTasks[i].Order = (i + 1);
|
||||||
result[i].StartDate = null;
|
allTasks[i].StartDate = null;
|
||||||
result[i].FinishDate = null;
|
allTasks[i].FinishDate = null;
|
||||||
result[i].CalcWorkHours = null;
|
allTasks[i].CalcWorkHours = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum 128 rounds
|
for (var x=0; x<16; x++) {
|
||||||
for (var x=0; x<128; x++) {
|
let pendingCount = allTasks.countMany(
|
||||||
let pendingCount = result.copy().countMany(
|
|
||||||
{ propName: "StartDate", value: null },
|
{ propName: "StartDate", value: null },
|
||||||
{ propName: "FinishDate", value: null }
|
{ propName: "FinishDate", value: null }
|
||||||
);
|
);
|
||||||
@ -257,81 +214,11 @@ class Project {
|
|||||||
|
|
||||||
a.#log("Round " + (x + 1));
|
a.#log("Round " + (x + 1));
|
||||||
|
|
||||||
for (var i=0; i<result.length; i++) {
|
a.#recalculateTask(allTasks, a.Tasks);
|
||||||
const nodeType = a.GetNodeType(result[i]);
|
|
||||||
|
|
||||||
switch (nodeType) {
|
|
||||||
case 1: // task no-parent/root
|
|
||||||
result[i].StartDate = Date.addDays(a.Project.StartDate, result[i].StartDelay);
|
|
||||||
result[i].FinishDate = Date.addDays(result[i].StartDate, result[i].Duration);
|
|
||||||
break;
|
|
||||||
case 2: // task no-parent/root, collated/group
|
|
||||||
result[i].StartDate = Date.addDays(a.Project.StartDate, result[i].StartDelay);
|
|
||||||
result[i].Progress = 0;
|
|
||||||
|
|
||||||
// update finish date, if possible
|
|
||||||
a.#recalculateCollatedTask(result, i);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 3: // task with parent
|
|
||||||
const node3 = result.first("ID", result[i].PredecessorTaskID);
|
|
||||||
if (node3 != null) {
|
|
||||||
if (node3.FinishDate != null) {
|
|
||||||
result[i].StartDate = Date.addDays(node3.FinishDate, result[i].StartDelay);
|
|
||||||
result[i].FinishDate = Date.addDays(result[i].StartDate, result[i].Duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 4: // task with parent, collated/group
|
|
||||||
const node4 = result.first("ID", result[i].PredecessorTaskID);
|
|
||||||
if (node4 != null) {
|
|
||||||
if (node4.FinishDate != null) {
|
|
||||||
result[i].StartDate = Date.addDays(node4.FinishDate, result[i].StartDelay);
|
|
||||||
result[i].Progress = 0;
|
|
||||||
|
|
||||||
// update finish date, if possible
|
|
||||||
a.#recalculateCollatedTask(result, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 5: // sub-task
|
|
||||||
const node5 = result.first("ID", result[i].CollatedTaskID);
|
|
||||||
if (node5 != null) {
|
|
||||||
if (node5.StartDate != null) {
|
|
||||||
result[i].StartDate = Date.addDays(node5.StartDate, result[i].StartDelay);
|
|
||||||
result[i].FinishDate = Date.addDays(result[i].StartDate, result[i].Duration);
|
|
||||||
result[i].Level = (node5.Level + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 6: // sub-task, collated/group
|
|
||||||
const node6 = result.first("ID", result[i].CollatedTaskID);
|
|
||||||
if (node6 != null) {
|
|
||||||
if (node6.StartDate != null) {
|
|
||||||
result[i].StartDate = Date.addDays(node6.StartDate, result[i].StartDelay);
|
|
||||||
result[i].Progress = 0;
|
|
||||||
result[i].Level = (node6.Level + 1);
|
|
||||||
|
|
||||||
// update finish date, if possible
|
|
||||||
a.#recalculateCollatedTask(result, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default: // orphan
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate work-hours
|
// Calculate work-hours
|
||||||
a.#recalculateWorkHours(result);
|
a.#recalculateWorkHours(allTasks);
|
||||||
|
|
||||||
// Calculate predecessor
|
|
||||||
a.#recalculatePredecessorTaskNo(result);
|
|
||||||
|
|
||||||
return isSuccess;
|
return isSuccess;
|
||||||
}
|
}
|
||||||
@ -378,51 +265,75 @@ class Project {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#recalculatePredecessorTaskNo(array) {
|
#recalculateTask(allTasks, tasks) {
|
||||||
const a = this;
|
const a = this;
|
||||||
|
|
||||||
for (var i=0; i<array.length; i++) {
|
for (let i=0; i<tasks.length; i++) {
|
||||||
if (array[i].PredecessorTaskID == null) {
|
const task = tasks[i];
|
||||||
continue;
|
|
||||||
|
a.#log(task.Name);
|
||||||
|
|
||||||
|
if (task.PredecessorTaskID != null) {
|
||||||
|
const parentTask = allTasks.first("ID", task.PredecessorTaskID);
|
||||||
|
if (parentTask != null) {
|
||||||
|
if (parentTask.FinishDate != null) {
|
||||||
|
task.StartDate = Date.addDays(parentTask.FinishDate, task.StartDelay);
|
||||||
|
|
||||||
|
a.#log("> Set StartDate from Predecessor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (task.CollatedTaskID != null) {
|
||||||
|
const groupTask = allTasks.first("ID", task.CollatedTaskID);
|
||||||
|
if (groupTask != null) {
|
||||||
|
if (groupTask.StartDate != null) {
|
||||||
|
task.StartDate = Date.addDays(groupTask.StartDate, task.StartDelay);
|
||||||
|
|
||||||
|
a.#log("> Set StartDate from Group");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
task.StartDate = Date.addDays(a.Project.StartDate, task.StartDelay);
|
||||||
|
|
||||||
|
a.#log("> Set StartDate from Project");
|
||||||
}
|
}
|
||||||
|
|
||||||
const predecessor = a.FindTask(array[i].PredecessorTaskID);
|
// if (task.IsCollated) {
|
||||||
if (predecessor == null) {
|
if (task.Tasks.length > 0) {
|
||||||
continue;
|
a.#recalculateTask(allTasks, task.Tasks);
|
||||||
|
|
||||||
|
a.#log("> Calc inner");
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (task.StartDate != null) {
|
||||||
|
if (task.IsCollated) {
|
||||||
|
|
||||||
|
const childTasks = task.Tasks.select("CollatedTaskID", task.ID);
|
||||||
|
if (childTasks.length <= 0) {
|
||||||
|
task.FinishDate = task.StartDate;
|
||||||
|
task.Duration = 0;
|
||||||
|
|
||||||
|
a.#log("> Set FinishDate from Group (0)");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (!childTasks.any("FinishDate", null)) {
|
||||||
|
task.FinishDate = childTasks.orderByDesc("FinishDate")[0].FinishDate;
|
||||||
|
task.Duration = Date.diffDays(task.StartDate, task.FinishDate);
|
||||||
|
|
||||||
|
a.#log("> Set FinishDate from Group");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
task.FinishDate = Date.addDays(task.StartDate, task.Duration);
|
||||||
|
|
||||||
|
a.#log("> Set FinishDate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
array[i].PredecessorTaskNo = predecessor.Order;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#recalculateCollatedTask(array, index) {
|
|
||||||
let node2 = array.select("CollatedTaskID", array[index].ID);
|
|
||||||
if (node2.length <= 0) {
|
|
||||||
// No children
|
|
||||||
array[index].Duration = 0;
|
|
||||||
|
|
||||||
return new Date(array[index].StartDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not ready, calculation pending
|
|
||||||
if (node2.any("FinishDate", null)) {
|
|
||||||
array[index].Duration = 0;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let node2FinishDate = new Date(array[index].StartDate);
|
|
||||||
node2.forEach(e => {
|
|
||||||
if (e.FinishDate > node2FinishDate) {
|
|
||||||
node2FinishDate = e.FinishDate;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
array[index].Progress = Math.average(node2.toList("Progress"));
|
|
||||||
array[index].FinishDate = new Date(node2FinishDate);
|
|
||||||
array[index].Duration = Date.diffDays(array[index].StartDate, array[index].FinishDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
#sortNode(node) {
|
#sortNode(node) {
|
||||||
const a = this;
|
const a = this;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user