diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index 16a70ece0..b75e682c6 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -341,4 +341,130 @@ describe('Gantt diagram', () => { expect(descriptionEl.textContent).to.equal(expectedAccDescription); }); }); + + it('should render a gantt diagram with tick is 15 minutes', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %H:%M + tickInterval 15minute + excludes weekends + + section Section + A task : a1, 2022-10-03, 6h + Another task : after a1, 6h + section Another + Task in sec : 2022-10-03, 3h + another task : 3h + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 6 hours', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %d %H:%M + tickInterval 6hour + excludes weekends + + section Section + A task : a1, 2022-10-03, 1d + Another task : after a1, 2d + section Another + Task in sec : 2022-10-04, 2d + another task : 2d + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 1 day', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %m-%d + tickInterval 1day + excludes weekends + + section Section + A task : a1, 2022-10-01, 30d + Another task : after a1, 20d + section Another + Task in sec : 2022-10-20, 12d + another task : 24d + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 1 week', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %m-%d + tickInterval 1week + excludes weekends + + section Section + A task : a1, 2022-10-01, 30d + Another task : after a1, 20d + section Another + Task in sec : 2022-10-20, 12d + another task : 24d + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 1 month', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %m-%d + tickInterval 1month + excludes weekends + + section Section + A task : a1, 2022-10-01, 30d + Another task : after a1, 20d + section Another + Task in sec : 2022-10-20, 12d + another task : 24d + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 1 day and topAxis is true', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %m-%d + tickInterval 1day + excludes weekends + + section Section + A task : a1, 2022-10-01, 30d + Another task : after a1, 20d + section Another + Task in sec : 2022-10-20, 12d + another task : 24d + `, + { gantt: { topAxis: true } } + ); + }); }); diff --git a/docs/gantt.md b/docs/gantt.md index 1492ae085..086ffd622 100644 --- a/docs/gantt.md +++ b/docs/gantt.md @@ -230,6 +230,18 @@ The following formatting strings are supported: More info in: https://github.com/mbostock/d3/wiki/Time-Formatting +### Axis ticks + +The default output ticks are auto. You can custom your `tickInterval`, like `1day` or `1week`. + + tickInterval 1day + +The pattern is: + + /^([1-9][0-9]*)(minute|hour|day|week|month)$/ + +More info in: + ## Comments Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 2343bdd34..540fc6760 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -297,6 +297,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig { sectionFontSize?: string | number; numberSectionStyles?: number; axisFormat?: string; + tickInterval?: string; topAxis?: boolean; } diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 570dc2da3..fdb520091 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -661,6 +661,19 @@ const config: Partial = { */ axisFormat: '%Y-%m-%d', + /** + * | Parameter | Description | Type | Required | Values | + * | ------------ | ------------| ------ | -------- | ------- | + * | tickInterval | axis ticks | string | Optional | string | + * + * **Notes:** + * + * Pattern is /^([1-9][0-9]*)(minute|hour|day|week|month)$/ + * + * Default value: undefined + */ + tickInterval: undefined, + /** * | Parameter | Description | Type | Required | Values | * | ----------- | ----------- | ------- | -------- | ----------- | diff --git a/packages/mermaid/src/diagrams/gantt/ganttDb.js b/packages/mermaid/src/diagrams/gantt/ganttDb.js index 99c93ea04..a0f18c3b8 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDb.js +++ b/packages/mermaid/src/diagrams/gantt/ganttDb.js @@ -17,6 +17,7 @@ import { let dateFormat = ''; let axisFormat = ''; +let tickInterval = undefined; let todayMarker = ''; let includes = []; let excludes = []; @@ -47,6 +48,7 @@ export const clear = function () { rawTasks = []; dateFormat = ''; axisFormat = ''; + tickInterval = undefined; todayMarker = ''; includes = []; excludes = []; @@ -65,6 +67,14 @@ export const getAxisFormat = function () { return axisFormat; }; +export const setTickInterval = function (txt) { + tickInterval = txt; +}; + +export const getTickInterval = function () { + return tickInterval; +}; + export const setTodayMarker = function (txt) { todayMarker = txt; }; @@ -647,6 +657,8 @@ export default { topAxisEnabled, setAxisFormat, getAxisFormat, + setTickInterval, + getTickInterval, setTodayMarker, getTodayMarker, setAccTitle, diff --git a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js index c9f6836a5..9501dd024 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js +++ b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js @@ -10,6 +10,11 @@ import { axisBottom, axisTop, timeFormat, + timeMinute, + timeHour, + timeDay, + timeWeek, + timeMonth, } from 'd3'; import common from '../common/common'; import { getConfig } from '../../config'; @@ -495,6 +500,33 @@ export const draw = function (text, id, version, diagObj) { .tickSize(-h + theTopPad + conf.gridLineStartPadding) .tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d')); + const reTickInterval = /^([1-9][0-9]*)(minute|hour|day|week|month)$/; + const resultTickInterval = reTickInterval.exec( + diagObj.db.getTickInterval() || conf.tickInterval + ); + + if (resultTickInterval !== null) { + const every = resultTickInterval[1]; + const interval = resultTickInterval[2]; + switch (interval) { + case 'minute': + bottomXAxis.ticks(timeMinute.every(every)); + break; + case 'hour': + bottomXAxis.ticks(timeHour.every(every)); + break; + case 'day': + bottomXAxis.ticks(timeDay.every(every)); + break; + case 'week': + bottomXAxis.ticks(timeWeek.every(every)); + break; + case 'month': + bottomXAxis.ticks(timeMonth.every(every)); + break; + } + } + svg .append('g') .attr('class', 'grid') @@ -512,6 +544,28 @@ export const draw = function (text, id, version, diagObj) { .tickSize(-h + theTopPad + conf.gridLineStartPadding) .tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d')); + if (resultTickInterval !== null) { + const every = resultTickInterval[1]; + const interval = resultTickInterval[2]; + switch (interval) { + case 'minute': + topXAxis.ticks(timeMinute.every(every)); + break; + case 'hour': + topXAxis.ticks(timeHour.every(every)); + break; + case 'day': + topXAxis.ticks(timeDay.every(every)); + break; + case 'week': + topXAxis.ticks(timeWeek.every(every)); + break; + case 'month': + topXAxis.ticks(timeMonth.every(every)); + break; + } + } + svg .append('g') .attr('class', 'grid') diff --git a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison index f25656453..2223aa378 100644 --- a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison +++ b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison @@ -82,6 +82,7 @@ that id. "inclusiveEndDates" return 'inclusiveEndDates'; "topAxis" return 'topAxis'; "axisFormat"\s[^#\n;]+ return 'axisFormat'; +"tickInterval"\s[^#\n;]+ return 'tickInterval'; "includes"\s[^#\n;]+ return 'includes'; "excludes"\s[^#\n;]+ return 'excludes'; "todayMarker"\s[^\n;]+ return 'todayMarker'; @@ -125,6 +126,7 @@ statement | inclusiveEndDates {yy.enableInclusiveEndDates();$$=$1.substr(18);} | topAxis {yy.TopAxis();$$=$1.substr(8);} | axisFormat {yy.setAxisFormat($1.substr(11));$$=$1.substr(11);} + | tickInterval {yy.setTickInterval($1.substr(13));$$=$1.substr(13);} | 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);} diff --git a/packages/mermaid/src/docs/gantt.md b/packages/mermaid/src/docs/gantt.md index ad6573db6..d1fbe28bd 100644 --- a/packages/mermaid/src/docs/gantt.md +++ b/packages/mermaid/src/docs/gantt.md @@ -174,6 +174,22 @@ The following formatting strings are supported: More info in: https://github.com/mbostock/d3/wiki/Time-Formatting +### Axis ticks + +The default output ticks are auto. You can custom your `tickInterval`, like `1day` or `1week`. + +``` +tickInterval 1day +``` + +The pattern is: + +``` +/^([1-9][0-9]*)(minute|hour|day|week|month)$/ +``` + +More info in: [https://github.com/d3/d3-time#interval_every](https://github.com/d3/d3-time#interval_every) + ## Comments Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax