mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-03 12:25:22 +01:00
Merge branch 'develop' into sidv/classDiagramLabels
* develop:
refactor(deps): replace `moment` with `dayjs`
test(gantt): test daylight savings in ganttdb
Update .lycheeignore
chore: dagre-d3-es@7.0.9
Update docs
Doc (typo): remove duplicate "be"
💄 section width now covers all tasks
This commit is contained in:
@@ -56,12 +56,12 @@
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"cytoscape-fcose": "^2.1.0",
|
||||
"d3": "^7.4.0",
|
||||
"dagre-d3-es": "7.0.8",
|
||||
"dagre-d3-es": "7.0.9",
|
||||
"dayjs": "^1.11.7",
|
||||
"dompurify": "2.4.3",
|
||||
"elkjs": "^0.8.2",
|
||||
"khroma": "^2.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"moment-mini": "^2.29.4",
|
||||
"non-layered-tidy-tree-layout": "^2.0.2",
|
||||
"stylis": "^4.1.2",
|
||||
"ts-dedent": "^2.2.0",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import moment from 'moment-mini';
|
||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||
import dayjs from 'dayjs';
|
||||
import dayjsIsoWeek from 'dayjs/plugin/isoWeek';
|
||||
import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import { log } from '../../logger';
|
||||
import * as configApi from '../../config';
|
||||
import utils from '../../utils';
|
||||
@@ -15,6 +18,10 @@ import {
|
||||
getDiagramTitle,
|
||||
} from '../../commonDb';
|
||||
|
||||
dayjs.extend(dayjsIsoWeek);
|
||||
dayjs.extend(dayjsCustomParseFormat);
|
||||
dayjs.extend(dayjsAdvancedFormat);
|
||||
|
||||
let dateFormat = '';
|
||||
let axisFormat = '';
|
||||
let tickInterval = undefined;
|
||||
@@ -162,18 +169,58 @@ export const isInvalidDate = function (date, dateFormat, excludes, includes) {
|
||||
return excludes.includes(date.format(dateFormat.trim()));
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO: fully document what this function does and what types it accepts
|
||||
*
|
||||
* @param {object} task - The task to check.
|
||||
* @param {string | Date} task.startTime - Might be a `Date` or a `string`.
|
||||
* TODO: is this always a Date?
|
||||
* @param {string | Date} task.endTime - Might be a `Date` or a `string`.
|
||||
* TODO: is this always a Date?
|
||||
* @param {string} dateFormat - Dayjs date format string.
|
||||
* @param {*} excludes
|
||||
* @param {*} includes
|
||||
*/
|
||||
const checkTaskDates = function (task, dateFormat, excludes, includes) {
|
||||
if (!excludes.length || task.manualEndTime) {
|
||||
return;
|
||||
}
|
||||
let startTime = moment(task.startTime, dateFormat, true);
|
||||
startTime.add(1, 'd');
|
||||
let endTime = moment(task.endTime, dateFormat, true);
|
||||
let renderEndTime = fixTaskDates(startTime, endTime, dateFormat, excludes, includes);
|
||||
task.endTime = endTime.toDate();
|
||||
let startTime;
|
||||
if (task.startTime instanceof Date) {
|
||||
startTime = dayjs(task.startTime);
|
||||
} else {
|
||||
startTime = dayjs(task.startTime, dateFormat, true);
|
||||
}
|
||||
startTime = startTime.add(1, 'd');
|
||||
|
||||
let originalEndTime;
|
||||
if (task.endTime instanceof Date) {
|
||||
originalEndTime = dayjs(task.endTime);
|
||||
} else {
|
||||
originalEndTime = dayjs(task.endTime, dateFormat, true);
|
||||
}
|
||||
const [fixedEndTime, renderEndTime] = fixTaskDates(
|
||||
startTime,
|
||||
originalEndTime,
|
||||
dateFormat,
|
||||
excludes,
|
||||
includes
|
||||
);
|
||||
task.endTime = fixedEndTime.toDate();
|
||||
task.renderEndTime = renderEndTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* TODO: what does this function do?
|
||||
*
|
||||
* @param {dayjs.Dayjs} startTime - The start time.
|
||||
* @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid).
|
||||
* @param {string} dateFormat - Dayjs date format string.
|
||||
* @param {*} excludes
|
||||
* @param {*} includes
|
||||
* @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render.
|
||||
* `renderEndTime` may be `null` if `startTime` is newer than `endTime`.
|
||||
*/
|
||||
const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) {
|
||||
let invalid = false;
|
||||
let renderEndTime = null;
|
||||
@@ -183,11 +230,11 @@ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, include
|
||||
}
|
||||
invalid = isInvalidDate(startTime, dateFormat, excludes, includes);
|
||||
if (invalid) {
|
||||
endTime.add(1, 'd');
|
||||
endTime = endTime.add(1, 'd');
|
||||
}
|
||||
startTime.add(1, 'd');
|
||||
startTime = startTime.add(1, 'd');
|
||||
}
|
||||
return renderEndTime;
|
||||
return [endTime, renderEndTime];
|
||||
};
|
||||
|
||||
const getStartDate = function (prevTime, dateFormat, str) {
|
||||
@@ -223,7 +270,7 @@ const getStartDate = function (prevTime, dateFormat, str) {
|
||||
}
|
||||
|
||||
// Check for actual date set
|
||||
let mDate = moment(str, dateFormat.trim(), true);
|
||||
let mDate = dayjs(str, dateFormat.trim(), true);
|
||||
if (mDate.isValid()) {
|
||||
return mDate.toDate();
|
||||
} else {
|
||||
@@ -238,11 +285,14 @@ const getStartDate = function (prevTime, dateFormat, str) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a string as a moment duration.
|
||||
* Parse a string into the args for `dayjs.add()`.
|
||||
*
|
||||
* The string have to be compound by a value and a shorthand duration unit. For example `5d`
|
||||
* represents 5 days.
|
||||
*
|
||||
* Please be aware that 1 day may be 23 or 25 hours, if the user lives in an area
|
||||
* that has daylight savings time (or even 23.5/24.5 hours in Lord Howe Island!)
|
||||
*
|
||||
* Shorthand unit supported are:
|
||||
*
|
||||
* - `y` for years
|
||||
@@ -254,33 +304,36 @@ const getStartDate = function (prevTime, dateFormat, str) {
|
||||
* - `ms` for milliseconds
|
||||
*
|
||||
* @param {string} str - A string representing the duration.
|
||||
* @returns {moment.Duration} A moment duration, including an invalid moment for invalid input
|
||||
* string.
|
||||
* @returns {[value: number, unit: dayjs.ManipulateType]} Arguments to pass to `dayjs.add()`
|
||||
*/
|
||||
const parseDuration = function (str) {
|
||||
const statement = /^(\d+(?:\.\d+)?)([Mdhmswy]|ms)$/.exec(str.trim());
|
||||
if (statement !== null) {
|
||||
return moment.duration(Number.parseFloat(statement[1]), statement[2]);
|
||||
return [Number.parseFloat(statement[1]), statement[2]];
|
||||
}
|
||||
return moment.duration.invalid();
|
||||
// NaN means an invalid duration
|
||||
return [NaN, 'ms'];
|
||||
};
|
||||
|
||||
const getEndDate = function (prevTime, dateFormat, str, inclusive = false) {
|
||||
str = str.trim();
|
||||
|
||||
// Check for actual date
|
||||
let mDate = moment(str, dateFormat.trim(), true);
|
||||
let mDate = dayjs(str, dateFormat.trim(), true);
|
||||
if (mDate.isValid()) {
|
||||
if (inclusive) {
|
||||
mDate.add(1, 'd');
|
||||
mDate = mDate.add(1, 'd');
|
||||
}
|
||||
return mDate.toDate();
|
||||
}
|
||||
|
||||
const endTime = moment(prevTime);
|
||||
const duration = parseDuration(str);
|
||||
if (duration.isValid()) {
|
||||
endTime.add(duration);
|
||||
let endTime = dayjs(prevTime);
|
||||
const [durationValue, durationUnit] = parseDuration(str);
|
||||
if (!Number.isNaN(durationValue)) {
|
||||
const newEndTime = endTime.add(durationValue, durationUnit);
|
||||
if (newEndTime.isValid()) {
|
||||
endTime = newEndTime;
|
||||
}
|
||||
}
|
||||
return endTime.toDate();
|
||||
};
|
||||
@@ -346,7 +399,7 @@ const compileData = function (prevTask, dataStr) {
|
||||
|
||||
if (endTimeData) {
|
||||
task.endTime = getEndDate(task.startTime, dateFormat, endTimeData, inclusiveEndDates);
|
||||
task.manualEndTime = moment(endTimeData, 'YYYY-MM-DD', true).isValid();
|
||||
task.manualEndTime = dayjs(endTimeData, 'YYYY-MM-DD', true).isValid();
|
||||
checkTaskDates(task, dateFormat, excludes, includes);
|
||||
}
|
||||
|
||||
@@ -496,7 +549,7 @@ const compileTasks = function () {
|
||||
);
|
||||
if (rawTasks[pos].endTime) {
|
||||
rawTasks[pos].processed = true;
|
||||
rawTasks[pos].manualEndTime = moment(
|
||||
rawTasks[pos].manualEndTime = dayjs(
|
||||
rawTasks[pos].raw.endTime.data,
|
||||
'YYYY-MM-DD',
|
||||
true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck TODO: Fix TS
|
||||
import moment from 'moment-mini';
|
||||
import dayjs from 'dayjs';
|
||||
import ganttDb from './ganttDb';
|
||||
import { convert } from '../../tests/util';
|
||||
|
||||
@@ -9,7 +9,7 @@ describe('when using the ganttDb', function () {
|
||||
});
|
||||
|
||||
describe('when using duration', function () {
|
||||
it.each([{ str: '1d', expected: moment.duration(1, 'd') }])(
|
||||
it.each([{ str: '1d', expected: [1, 'd'] }])(
|
||||
'should %s resulting in $o duration',
|
||||
({ str, expected }) => {
|
||||
expect(ganttDb.parseDuration(str)).toEqual(expected);
|
||||
@@ -19,11 +19,11 @@ describe('when using the ganttDb', function () {
|
||||
it.each(
|
||||
convert`
|
||||
str | expected
|
||||
${'1d'} | ${moment.duration(1, 'd')}
|
||||
${'2w'} | ${moment.duration(2, 'w')}
|
||||
${'1ms'} | ${moment.duration(1, 'ms')}
|
||||
${'0.1s'} | ${moment.duration(100, 'ms')}
|
||||
${'1f'} | ${moment.duration.invalid()}
|
||||
${'1d'} | ${[1, 'd']}
|
||||
${'2w'} | ${[2, 'w']}
|
||||
${'1ms'} | ${[1, 'ms']}
|
||||
${'0.1s'} | ${[0.1, 's']}
|
||||
${'1f'} | ${[NaN, 'ms']}
|
||||
`
|
||||
)('should $str resulting in $expected duration', ({ str, expected }) => {
|
||||
expect(ganttDb.parseDuration(str)).toEqual(expected);
|
||||
@@ -171,44 +171,44 @@ describe('when using the ganttDb', function () {
|
||||
|
||||
const tasks = ganttDb.getTasks();
|
||||
|
||||
expect(tasks[0].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].renderEndTime).toEqual(moment('2019-02-02', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].renderEndTime).toEqual(dayjs('2019-02-02', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
|
||||
expect(tasks[1].startTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(moment('2019-02-07', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].renderEndTime).toEqual(moment('2019-02-06', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].startTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(dayjs('2019-02-07', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].renderEndTime).toEqual(dayjs('2019-02-06', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].id).toEqual('id2');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
|
||||
expect(tasks[2].startTime).toEqual(moment('2019-02-07', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].endTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].renderEndTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].startTime).toEqual(dayjs('2019-02-07', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].endTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].renderEndTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].id).toEqual('id3');
|
||||
expect(tasks[2].task).toEqual('test3');
|
||||
|
||||
expect(tasks[3].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[3].endTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[3].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[3].endTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[3].renderEndTime).toBeNull(); // Fixed end
|
||||
expect(tasks[3].id).toEqual('id4');
|
||||
expect(tasks[3].task).toEqual('test4');
|
||||
|
||||
expect(tasks[4].startTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].endTime).toEqual(moment('2019-02-21', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].renderEndTime).toEqual(moment('2019-02-21', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].startTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].endTime).toEqual(dayjs('2019-02-21', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].renderEndTime).toEqual(dayjs('2019-02-21', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].id).toEqual('id5');
|
||||
expect(tasks[4].task).toEqual('test5');
|
||||
|
||||
expect(tasks[5].startTime).toEqual(moment('2019-02-13', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].endTime).toEqual(moment('2019-02-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].renderEndTime).toEqual(moment('2019-02-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].startTime).toEqual(dayjs('2019-02-13', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].endTime).toEqual(dayjs('2019-02-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].renderEndTime).toEqual(dayjs('2019-02-15', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].id).toEqual('id6');
|
||||
expect(tasks[5].task).toEqual('test6');
|
||||
|
||||
expect(tasks[6].startTime).toEqual(moment('2019-02-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[6].endTime).toEqual(moment('2019-02-19', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[6].startTime).toEqual(dayjs('2019-02-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[6].endTime).toEqual(dayjs('2019-02-19', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[6].id).toEqual('id7');
|
||||
expect(tasks[6].task).toEqual('test7');
|
||||
});
|
||||
@@ -243,109 +243,103 @@ describe('when using the ganttDb', function () {
|
||||
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].startTime).toEqual(dayjs('2014-01-06', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-09', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-12', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[2].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-17', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[3].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-06', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[4].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-08', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[5].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-10', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[6].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[7].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-18', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[8].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-20', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[9].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-08', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[10].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[11].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[12].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[13].endTime).toEqual(dayjs('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].startTime).toEqual(dayjs('2014-01-16', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[14].endTime).toEqual(dayjs('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()
|
||||
dayjs('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()
|
||||
);
|
||||
expect(tasks[15].endTime).toEqual(dayjs('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');
|
||||
@@ -358,19 +352,53 @@ describe('when using the ganttDb', function () {
|
||||
ganttDb.addTask('test2', 'id2,after id1,20d');
|
||||
const tasks = ganttDb.getTasks();
|
||||
|
||||
expect(tasks[0].startTime).toEqual(moment('2019-09-30', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(moment('2019-10-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].startTime).toEqual(dayjs('2019-09-30', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(dayjs('2019-10-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].renderEndTime).toBeNull(); // Fixed end
|
||||
expect(tasks[0].id).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
|
||||
expect(tasks[1].startTime).toEqual(moment('2019-10-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(moment('2019-10-31', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].startTime).toEqual(dayjs('2019-10-11', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(dayjs('2019-10-31', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].renderEndTime).toBeNull(); // Fixed end
|
||||
expect(tasks[1].id).toEqual('id2');
|
||||
expect(tasks[1].task).toEqual('test2');
|
||||
});
|
||||
|
||||
/**
|
||||
* Unfortunately, Vitest has no way of modifying the timezone at runtime, so
|
||||
* in order to test this, please run this test with
|
||||
*
|
||||
* ```bash
|
||||
* TZ='America/Los_Angeles' pnpm exec vitest run ganttDb
|
||||
* ```
|
||||
*/
|
||||
/* c8 ignore start */ // tell code-coverage to ignore this block of code
|
||||
describe.skipIf(process.env.TZ != 'America/Los_Angeles')(
|
||||
'when using a timezone with daylight savings (only run if TZ="America/Los_Angeles")',
|
||||
() => {
|
||||
it('should add 1 day even on days with 25 hours', function () {
|
||||
const startTime = new Date(2020, 10, 1);
|
||||
expect(startTime.toISOString()).toBe('2020-11-01T07:00:00.000Z');
|
||||
|
||||
const endTime = new Date(2020, 10, 2);
|
||||
expect(endTime.toISOString()).toBe('2020-11-02T08:00:00.000Z');
|
||||
|
||||
ganttDb.setDateFormat('YYYY-MM-DD');
|
||||
ganttDb.addSection('Task handles 25 hour day');
|
||||
ganttDb.addTask('daylight savings day', 'id1,2020-11-01,1d');
|
||||
const tasks = ganttDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(startTime);
|
||||
expect(tasks[0].endTime).toEqual(endTime);
|
||||
|
||||
// In USA states that use daylight savings, 2020-11-01 had 25 hours
|
||||
const millisecondsIn25Hours = 25 * 60 * 60 * 1000;
|
||||
expect(endTime - startTime).toEqual(millisecondsIn25Hours);
|
||||
});
|
||||
}
|
||||
);
|
||||
/* c8 ignore stop */
|
||||
|
||||
describe('when setting inclusive end dates', function () {
|
||||
beforeEach(function () {
|
||||
ganttDb.setDateFormat('YYYY-MM-DD');
|
||||
@@ -380,13 +408,13 @@ describe('when using the ganttDb', function () {
|
||||
});
|
||||
it('should automatically add one day to all end dates', function () {
|
||||
const tasks = ganttDb.getTasks();
|
||||
expect(tasks[0].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(moment('2019-02-02', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].endTime).toEqual(dayjs('2019-02-02', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[0].id).toEqual('id1');
|
||||
expect(tasks[0].task).toEqual('test1');
|
||||
|
||||
expect(tasks[1].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].endTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate());
|
||||
expect(tasks[1].renderEndTime).toBeNull(); // Fixed end
|
||||
expect(tasks[1].manualEndTime).toBeTruthy();
|
||||
expect(tasks[1].id).toEqual('id2');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import moment from 'moment-mini';
|
||||
import dayjs from 'dayjs';
|
||||
import { log } from '../../logger';
|
||||
import {
|
||||
select,
|
||||
@@ -435,16 +435,16 @@ export const draw = function (text, id, version, diagObj) {
|
||||
|
||||
const excludeRanges = [];
|
||||
let range = null;
|
||||
let d = moment(minTime);
|
||||
let d = dayjs(minTime);
|
||||
while (d.valueOf() <= maxTime) {
|
||||
if (diagObj.db.isInvalidDate(d, dateFormat, excludes, includes)) {
|
||||
if (!range) {
|
||||
range = {
|
||||
start: d.clone(),
|
||||
end: d.clone(),
|
||||
start: d,
|
||||
end: d,
|
||||
};
|
||||
} else {
|
||||
range.end = d.clone();
|
||||
range.end = d;
|
||||
}
|
||||
} else {
|
||||
if (range) {
|
||||
@@ -452,7 +452,7 @@ export const draw = function (text, id, version, diagObj) {
|
||||
range = null;
|
||||
}
|
||||
}
|
||||
d.add(1, 'd');
|
||||
d = d.add(1, 'd');
|
||||
}
|
||||
|
||||
const rectangles = svg.append('g').selectAll('rect').data(excludeRanges).enter();
|
||||
@@ -467,7 +467,7 @@ export const draw = function (text, id, version, diagObj) {
|
||||
})
|
||||
.attr('y', conf.gridLineStartPadding)
|
||||
.attr('width', function (d) {
|
||||
const renderEnd = d.end.clone().add(1, 'day');
|
||||
const renderEnd = d.end.add(1, 'day');
|
||||
return timeScale(renderEnd) - timeScale(d.start);
|
||||
})
|
||||
.attr('height', h - theTopPad - conf.gridLineStartPadding)
|
||||
|
||||
@@ -224,6 +224,17 @@ export const drawTasks = function (diagram, tasks, verticalPos) {
|
||||
num = sectionNumber % fills.length;
|
||||
colour = textColours[sectionNumber % textColours.length];
|
||||
|
||||
// count how many consecutive tasks have the same section
|
||||
let taskInSectionCount = 0;
|
||||
const currentSection = task.section;
|
||||
for (let taskIndex = i; taskIndex < tasks.length; taskIndex++) {
|
||||
if (tasks[taskIndex].section == currentSection) {
|
||||
taskInSectionCount = taskInSectionCount + 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const section = {
|
||||
x: i * conf.taskMargin + i * conf.width + LEFT_MARGIN,
|
||||
y: 50,
|
||||
@@ -231,6 +242,7 @@ export const drawTasks = function (diagram, tasks, verticalPos) {
|
||||
fill,
|
||||
num,
|
||||
colour,
|
||||
taskCount: taskInSectionCount,
|
||||
};
|
||||
|
||||
svgDraw.drawSection(diagram, section, conf);
|
||||
|
||||
@@ -196,7 +196,10 @@ export const drawSection = function (elem, section, conf) {
|
||||
rect.x = section.x;
|
||||
rect.y = section.y;
|
||||
rect.fill = section.fill;
|
||||
rect.width = conf.width;
|
||||
// section width covers all nested tasks
|
||||
rect.width =
|
||||
conf.width * section.taskCount + // width of the tasks
|
||||
conf.diagramMarginX * (section.taskCount - 1); // width of space between tasks
|
||||
rect.height = conf.height;
|
||||
rect.class = 'journey-section section-type-' + section.num;
|
||||
rect.rx = 3;
|
||||
|
||||
@@ -116,7 +116,7 @@ The following formatting options are supported:
|
||||
| `YY` | 14 | 2 digit year |
|
||||
| `Q` | 1..4 | Quarter of year. Sets month to first month in quarter. |
|
||||
| `M MM` | 1..12 | Month number |
|
||||
| `MMM MMMM` | January..Dec | Month name in locale set by `moment.locale()` |
|
||||
| `MMM MMMM` | January..Dec | Month name in locale set by `dayjs.locale()` |
|
||||
| `D DD` | 1..31 | Day of month |
|
||||
| `Do` | 1st..31st | Day of month with ordinal |
|
||||
| `DDD DDDD` | 1..365 | Day of year |
|
||||
@@ -132,7 +132,7 @@ The following formatting options are supported:
|
||||
| `SSS` | 0..999 | Thousandths of a second |
|
||||
| `Z ZZ` | +12:00 | Offset from UTC as +-HH:mm, +-HHmm, or Z |
|
||||
|
||||
More info in: https://momentjs.com/docs/#/parsing/string-format/
|
||||
More info in: https://day.js.org/docs/en/parse/string-format/
|
||||
|
||||
### Output date format on the axis
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ It is possible to get a sequence number attached to each arrow in a sequence dia
|
||||
</script>
|
||||
```
|
||||
|
||||
It can also be be turned on via the diagram code as in the diagram:
|
||||
It can also be turned on via the diagram code as in the diagram:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
/* eslint-disable no-console */
|
||||
import moment from 'moment-mini';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
||||
|
||||
@@ -85,6 +85,6 @@ export const setLogLevel = function (level: keyof typeof LEVELS | number | strin
|
||||
* @returns The format with the timestamp and log level
|
||||
*/
|
||||
const format = (level: Uppercase<LogLevel>): string => {
|
||||
const time = moment().format('ss.SSS');
|
||||
const time = dayjs().format('ss.SSS');
|
||||
return `%c${time} : ${level} : `;
|
||||
};
|
||||
|
||||
@@ -7,8 +7,8 @@ Jest code
|
||||
```ts
|
||||
it.each`
|
||||
str | expected
|
||||
${'1d'} | ${moment.duration(1, 'd')}
|
||||
${'2w'} | ${moment.duration(2, 'w')}
|
||||
${'1d'} | ${dayjs.duration(1, 'd')}
|
||||
${'2w'} | ${dayjs.duration(2, 'w')}
|
||||
`('should parse $str to $expected duration', ({ str, expected }) => {
|
||||
expect(yourFunction(str)).toEqual(expected);
|
||||
});
|
||||
@@ -18,8 +18,8 @@ Vitest code
|
||||
```ts
|
||||
it.each(convert`
|
||||
str | expected
|
||||
${'1d'} | ${moment.duration(1, 'd')}
|
||||
${'2w'} | ${moment.duration(2, 'w')}
|
||||
${'1d'} | ${dayjs.duration(1, 'd')}
|
||||
${'2w'} | ${dayjs.duration(2, 'w')}
|
||||
`)('should parse $str to $expected duration', ({ str, expected }) => {
|
||||
expect(yourFunction(str)).toEqual(expected);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user