Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "until" keyword in gantt charts #5224

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions docs/syntax/gantt.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -114,20 +114,25 @@ 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
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
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
Expand Down
29 changes: 29 additions & 0 deletions packages/mermaid/src/diagrams/gantt/ganttDb.js
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,35 @@
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());
fzag marked this conversation as resolved.
Show resolved Hide resolved

if (untilStatement !== null) {
// check all until ids and take the earliest
let earliestStartingTask = null;
untilStatement[1].split(' ').forEach(function (id) {
fzag marked this conversation as resolved.
Show resolved Hide resolved
let task = findTaskById(id);
if (task !== undefined) {
if (!earliestStartingTask) {
earliestStartingTask = task;
} else {
if (task.startTime < earliestStartingTask.startTime) {
earliestStartingTask = task;
}

Check warning on line 361 in packages/mermaid/src/diagrams/gantt/ganttDb.js

View check run for this annotation

Codecov / codecov/patch

packages/mermaid/src/diagrams/gantt/ganttDb.js#L360-L361

Added lines #L360 - L361 were not covered by tests
}
}
});

if (!earliestStartingTask) {
fzag marked this conversation as resolved.
Show resolved Hide resolved
const dt = new Date();
dt.setHours(0, 0, 0, 0);
return dt;

Check warning on line 369 in packages/mermaid/src/diagrams/gantt/ganttDb.js

View check run for this annotation

Codecov / codecov/patch

packages/mermaid/src/diagrams/gantt/ganttDb.js#L367-L369

Added lines #L367 - L369 were not covered by tests
fzag marked this conversation as resolved.
Show resolved Hide resolved
} else {
return earliestStartingTask.startTime;
}
}

// Check for actual date
let mDate = dayjs(str, dateFormat.trim(), true);
if (mDate.isValid()) {
Expand Down
56 changes: 54 additions & 2 deletions packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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');
sidharthv96 marked this conversation as resolved.
Show resolved Hide resolved

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, 1, 5));
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, 0, 11));
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');
Expand Down
9 changes: 7 additions & 2 deletions packages/mermaid/src/docs/syntax/gantt.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -63,13 +63,18 @@ 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
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
Expand Down
Loading