From 8f2c395712abdbc4adda0162801a79b339bd9a85 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 14 Jul 2024 16:01:05 -0700 Subject: [PATCH] Add Gantt support for 'today' Feature request: https://github.com/mermaid-js/mermaid/issues/2853 --- cypress/integration/rendering/gantt.spec.js | 30 ++++++++++ docs/syntax/gantt.md | 60 +++++++++++++++++++ .../mermaid/src/diagrams/gantt/ganttDb.js | 12 ++++ .../src/diagrams/gantt/ganttRenderer.js | 19 +++++- .../src/diagrams/gantt/parser/gantt.jison | 2 + .../src/diagrams/gantt/parser/gantt.spec.js | 8 +++ packages/mermaid/src/docs/syntax/gantt.md | 33 ++++++++++ 7 files changed, 163 insertions(+), 1 deletion(-) diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index a0c2dbcb9e..ab090a8911 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -208,6 +208,36 @@ describe('Gantt diagram', () => { ); }); + it('should position a dateFormat-based today marker', () => { + imgSnapshotTest( + ` + gantt + title Reposition a today marker (using dateFormat) + dateFormat YYYY-MM-DD + today 2024-01-18 + section Project + A task :a1, 2024-01-01, 30d + Another task :after a1, 20d + `, + {} + ); + }); + + it('should position a duration-based today marker', () => { + imgSnapshotTest( + ` + gantt + title Reposition a today marker (using duration) + dateFormat x + axisFormat %L ms + today 19ms + section Section1 + A task: Draw 1: a1, 0, 28ms + `, + {} + ); + }); + it('should handle milliseconds', () => { imgSnapshotTest( ` diff --git a/docs/syntax/gantt.md b/docs/syntax/gantt.md index cdaf0c2acd..85692f7ee2 100644 --- a/docs/syntax/gantt.md +++ b/docs/syntax/gantt.md @@ -338,6 +338,66 @@ gantt > **Warning** > `millisecond` and `second` support was added in v10.3.0 +### Changing Today (v\+) + +By default, the today marker uses the current date. Use `today` to set a custom date, using the `dateFormat`. + +```mermaid-example +gantt + title A Gantt Diagram With Custom Today + dateFormat YYYY-MM-DD + today 2024-01-20 + section Section + A task :a1, 2024-01-01, 30d + Another task :after a1, 20d +``` + +```mermaid +gantt + title A Gantt Diagram With Custom Today + dateFormat YYYY-MM-DD + today 2024-01-20 + section Section + A task :a1, 2024-01-01, 30d + Another task :after a1, 20d +``` + +You can also use a duration: + +```mermaid-example +--- +displayMode: compact +--- +gantt + title A Gantt Diagram With Custom Today (Duration) + dateFormat x + axisFormat %L ms + today 18ms + todayMarker stroke-width:2px,stroke:#FF0,opacity:0.5 + section Graphics + Draw 1: a1, 0, 28ms + Draw 2: after a1, 20ms + section Compute + Kernel: b1, 20, 12ms +``` + +```mermaid +--- +displayMode: compact +--- +gantt + title A Gantt Diagram With Custom Today (Duration) + dateFormat x + axisFormat %L ms + today 18ms + todayMarker stroke-width:2px,stroke:#FF0,opacity:0.5 + section Graphics + Draw 1: a1, 0, 28ms + Draw 2: after a1, 20ms + section Compute + Kernel: b1, 20, 12ms +``` + ## Output in compact mode The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceding YAML settings. diff --git a/packages/mermaid/src/diagrams/gantt/ganttDb.js b/packages/mermaid/src/diagrams/gantt/ganttDb.js index 15c7fab979..346edb27fc 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDb.js +++ b/packages/mermaid/src/diagrams/gantt/ganttDb.js @@ -26,6 +26,7 @@ let dateFormat = ''; let axisFormat = ''; let tickInterval = undefined; let todayMarker = ''; +let today = ''; let includes = []; let excludes = []; let links = new Map(); @@ -57,6 +58,7 @@ export const clear = function () { displayMode = ''; tickInterval = undefined; todayMarker = ''; + today = ''; includes = []; excludes = []; inclusiveEndDates = false; @@ -92,6 +94,14 @@ export const getTodayMarker = function () { return todayMarker; }; +export const setToday = function (txt) { + today = txt; +}; + +export const getToday = function () { + return today; +}; + export const setDateFormat = function (txt) { dateFormat = txt; }; @@ -766,6 +776,8 @@ export default { getTickInterval, setTodayMarker, getTodayMarker, + setToday, + getToday, setAccTitle, getAccTitle, setDiagramTitle, diff --git a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js index a10eb100f4..04469704ad 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js +++ b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js @@ -756,7 +756,24 @@ export const draw = function (text, id, version, diagObj) { } const todayG = svg.append('g').attr('class', 'today'); - const today = new Date(); + + let today = new Date(); + const dateFormat = diagObj.db.getDateFormat(); + const dbToday = diagObj.db.getToday(); + let customToday = dayjs(dbToday, dateFormat.trim(), true); + if (customToday.isValid()) { + today = customToday.toDate(); + } else { + const [durationValue, durationUnit] = diagObj.db.parseDuration(dbToday); + if (!Number.isNaN(durationValue)) { + // let dayjs do the math to support 'ms' and such + customToday = dayjs(0).add(durationValue, durationUnit); + if (customToday.isValid()) { + today = customToday; + } + } + } + const todayLine = todayG.append('line'); todayLine diff --git a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison index f2333ff84e..c4598d5f2d 100644 --- a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison +++ b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison @@ -77,6 +77,7 @@ that id. "includes"\s[^#\n;]+ return 'includes'; "excludes"\s[^#\n;]+ return 'excludes'; "todayMarker"\s[^\n;]+ return 'todayMarker'; +"today"\s[^\n;]+ return 'today'; weekday\s+monday return 'weekday_monday' weekday\s+tuesday return 'weekday_tuesday' weekday\s+wednesday return 'weekday_wednesday' @@ -144,6 +145,7 @@ statement | excludes {yy.setExcludes($1.substr(9));$$=$1.substr(9);} | includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);} | todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);} + | today {yy.setToday($1.substr(6));$$=$1.substr(6);} | weekday | weekend | title {yy.setDiagramTitle($1.substr(6));$$=$1.substr(6);} diff --git a/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js b/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js index 33f91a8825..371a8cab6b 100644 --- a/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js +++ b/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js @@ -48,6 +48,14 @@ describe('when parsing a gantt diagram it', function () { expect(parserFnConstructor(str)).not.toThrow(); expect(ganttDb.setTodayMarker).toHaveBeenCalledWith('off'); }); + it('should handle a today definition', function () { + spyOn(ganttDb, 'setToday'); + const str = + 'gantt\ndateFormat yyyy-mm-dd\ntitle Adding gantt diagram functionality to mermaid\nexcludes weekdays 2019-02-01\ntoday 2019-02-04'; + + expect(parserFnConstructor(str)).not.toThrow(); + expect(ganttDb.setToday).toHaveBeenCalledWith('2019-02-04'); + }); it('should handle a section definition', function () { const str = 'gantt\n' + diff --git a/packages/mermaid/src/docs/syntax/gantt.md b/packages/mermaid/src/docs/syntax/gantt.md index 01a9f041dd..77656e0524 100644 --- a/packages/mermaid/src/docs/syntax/gantt.md +++ b/packages/mermaid/src/docs/syntax/gantt.md @@ -255,6 +255,39 @@ gantt `millisecond` and `second` support was added in v10.3.0 ``` +### Changing Today (v\+) + +By default, the today marker uses the current date. Use `today` to set a custom date, using the `dateFormat`. + +```mermaid-example +gantt + title A Gantt Diagram With Custom Today + dateFormat YYYY-MM-DD + today 2024-01-20 + section Section + A task :a1, 2024-01-01, 30d + Another task :after a1, 20d +``` + +You can also use a duration: + +```mermaid-example +--- +displayMode: compact +--- +gantt + title A Gantt Diagram With Custom Today (Duration) + dateFormat x + axisFormat %L ms + today 18ms + todayMarker stroke-width:2px,stroke:#FF0,opacity:0.5 + section Graphics + Draw 1: a1, 0, 28ms + Draw 2: after a1, 20ms + section Compute + Kernel: b1, 20, 12ms +``` + ## Output in compact mode The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceding YAML settings.