mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-18 23:09:49 +02:00
feat: added includes; added excludes date background
This commit is contained in:
@@ -8,6 +8,7 @@ import mermaidAPI from '../../mermaidAPI';
|
||||
let dateFormat = '';
|
||||
let axisFormat = '';
|
||||
let todayMarker = '';
|
||||
let includes = [];
|
||||
let excludes = [];
|
||||
let title = '';
|
||||
let sections = [];
|
||||
@@ -38,6 +39,7 @@ export const clear = function () {
|
||||
dateFormat = '';
|
||||
axisFormat = '';
|
||||
todayMarker = '';
|
||||
includes = [];
|
||||
excludes = [];
|
||||
inclusiveEndDates = false;
|
||||
topAxis = false;
|
||||
@@ -84,6 +86,13 @@ export const getDateFormat = function () {
|
||||
return dateFormat;
|
||||
};
|
||||
|
||||
export const setIncludes = function (txt) {
|
||||
includes = txt.toLowerCase().split(/[\s,]+/);
|
||||
};
|
||||
|
||||
export const getIncludes = function () {
|
||||
return includes;
|
||||
};
|
||||
export const setExcludes = function (txt) {
|
||||
excludes = txt.toLowerCase().split(/[\s,]+/);
|
||||
};
|
||||
@@ -123,7 +132,10 @@ export const getTasks = function () {
|
||||
return tasks;
|
||||
};
|
||||
|
||||
const isInvalidDate = function (date, dateFormat, excludes) {
|
||||
export const isInvalidDate = function (date, dateFormat, excludes, includes) {
|
||||
if (includes.indexOf(date.format(dateFormat.trim())) >= 0) {
|
||||
return false;
|
||||
}
|
||||
if (date.isoWeekday() >= 6 && excludes.indexOf('weekends') >= 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -133,24 +145,24 @@ const isInvalidDate = function (date, dateFormat, excludes) {
|
||||
return excludes.indexOf(date.format(dateFormat.trim())) >= 0;
|
||||
};
|
||||
|
||||
const checkTaskDates = function (task, dateFormat, excludes) {
|
||||
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);
|
||||
let renderEndTime = fixTaskDates(startTime, endTime, dateFormat, excludes, includes);
|
||||
task.endTime = endTime.toDate();
|
||||
task.renderEndTime = renderEndTime;
|
||||
};
|
||||
|
||||
const fixTaskDates = function (startTime, endTime, dateFormat, excludes) {
|
||||
const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) {
|
||||
let invalid = false;
|
||||
let renderEndTime = null;
|
||||
while (startTime <= endTime) {
|
||||
if (!invalid) {
|
||||
renderEndTime = endTime.toDate();
|
||||
}
|
||||
invalid = isInvalidDate(startTime, dateFormat, excludes);
|
||||
invalid = isInvalidDate(startTime, dateFormat, excludes, includes);
|
||||
if (invalid) {
|
||||
endTime.add(1, 'd');
|
||||
}
|
||||
@@ -306,7 +318,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();
|
||||
checkTaskDates(task, dateFormat, excludes);
|
||||
checkTaskDates(task, dateFormat, excludes, includes);
|
||||
}
|
||||
|
||||
return task;
|
||||
@@ -460,7 +472,7 @@ const compileTasks = function () {
|
||||
'YYYY-MM-DD',
|
||||
true
|
||||
).isValid();
|
||||
checkTaskDates(rawTasks[pos], dateFormat, excludes);
|
||||
checkTaskDates(rawTasks[pos], dateFormat, excludes, includes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,12 +630,15 @@ export default {
|
||||
addTask,
|
||||
findTaskById,
|
||||
addTaskOrg,
|
||||
setIncludes,
|
||||
getIncludes,
|
||||
setExcludes,
|
||||
getExcludes,
|
||||
setClickEvent,
|
||||
setLink,
|
||||
bindFunctions,
|
||||
durationToDate,
|
||||
isInvalidDate,
|
||||
};
|
||||
|
||||
function getTaskTags(data, task, tags) {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import moment from 'moment-mini';
|
||||
import {
|
||||
select,
|
||||
scaleTime,
|
||||
@@ -108,6 +109,16 @@ export const draw = function (text, id) {
|
||||
.range(['#00B9FA', '#F95002'])
|
||||
.interpolate(interpolateHcl);
|
||||
|
||||
drawExcludeDays(
|
||||
gap,
|
||||
topPadding,
|
||||
leftPadding,
|
||||
pageWidth,
|
||||
pageHeight,
|
||||
tasks,
|
||||
parser.yy.getExcludes(),
|
||||
parser.yy.getIncludes()
|
||||
);
|
||||
makeGrid(leftPadding, topPadding, pageWidth, pageHeight);
|
||||
drawRects(tasks, gap, topPadding, leftPadding, barHeight, colorScale, pageWidth, pageHeight);
|
||||
vertLabels(gap, topPadding, leftPadding, barHeight, colorScale);
|
||||
@@ -341,6 +352,67 @@ export const draw = function (text, id) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function drawExcludeDays(theGap, theTopPad, theSidePad, w, h, tasks, excludes, includes) {
|
||||
const minTime = tasks.reduce(
|
||||
(min, { startTime }) => (min ? Math.min(min, startTime) : startTime),
|
||||
0
|
||||
);
|
||||
const maxTime = tasks.reduce((max, { endTime }) => (max ? Math.max(max, endTime) : endTime), 0);
|
||||
const dateFormat = parser.yy.getDateFormat();
|
||||
if (!minTime || !maxTime) return;
|
||||
|
||||
const excludeRanges = [];
|
||||
let range = null;
|
||||
let d = moment(minTime);
|
||||
while (d.valueOf() <= maxTime) {
|
||||
if (parser.yy.isInvalidDate(d, dateFormat, excludes, includes)) {
|
||||
if (!range) {
|
||||
range = {
|
||||
start: d.clone(),
|
||||
end: d.clone(),
|
||||
};
|
||||
} else {
|
||||
range.end = d.clone();
|
||||
}
|
||||
} else {
|
||||
if (range) {
|
||||
excludeRanges.push(range);
|
||||
range = null;
|
||||
}
|
||||
}
|
||||
d.add(1, 'd');
|
||||
}
|
||||
|
||||
const rectangles = svg.append('g').selectAll('rect').data(excludeRanges).enter();
|
||||
|
||||
rectangles
|
||||
.append('rect')
|
||||
.attr('id', function (d) {
|
||||
return 'exclude-' + d.start.format('YYYY-MM-DD');
|
||||
})
|
||||
.attr('x', function (d) {
|
||||
return timeScale(d.start) + theSidePad;
|
||||
})
|
||||
.attr('y', conf.gridLineStartPadding)
|
||||
.attr('width', function (d) {
|
||||
const renderEnd = d.end.clone().add(1, 'day');
|
||||
return timeScale(renderEnd) - timeScale(d.start);
|
||||
})
|
||||
.attr('height', h - theTopPad - conf.gridLineStartPadding)
|
||||
.attr('transform-origin', function (d, i) {
|
||||
return (
|
||||
(
|
||||
timeScale(d.start) +
|
||||
theSidePad +
|
||||
0.5 * (timeScale(d.end) - timeScale(d.start))
|
||||
).toString() +
|
||||
'px ' +
|
||||
(i * theGap + 0.5 * h).toString() +
|
||||
'px'
|
||||
);
|
||||
})
|
||||
.attr('class', 'exclude-range');
|
||||
}
|
||||
|
||||
function makeGrid(theSidePad, theTopPad, w, h) {
|
||||
let bottomXAxis = axisBottom(timeScale)
|
||||
@@ -458,7 +530,8 @@ export const draw = function (text, id) {
|
||||
const hash = {};
|
||||
const result = [];
|
||||
for (let i = 0, l = arr.length; i < l; ++i) {
|
||||
if (!hash.hasOwnProperty(arr[i])) { // eslint-disable-line
|
||||
if (!Object.prototype.hasOwnProperty.call(hash, arr[i])) {
|
||||
// eslint-disable-line
|
||||
// it works with objects! in FF, at least
|
||||
hash[arr[i]] = true;
|
||||
result.push(arr[i]);
|
||||
|
@@ -70,6 +70,7 @@ that id.
|
||||
"inclusiveEndDates" return 'inclusiveEndDates';
|
||||
"topAxis" return 'topAxis';
|
||||
"axisFormat"\s[^#\n;]+ return 'axisFormat';
|
||||
"includes"\s[^#\n;]+ return 'includes';
|
||||
"excludes"\s[^#\n;]+ return 'excludes';
|
||||
"todayMarker"\s[^\n;]+ return 'todayMarker';
|
||||
\d\d\d\d"-"\d\d"-"\d\d return 'date';
|
||||
@@ -112,6 +113,7 @@ statement
|
||||
| topAxis {yy.TopAxis();$$=$1.substr(8);}
|
||||
| axisFormat {yy.setAxisFormat($1.substr(11));$$=$1.substr(11);}
|
||||
| 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);}
|
||||
| title {yy.setTitle($1.substr(6));$$=$1.substr(6);}
|
||||
| section {yy.addSection($1.substr(8));$$=$1.substr(8);}
|
||||
|
@@ -4,6 +4,9 @@ const getStyles = (options) =>
|
||||
font-family: "trebuchet ms", verdana, arial, sans-serif;
|
||||
font-family: var(--mermaid-font-family);
|
||||
}
|
||||
.exclude-range {
|
||||
fill: ${options.excludeBkgColor};
|
||||
}
|
||||
|
||||
.section {
|
||||
stroke: none;
|
||||
|
Reference in New Issue
Block a user