implement until keyword in gantt charts

This commit is contained in:
Franck Zagala
2024-01-22 20:11:27 +00:00
parent b91624cb63
commit cafe932cbc
4 changed files with 99 additions and 8 deletions

View File

@@ -67,8 +67,8 @@ gantt
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
Functionality added :milestone, 2014-01-25, 0d
Add to mermaid :until isadded
Functionality added :milestone, isadded, 2014-01-25, 0d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
@@ -100,8 +100,8 @@ gantt
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
Functionality added :milestone, 2014-01-25, 0d
Add to mermaid :until isadded
Functionality added :milestone, isadded, 2014-01-25, 0d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
@@ -114,6 +114,9 @@ gantt
Add another diagram to demo page :48h
```
> **Note**
> Support for keyword `until` was added in (v\<MERMAID_RELEASE_VERSION>+). This can be used to define a task which is running until some other specific task or milestone starts.
It is possible to set multiple dependencies separated by space:
```mermaid-example
@@ -121,6 +124,7 @@ gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
kiwi :d, 2017-07-20, until b c
```
```mermaid
@@ -128,6 +132,7 @@ gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
kiwi :d, 2017-07-20, until b c
```
### Title

View File

@@ -343,6 +343,35 @@ const parseDuration = function (str) {
const getEndDate = function (prevTime, dateFormat, str, inclusive = false) {
str = str.trim();
// Test for until
const re = /^until\s+([\d\w- ]+)/;
const untilStatement = re.exec(str.trim());
if (untilStatement !== null) {
// check all until ids and take the earliest
let earliestStartingTask = null;
untilStatement[1].split(' ').forEach(function (id) {
let task = findTaskById(id);
if (task !== undefined) {
if (!earliestStartingTask) {
earliestStartingTask = task;
} else {
if (task.startTime < earliestStartingTask.startTime) {
earliestStartingTask = task;
}
}
}
});
if (!earliestStartingTask) {
const dt = new Date();
dt.setHours(0, 0, 0, 0);
return dt;
} else {
return earliestStartingTask.startTime;
}
}
// Check for actual date
let mDate = dayjs(str, dateFormat.trim(), true);
if (mDate.isValid()) {

View File

@@ -140,10 +140,10 @@ describe('when using the ganttDb', function () {
it('should handle relative start date based on id regardless of sections', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('testa1');
ganttDb.addSection('sec1');
ganttDb.addTask('test1', 'id1,2013-01-01,2w');
ganttDb.addTask('test2', 'id2,after id3,1d');
ganttDb.addSection('testa2');
ganttDb.addSection('sec2');
ganttDb.addTask('test3', 'id3,after id1,2d');
const tasks = ganttDb.getTasks();
@@ -158,6 +158,58 @@ describe('when using the ganttDb', function () {
expect(tasks[2].startTime).toEqual(new Date(2013, 0, 15));
expect(tasks[2].endTime).toEqual(new Date(2013, 0, 17));
});
it('should handle relative end date based on id regardless of sections', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('sec1');
ganttDb.addTask('task1', 'id1,2013-01-01,until id3');
ganttDb.addSection('sec2');
ganttDb.addTask('task2', 'id2,2013-01-10,until id3');
ganttDb.addTask('task3', 'id3,2013-02-01,2d');
const tasks = ganttDb.getTasks();
expect(tasks[0].startTime).toEqual(new Date(2013, 0, 1));
expect(tasks[0].endTime).toEqual(new Date(2013, 1, 1));
expect(tasks[0].id).toEqual('id1');
expect(tasks[0].task).toEqual('task1');
expect(tasks[1].id).toEqual('id2');
expect(tasks[1].task).toEqual('task2');
expect(tasks[1].startTime).toEqual(new Date(2013, 0, 10));
expect(tasks[1].endTime).toEqual(new Date(2013, 1, 1));
});
it('should handle relative start date based on multiple id', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('sec1');
ganttDb.addTask('task1', 'id1,after id2 id3 id4,1d');
ganttDb.addTask('task2', 'id2,2013-01-01,1d');
ganttDb.addTask('task3', 'id3,2013-02-01,3d');
ganttDb.addTask('task4', 'id4,2013-02-01,2d');
const tasks = ganttDb.getTasks();
expect(tasks[0].endTime).toEqual(new Date(2013, 0, 2));
expect(tasks[0].id).toEqual('id1');
expect(tasks[0].task).toEqual('task1');
});
it('should handle relative end date based on multiple id', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('sec1');
ganttDb.addTask('task1', 'id1,2013-01-01,until id2 id3 id4');
ganttDb.addTask('task2', 'id2,2013-01-11,1d');
ganttDb.addTask('task3', 'id3,2013-02-10,1d');
ganttDb.addTask('task4', 'id4,2013-02-12,1d');
const tasks = ganttDb.getTasks();
expect(tasks[0].endTime).toEqual(new Date(2013, 1, 10));
expect(tasks[0].id).toEqual('id1');
expect(tasks[0].task).toEqual('task1');
});
it('should ignore weekends', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.setExcludes('weekends 2019-02-06,friday');

View File

@@ -49,8 +49,8 @@ gantt
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
Functionality added :milestone, 2014-01-25, 0d
Add to mermaid :until isadded
Functionality added :milestone, isadded, 2014-01-25, 0d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
@@ -63,6 +63,10 @@ gantt
Add another diagram to demo page :48h
```
```note
Support for keyword `until` was added in (v<MERMAID_RELEASE_VERSION>+). This can be used to define a task which is running until some other specific task or milestone starts.
```
It is possible to set multiple dependencies separated by space:
```mermaid-example
@@ -70,6 +74,7 @@ gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
kiwi :d, 2017-07-20, until b c
```
### Title