diff --git a/demo.html b/demo.html index 9fdc571..bfda647 100644 --- a/demo.html +++ b/demo.html @@ -138,15 +138,16 @@ textarea { window.project1.Clear(); 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}, - {"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}, - {"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}, - {"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}, - {"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}, - {"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}, - {"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}, - {"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}, - {"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":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":[]}, + {"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":[]}, + {"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":[]}, + {"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":[]}, + {"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":[]}, + {"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":[]}, + {"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":[]}, + {"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":[]}, + {"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) => { @@ -182,7 +183,7 @@ textarea { window.project1.Clear(); 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": 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}, diff --git a/src/project/gantt-chart.js b/src/project/gantt-chart.js index 4413493..1dbe292 100644 --- a/src/project/gantt-chart.js +++ b/src/project/gantt-chart.js @@ -298,7 +298,7 @@ class GanttChart { style = a.Options.Row.CollatedTask; } else if (a.Tasks[i].CollatedTaskID != null) { style = a.Options.Row.ChildTask; - } else if (a.Tasks[i].PredecessorTaskNo == null) { + } else if (a.Tasks[i].PredecessorTaskID == null) { style = a.Options.Row.OrphanTask; } @@ -320,7 +320,7 @@ class GanttChart { continue; } - if (a.Tasks[i].PredecessorTaskNo == null) { + if (a.Tasks[i].PredecessorTaskID == null) { continue; } @@ -329,7 +329,7 @@ class GanttChart { const paddingX = (a.Options.Row.CollatedTask.Height + a.Options.BorderWidth); 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) { continue; } diff --git a/src/project/project-node-model.js b/src/project/project-node-model.js new file mode 100644 index 0000000..4d27008 --- /dev/null +++ b/src/project/project-node-model.js @@ -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; \ No newline at end of file diff --git a/src/project/project-planner.js b/src/project/project-planner.js index b75cfc3..0de5d43 100644 --- a/src/project/project-planner.js +++ b/src/project/project-planner.js @@ -8,7 +8,6 @@ class ProjectPlanner { const a = this; a.Container = el; - a.Columns = [ null, null, @@ -20,6 +19,7 @@ class ProjectPlanner { "Resource Names", null ]; + a.Tasks = []; a.#initialiseComponents(); } @@ -52,6 +52,8 @@ class ProjectPlanner { Load(tasks) { const a = this; + a.Tasks = tasks; + if (!a.Container.classList.contains("literyzjs-project")) { a.Container.classList.add("literyzjs-project"); } @@ -125,7 +127,7 @@ class ProjectPlanner { htmlContent += "" + task.Duration + " day" + (parseInt(task.Duration) == 1 ? "" : "s") + ""; htmlContent += "" + new Date(task.StartDate).toLocaleDateString() + ""; htmlContent += "" + new Date(task.FinishDate).toLocaleDateString() + ""; - htmlContent += "" + (task.PredecessorTaskNo ?? "") + ""; + htmlContent += "" + a.#findTaskNo(task.PredecessorTaskID) + ""; htmlContent += ""; htmlContent += ""; htmlContent += ""; @@ -133,6 +135,18 @@ class ProjectPlanner { return htmlContent; } + #findTaskNo(id) { + const a = this; + + if (id == null) { + return ""; + } + + const item = a.Tasks.first("ID", id); + + return (item == null) ? "" : item.Order; + } + } diff --git a/src/project/project-task-model.js b/src/project/project-task-model.js new file mode 100644 index 0000000..091722f --- /dev/null +++ b/src/project/project-task-model.js @@ -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; \ No newline at end of file diff --git a/src/project/project.js b/src/project/project.js index 682f6e0..9529a36 100644 --- a/src/project/project.js +++ b/src/project/project.js @@ -1,3 +1,6 @@ +import ProjectTaskModel from './project-task-model.js'; +import ProjectNodeModel from './project-node-model.js'; + import '../references/extensions.dist.js'; @@ -12,27 +15,6 @@ class Project { } - 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() { 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) { const a = this; - const newTask = Object.assign(a.NewTask, task); - const newTaskNode = Object.assign(a.#newTaskNode, newTask); + const newTask = new ProjectTaskModel(task); + const newTaskNode = new ProjectNodeModel(newTask); if ((newTaskNode.PredecessorTaskID == null) && (newTaskNode.CollatedTaskID == null)) { a.Tasks.push(newTaskNode); @@ -330,9 +288,6 @@ class Project { // Calculate work-hours a.#recalculateWorkHours(result); - // Calculate predecessor - a.#recalculatePredecessorTaskNo(result); - return isSuccess; } @@ -378,23 +333,6 @@ class Project { } } - #recalculatePredecessorTaskNo(array) { - const a = this; - - for (var i=0; i