From 5f56db6f6e85e61d72f3c275b3649d7b3ec1d1c2 Mon Sep 17 00:00:00 2001 From: Abhijeet Pathak Date: Sat, 20 Jun 2020 18:03:48 +0530 Subject: [PATCH 1/4] Fix for the issue 1005 (https://github.com/mermaid-js/mermaid/issues/1005) A new attribute 'order' has been introduced in the task which records the serial number of task in the script. In ganttRenderer.js, the tasks are sorted by stratTime attribute. The function which calculates 'y' for task rectangles, lables etc. has been modified to correctly position it. --- src/diagrams/gantt/ganttDb.js | 7 +++++++ src/diagrams/gantt/ganttRenderer.js | 24 +++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/diagrams/gantt/ganttDb.js b/src/diagrams/gantt/ganttDb.js index 0c01ab257..c8e138526 100644 --- a/src/diagrams/gantt/ganttDb.js +++ b/src/diagrams/gantt/ganttDb.js @@ -17,6 +17,9 @@ const tags = ['active', 'done', 'crit', 'milestone']; let funs = []; let inclusiveEndDates = false; +// The serial order of the task in the script +let lastOrder = 0; + export const clear = function() { sections = []; tasks = []; @@ -32,6 +35,7 @@ export const clear = function() { todayMarker = ''; excludes = []; inclusiveEndDates = false; + lastOrder = 0; }; export const setAxisFormat = function(txt) { @@ -374,6 +378,9 @@ export const addTask = function(descr, data) { rawTask.done = taskInfo.done; rawTask.crit = taskInfo.crit; rawTask.milestone = taskInfo.milestone; + rawTask.order = lastOrder; + + lastOrder++; const pos = rawTasks.push(rawTask); diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index ad902bf20..99d0c5642 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -80,6 +80,23 @@ export const draw = function(text, id) { categories = checkUnique(categories); + function taskCompare(a, b) { + const taskA = a.startTime; + const taskB = b.startTime; + + let result = 0; + if (taskA > taskB) { + result = 1; + } else if (taskA < taskB) { + result = -1; + } + return result; + } + + // Sort the task array using the above taskCompare() so that + // tasks are created based on their order of startTime + taskArray.sort(taskCompare); + makeGant(taskArray, w, h); if (typeof conf.useWidth !== 'undefined') { elem.setAttribute('width', w); @@ -119,7 +136,7 @@ export const draw = function(text, id) { .append('rect') .attr('x', 0) .attr('y', function(d, i) { - return i * theGap + theTopPad - 2; + return d.order * theGap + theTopPad - 2; }) .attr('width', function() { return w - conf.rightPadding / 2; @@ -160,7 +177,7 @@ export const draw = function(text, id) { return timeScale(d.startTime) + theSidePad; }) .attr('y', function(d, i) { - return i * theGap + theTopPad; + return d.order * theGap + theTopPad; }) .attr('width', function(d) { if (d.milestone) { @@ -263,7 +280,7 @@ export const draw = function(text, id) { } }) .attr('y', function(d, i) { - return i * theGap + conf.barHeight / 2 + (conf.fontSize / 2 - 2) + theTopPad; + return d.order * theGap + conf.barHeight / 2 + (conf.fontSize / 2 - 2) + theTopPad; }) .attr('text-height', theBarHeight) .attr('class', function(d) { @@ -280,6 +297,7 @@ export const draw = function(text, id) { } let secNum = 0; + console.log(conf); for (let i = 0; i < categories.length; i++) { if (d.type === categories[i]) { secNum = i % conf.numberSectionStyles; From e515c7beb16047cb5f54e11599445a27f946e039 Mon Sep 17 00:00:00 2001 From: Abhijeet Pathak Date: Sat, 20 Jun 2020 18:39:19 +0530 Subject: [PATCH 2/4] Fxed liniting issues. --- src/diagrams/gantt/ganttRenderer.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/diagrams/gantt/ganttRenderer.js b/src/diagrams/gantt/ganttRenderer.js index 99d0c5642..98e6391a9 100644 --- a/src/diagrams/gantt/ganttRenderer.js +++ b/src/diagrams/gantt/ganttRenderer.js @@ -83,7 +83,6 @@ export const draw = function(text, id) { function taskCompare(a, b) { const taskA = a.startTime; const taskB = b.startTime; - let result = 0; if (taskA > taskB) { result = 1; @@ -136,7 +135,9 @@ export const draw = function(text, id) { .append('rect') .attr('x', 0) .attr('y', function(d, i) { - return d.order * theGap + theTopPad - 2; + // Ignore the incoming i value and use our order instead + i = d.order; + return i * theGap + theTopPad - 2; }) .attr('width', function() { return w - conf.rightPadding / 2; @@ -177,7 +178,9 @@ export const draw = function(text, id) { return timeScale(d.startTime) + theSidePad; }) .attr('y', function(d, i) { - return d.order * theGap + theTopPad; + // Ignore the incoming i value and use our order instead + i = d.order; + return i * theGap + theTopPad; }) .attr('width', function(d) { if (d.milestone) { @@ -280,7 +283,9 @@ export const draw = function(text, id) { } }) .attr('y', function(d, i) { - return d.order * theGap + conf.barHeight / 2 + (conf.fontSize / 2 - 2) + theTopPad; + // Ignore the incoming i value and use our order instead + i = d.order; + return i * theGap + conf.barHeight / 2 + (conf.fontSize / 2 - 2) + theTopPad; }) .attr('text-height', theBarHeight) .attr('class', function(d) { From 2840c98bb029f2200cc78ecdb857626146da85e3 Mon Sep 17 00:00:00 2001 From: Abhijeet Pathak Date: Tue, 23 Jun 2020 22:32:49 +0530 Subject: [PATCH 3/4] Added test case for preserving creation order of tasks --- src/diagrams/gantt/ganttDb.spec.js | 131 +++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/src/diagrams/gantt/ganttDb.spec.js b/src/diagrams/gantt/ganttDb.spec.js index 67e150c15..c655889f8 100644 --- a/src/diagrams/gantt/ganttDb.spec.js +++ b/src/diagrams/gantt/ganttDb.spec.js @@ -176,6 +176,137 @@ describe('when using the ganttDb', function() { expect(tasks[6].task).toEqual('test7'); }); + it('should create tasks in the order days - top to bottom and letft to right', function() { + ganttDb.setTitle('Project Execution'); + ganttDb.setDateFormat('YYYY-MM-DD'); + ganttDb.addSection('section A section'); + ganttDb.addTask('Completed task', 'done, des1, 2014-01-06,2014-01-08'); + ganttDb.addTask('Active task', 'active, des2, 2014-01-09, 3d'); + ganttDb.addTask('Future task', 'des3, after des2, 5d'); + ganttDb.addTask('Future task2', 'des4, after des3, 5d'); + + ganttDb.addSection('section Critical tasks'); + ganttDb.addTask('Completed task in the critical line', 'crit, done, 2014-01-06,24h'); + ganttDb.addTask('Implement parser and jison', 'crit, done, after des1, 2d'); + ganttDb.addTask('Create tests for parser', 'crit, active, 3d'); + ganttDb.addTask('Future task in critical line', 'crit, 5d'); + ganttDb.addTask('Create tests for renderer', '2d'); + ganttDb.addTask('Add to mermaid', '1d'); + + ganttDb.addSection('section Documentation'); + ganttDb.addTask('Describe gantt syntax', 'active, a1, after des1, 3d'); + ganttDb.addTask('Add gantt diagram to demo page', 'after a1 , 20h'); + ganttDb.addTask('Add another diagram to demo page', 'doc1, after a1 , 48h'); + + ganttDb.addSection('section Last section'); + ganttDb.addTask('Describe gantt syntax', 'after doc1, 3d'); + ganttDb.addTask('Add gantt diagram to demo page', '20h'); + ganttDb.addTask('Add another diagram to demo page', '48h'); + + const tasks = ganttDb.getTasks(); + + // Section - A section + expect(tasks[0].startTime).toEqual(moment('2014-01-06', 'YYYY-MM-DD').toDate()); + expect(tasks[0].endTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[0].order).toEqual(0); + expect(tasks[0].id).toEqual('des1'); + expect(tasks[0].task).toEqual('Completed task'); + + expect(tasks[1].startTime).toEqual(moment('2014-01-09', 'YYYY-MM-DD').toDate()); + expect(tasks[1].endTime).toEqual(moment('2014-01-12', 'YYYY-MM-DD').toDate()); + expect(tasks[1].order).toEqual(1); + expect(tasks[1].id).toEqual('des2'); + expect(tasks[1].task).toEqual('Active task'); + + expect(tasks[2].startTime).toEqual(moment('2014-01-12', 'YYYY-MM-DD').toDate()); + expect(tasks[2].endTime).toEqual(moment('2014-01-17', 'YYYY-MM-DD').toDate()); + expect(tasks[2].order).toEqual(2); + expect(tasks[2].id).toEqual('des3'); + expect(tasks[2].task).toEqual('Future task'); + + expect(tasks[3].startTime).toEqual(moment('2014-01-17', 'YYYY-MM-DD').toDate()); + expect(tasks[3].endTime).toEqual(moment('2014-01-22', 'YYYY-MM-DD').toDate()); + expect(tasks[3].order).toEqual(3); + expect(tasks[3].id).toEqual('des4'); + expect(tasks[3].task).toEqual('Future task2'); + + // Section - Critical tasks + expect(tasks[4].startTime).toEqual(moment('2014-01-06', 'YYYY-MM-DD').toDate()); + expect(tasks[4].endTime).toEqual(moment('2014-01-07', 'YYYY-MM-DD').toDate()); + expect(tasks[4].order).toEqual(4); + expect(tasks[4].id).toEqual('task1'); + expect(tasks[4].task).toEqual('Completed task in the critical line'); + + expect(tasks[5].startTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[5].endTime).toEqual(moment('2014-01-10', 'YYYY-MM-DD').toDate()); + expect(tasks[5].order).toEqual(5); + expect(tasks[5].id).toEqual('task2'); + expect(tasks[5].task).toEqual('Implement parser and jison'); + + expect(tasks[6].startTime).toEqual(moment('2014-01-10', 'YYYY-MM-DD').toDate()); + expect(tasks[6].endTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[6].order).toEqual(6); + expect(tasks[6].id).toEqual('task3'); + expect(tasks[6].task).toEqual('Create tests for parser'); + + expect(tasks[7].startTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[7].endTime).toEqual(moment('2014-01-18', 'YYYY-MM-DD').toDate()); + expect(tasks[7].order).toEqual(7); + expect(tasks[7].id).toEqual('task4'); + expect(tasks[7].task).toEqual('Future task in critical line'); + + expect(tasks[8].startTime).toEqual(moment('2014-01-18', 'YYYY-MM-DD').toDate()); + expect(tasks[8].endTime).toEqual(moment('2014-01-20', 'YYYY-MM-DD').toDate()); + expect(tasks[8].order).toEqual(8); + expect(tasks[8].id).toEqual('task5'); + expect(tasks[8].task).toEqual('Create tests for renderer'); + + expect(tasks[9].startTime).toEqual(moment('2014-01-20', 'YYYY-MM-DD').toDate()); + expect(tasks[9].endTime).toEqual(moment('2014-01-21', 'YYYY-MM-DD').toDate()); + expect(tasks[9].order).toEqual(9); + expect(tasks[9].id).toEqual('task6'); + expect(tasks[9].task).toEqual('Add to mermaid'); + + // Section - Documentation + expect(tasks[10].startTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[10].endTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[10].order).toEqual(10); + expect(tasks[10].id).toEqual('a1'); + expect(tasks[10].task).toEqual('Describe gantt syntax'); + + expect(tasks[11].startTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[11].endTime).toEqual(moment('2014-01-11 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); + expect(tasks[11].order).toEqual(11); + expect(tasks[11].id).toEqual('task7'); + expect(tasks[11].task).toEqual('Add gantt diagram to demo page'); + + expect(tasks[12].startTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[12].endTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[12].order).toEqual(12); + expect(tasks[12].id).toEqual('doc1'); + expect(tasks[12].task).toEqual('Add another diagram to demo page'); + + // Section - Last section + expect(tasks[13].startTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[13].endTime).toEqual(moment('2014-01-16', 'YYYY-MM-DD').toDate()); + expect(tasks[13].order).toEqual(13); + expect(tasks[13].id).toEqual('task8'); + expect(tasks[13].task).toEqual('Describe gantt syntax'); + + expect(tasks[14].startTime).toEqual(moment('2014-01-16', 'YYYY-MM-DD').toDate()); + expect(tasks[14].endTime).toEqual(moment('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); + expect(tasks[14].order).toEqual(14); + expect(tasks[14].id).toEqual('task9'); + expect(tasks[14].task).toEqual('Add gantt diagram to demo page'); + + expect(tasks[15].startTime).toEqual(moment('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); + expect(tasks[15].endTime).toEqual(moment('2014-01-18 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); + expect(tasks[15].order).toEqual(15); + expect(tasks[15].id).toEqual('task10'); + expect(tasks[15].task).toEqual('Add another diagram to demo page'); + }); + + it('should work when end date is the 31st', function() { ganttDb.setDateFormat('YYYY-MM-DD'); ganttDb.addSection('Task endTime is on the 31st day of the month'); From 3c727bc46f167932082497e5ba946a57edd9b518 Mon Sep 17 00:00:00 2001 From: abhijeet-pathak <56287990+abhijeet-pathak@users.noreply.github.com> Date: Wed, 24 Jun 2020 14:51:08 +0530 Subject: [PATCH 4/4] Corrected the test case description --- src/diagrams/gantt/ganttDb.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/diagrams/gantt/ganttDb.spec.js b/src/diagrams/gantt/ganttDb.spec.js index c655889f8..4ece88fa3 100644 --- a/src/diagrams/gantt/ganttDb.spec.js +++ b/src/diagrams/gantt/ganttDb.spec.js @@ -176,7 +176,7 @@ describe('when using the ganttDb', function() { expect(tasks[6].task).toEqual('test7'); }); - it('should create tasks in the order days - top to bottom and letft to right', function() { + it('should maintain the order in which tasks are created', function() { ganttDb.setTitle('Project Execution'); ganttDb.setDateFormat('YYYY-MM-DD'); ganttDb.addSection('section A section');