2019-09-12 12:57:36 -07:00
|
|
|
import moment from 'moment-mini';
|
|
|
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
|
|
|
import { logger } from '../../logger';
|
|
|
|
import { getConfig } from '../../config';
|
|
|
|
|
|
|
|
const config = getConfig();
|
|
|
|
let dateFormat = '';
|
|
|
|
let axisFormat = '';
|
|
|
|
let excludes = [];
|
|
|
|
let title = '';
|
|
|
|
let sections = [];
|
|
|
|
let tasks = [];
|
|
|
|
let currentSection = '';
|
|
|
|
const tags = ['active', 'done', 'crit', 'milestone'];
|
|
|
|
let funs = [];
|
|
|
|
let inclusiveEndDates = false;
|
|
|
|
|
|
|
|
export const clear = function() {
|
|
|
|
sections = [];
|
|
|
|
tasks = [];
|
|
|
|
currentSection = '';
|
|
|
|
funs = [];
|
|
|
|
title = '';
|
|
|
|
taskCnt = 0;
|
|
|
|
lastTask = undefined;
|
|
|
|
lastTaskID = undefined;
|
|
|
|
rawTasks = [];
|
|
|
|
dateFormat = '';
|
|
|
|
axisFormat = '';
|
|
|
|
excludes = [];
|
|
|
|
inclusiveEndDates = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setAxisFormat = function(txt) {
|
|
|
|
axisFormat = txt;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getAxisFormat = function() {
|
|
|
|
return axisFormat;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setDateFormat = function(txt) {
|
|
|
|
dateFormat = txt;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const enableInclusiveEndDates = function() {
|
|
|
|
inclusiveEndDates = true;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const endDatesAreInclusive = function() {
|
|
|
|
return inclusiveEndDates;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getDateFormat = function() {
|
|
|
|
return dateFormat;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setExcludes = function(txt) {
|
|
|
|
excludes = txt.toLowerCase().split(/[\s,]+/);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getExcludes = function() {
|
|
|
|
return excludes;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const setTitle = function(txt) {
|
|
|
|
title = txt;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getTitle = function() {
|
|
|
|
return title;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const addSection = function(txt) {
|
|
|
|
currentSection = txt;
|
|
|
|
sections.push(txt);
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getSections = function() {
|
|
|
|
return sections;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getTasks = function() {
|
|
|
|
let allItemsPricessed = compileTasks();
|
|
|
|
const maxDepth = 10;
|
|
|
|
let iterationCount = 0;
|
|
|
|
while (!allItemsPricessed && iterationCount < maxDepth) {
|
|
|
|
allItemsPricessed = compileTasks();
|
|
|
|
iterationCount++;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
tasks = rawTasks;
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
return tasks;
|
|
|
|
};
|
2015-02-08 20:07:15 +01:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const isInvalidDate = function(date, dateFormat, excludes) {
|
2019-02-06 17:25:39 -02:00
|
|
|
if (date.isoWeekday() >= 6 && excludes.indexOf('weekends') >= 0) {
|
2019-09-12 12:57:36 -07:00
|
|
|
return true;
|
2019-02-06 17:25:39 -02:00
|
|
|
}
|
2019-02-07 11:21:00 -02:00
|
|
|
if (excludes.indexOf(date.format('dddd').toLowerCase()) >= 0) {
|
2019-09-12 12:57:36 -07:00
|
|
|
return true;
|
2019-02-07 11:21:00 -02:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return excludes.indexOf(date.format(dateFormat.trim())) >= 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
const checkTaskDates = function(task, dateFormat, excludes) {
|
|
|
|
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);
|
|
|
|
task.endTime = endTime.toDate();
|
|
|
|
task.renderEndTime = renderEndTime;
|
|
|
|
};
|
|
|
|
|
|
|
|
const fixTaskDates = function(startTime, endTime, dateFormat, excludes) {
|
|
|
|
let invalid = false;
|
|
|
|
let renderEndTime = null;
|
2019-02-07 11:27:01 -02:00
|
|
|
while (startTime.date() <= endTime.date()) {
|
2019-02-12 17:29:38 -02:00
|
|
|
if (!invalid) {
|
2019-09-12 12:57:36 -07:00
|
|
|
renderEndTime = endTime.toDate();
|
2019-02-12 17:29:38 -02:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
invalid = isInvalidDate(startTime, dateFormat, excludes);
|
2019-02-12 17:29:38 -02:00
|
|
|
if (invalid) {
|
2019-09-12 12:57:36 -07:00
|
|
|
endTime.add(1, 'd');
|
2019-02-07 11:21:00 -02:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
startTime.add(1, 'd');
|
2019-02-06 16:54:09 -02:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return renderEndTime;
|
|
|
|
};
|
2019-02-06 16:54:09 -02:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const getStartDate = function(prevTime, dateFormat, str) {
|
|
|
|
str = str.trim();
|
2015-02-20 19:06:15 +01:00
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
// Test for after
|
2019-09-12 12:57:36 -07:00
|
|
|
const re = /^after\s+([\d\w-]+)/;
|
|
|
|
const afterStatement = re.exec(str.trim());
|
2015-10-21 21:14:41 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (afterStatement !== null) {
|
2019-09-12 12:57:36 -07:00
|
|
|
const task = findTaskById(afterStatement[1]);
|
2015-10-24 12:44:47 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof task === 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
const dt = new Date();
|
|
|
|
dt.setHours(0, 0, 0, 0);
|
|
|
|
return dt;
|
2015-02-08 20:07:15 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return task.endTime;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
// Check for actual date set
|
2019-09-12 12:57:36 -07:00
|
|
|
let mDate = moment(str, dateFormat.trim(), true);
|
2019-02-06 16:54:09 -02:00
|
|
|
if (mDate.isValid()) {
|
2019-09-12 12:57:36 -07:00
|
|
|
return mDate.toDate();
|
2017-04-11 22:14:25 +08:00
|
|
|
} else {
|
2019-09-12 12:57:36 -07:00
|
|
|
logger.debug('Invalid date:' + str);
|
|
|
|
logger.debug('With date format:' + dateFormat.trim());
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2017-04-16 23:48:36 +08:00
|
|
|
// Default date - now
|
2019-09-12 12:57:36 -07:00
|
|
|
return new Date();
|
|
|
|
};
|
2015-02-08 20:07:15 +01:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const durationToDate = function(durationStatement, relativeTime) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (durationStatement !== null) {
|
|
|
|
switch (durationStatement[2]) {
|
|
|
|
case 's':
|
2019-09-12 12:57:36 -07:00
|
|
|
relativeTime.add(durationStatement[1], 'seconds');
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 'm':
|
2019-09-12 12:57:36 -07:00
|
|
|
relativeTime.add(durationStatement[1], 'minutes');
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 'h':
|
2019-09-12 12:57:36 -07:00
|
|
|
relativeTime.add(durationStatement[1], 'hours');
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 'd':
|
2019-09-12 12:57:36 -07:00
|
|
|
relativeTime.add(durationStatement[1], 'days');
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 'w':
|
2019-09-12 12:57:36 -07:00
|
|
|
relativeTime.add(durationStatement[1], 'weeks');
|
|
|
|
break;
|
2015-02-08 20:07:15 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2017-04-16 23:48:36 +08:00
|
|
|
// Default date - now
|
2019-09-12 12:57:36 -07:00
|
|
|
return relativeTime.toDate();
|
|
|
|
};
|
2019-07-07 17:01:45 -03:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const getEndDate = function(prevTime, dateFormat, str, inclusive) {
|
|
|
|
inclusive = inclusive || false;
|
|
|
|
str = str.trim();
|
2019-07-07 17:01:45 -03:00
|
|
|
|
|
|
|
// Check for actual date
|
2019-09-12 12:57:36 -07:00
|
|
|
let mDate = moment(str, dateFormat.trim(), true);
|
2019-07-07 17:01:45 -03:00
|
|
|
if (mDate.isValid()) {
|
|
|
|
if (inclusive) {
|
2019-09-12 12:57:36 -07:00
|
|
|
mDate.add(1, 'd');
|
2019-07-07 17:01:45 -03:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return mDate.toDate();
|
2019-07-07 17:01:45 -03:00
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
return durationToDate(/^([\d]+)([wdhms])/.exec(str.trim()), moment(prevTime));
|
|
|
|
};
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let taskCnt = 0;
|
|
|
|
const parseId = function(idStr) {
|
2017-04-11 22:14:25 +08:00
|
|
|
if (typeof idStr === 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
taskCnt = taskCnt + 1;
|
|
|
|
return 'task' + taskCnt;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return idStr;
|
|
|
|
};
|
2015-02-08 20:07:15 +01:00
|
|
|
// id, startDate, endDate
|
|
|
|
// id, startDate, length
|
|
|
|
// id, after x, endDate
|
|
|
|
// id, after x, length
|
|
|
|
// startDate, endDate
|
|
|
|
// startDate, length
|
|
|
|
// after x, endDate
|
|
|
|
// after x, length
|
|
|
|
// endDate
|
|
|
|
// length
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const compileData = function(prevTask, dataStr) {
|
|
|
|
let ds;
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (dataStr.substr(0, 1) === ':') {
|
2019-09-12 12:57:36 -07:00
|
|
|
ds = dataStr.substr(1, dataStr.length);
|
2017-04-11 22:14:25 +08:00
|
|
|
} else {
|
2019-09-12 12:57:36 -07:00
|
|
|
ds = dataStr;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const data = ds.split(',');
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const task = {};
|
2015-08-25 14:49:56 -07:00
|
|
|
|
2019-01-31 15:33:35 +08:00
|
|
|
// Get tags like active, done, crit and milestone
|
2019-09-12 12:57:36 -07:00
|
|
|
getTaskTags(data, task, tags);
|
2019-02-01 13:27:42 +08:00
|
|
|
|
2017-09-14 20:59:58 +08:00
|
|
|
for (let i = 0; i < data.length; i++) {
|
2019-09-12 12:57:36 -07:00
|
|
|
data[i] = data[i].trim();
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let endTimeData = '';
|
2017-04-11 22:14:25 +08:00
|
|
|
switch (data.length) {
|
|
|
|
case 1:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId();
|
|
|
|
task.startTime = prevTask.endTime;
|
|
|
|
endTimeData = data[0];
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 2:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId();
|
|
|
|
task.startTime = getStartDate(undefined, dateFormat, data[0]);
|
|
|
|
endTimeData = data[1];
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 3:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId(data[0]);
|
|
|
|
task.startTime = getStartDate(undefined, dateFormat, data[1]);
|
|
|
|
endTimeData = data[2];
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2019-02-07 11:21:00 -02:00
|
|
|
if (endTimeData) {
|
2019-09-12 12:57:36 -07:00
|
|
|
task.endTime = getEndDate(task.startTime, dateFormat, endTimeData, inclusiveEndDates);
|
|
|
|
task.manualEndTime = moment(endTimeData, 'YYYY-MM-DD', true).isValid();
|
|
|
|
checkTaskDates(task, dateFormat, excludes);
|
2019-02-07 11:21:00 -02:00
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
return task;
|
|
|
|
};
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const parseData = function(prevTaskId, dataStr) {
|
|
|
|
let ds;
|
2017-04-11 22:14:25 +08:00
|
|
|
if (dataStr.substr(0, 1) === ':') {
|
2019-09-12 12:57:36 -07:00
|
|
|
ds = dataStr.substr(1, dataStr.length);
|
2017-04-11 22:14:25 +08:00
|
|
|
} else {
|
2019-09-12 12:57:36 -07:00
|
|
|
ds = dataStr;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const data = ds.split(',');
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const task = {};
|
2015-10-21 21:14:41 +02:00
|
|
|
|
2019-01-31 15:33:35 +08:00
|
|
|
// Get tags like active, done, crit and milestone
|
2019-09-12 12:57:36 -07:00
|
|
|
getTaskTags(data, task, tags);
|
2019-02-01 13:27:42 +08:00
|
|
|
|
2017-09-14 20:59:58 +08:00
|
|
|
for (let i = 0; i < data.length; i++) {
|
2019-09-12 12:57:36 -07:00
|
|
|
data[i] = data[i].trim();
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (data.length) {
|
|
|
|
case 1:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId();
|
2019-03-08 00:19:53 +01:00
|
|
|
task.startTime = {
|
|
|
|
type: 'prevTaskEnd',
|
|
|
|
id: prevTaskId
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
task.endTime = {
|
|
|
|
data: data[0]
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 2:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId();
|
2019-03-08 00:19:53 +01:00
|
|
|
task.startTime = {
|
|
|
|
type: 'getStartDate',
|
|
|
|
startData: data[0]
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
task.endTime = {
|
|
|
|
data: data[1]
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
case 3:
|
2019-09-12 12:57:36 -07:00
|
|
|
task.id = parseId(data[0]);
|
2019-03-08 00:19:53 +01:00
|
|
|
task.startTime = {
|
|
|
|
type: 'getStartDate',
|
|
|
|
startData: data[1]
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
task.endTime = {
|
|
|
|
data: data[2]
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
default:
|
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
return task;
|
|
|
|
};
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let lastTask;
|
|
|
|
let lastTaskID;
|
|
|
|
let rawTasks = [];
|
|
|
|
const taskDb = {};
|
|
|
|
export const addTask = function(descr, data) {
|
2017-09-14 20:59:58 +08:00
|
|
|
const rawTask = {
|
2017-04-11 22:14:25 +08:00
|
|
|
section: currentSection,
|
|
|
|
type: currentSection,
|
|
|
|
processed: false,
|
2019-02-07 11:21:00 -02:00
|
|
|
manualEndTime: false,
|
2019-02-12 17:29:38 -02:00
|
|
|
renderEndTime: null,
|
2017-04-16 23:48:36 +08:00
|
|
|
raw: { data: data },
|
2019-03-08 00:19:53 +01:00
|
|
|
task: descr,
|
|
|
|
classes: []
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
|
|
|
const taskInfo = parseData(lastTaskID, data);
|
|
|
|
rawTask.raw.startTime = taskInfo.startTime;
|
|
|
|
rawTask.raw.endTime = taskInfo.endTime;
|
|
|
|
rawTask.id = taskInfo.id;
|
|
|
|
rawTask.prevTaskId = lastTaskID;
|
|
|
|
rawTask.active = taskInfo.active;
|
|
|
|
rawTask.done = taskInfo.done;
|
|
|
|
rawTask.crit = taskInfo.crit;
|
|
|
|
rawTask.milestone = taskInfo.milestone;
|
|
|
|
|
|
|
|
const pos = rawTasks.push(rawTask);
|
|
|
|
|
|
|
|
lastTaskID = rawTask.id;
|
2017-04-16 23:48:36 +08:00
|
|
|
// Store cross ref
|
2019-09-12 12:57:36 -07:00
|
|
|
taskDb[rawTask.id] = pos - 1;
|
|
|
|
};
|
2015-10-24 12:44:47 +02:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
export const findTaskById = function(id) {
|
|
|
|
const pos = taskDb[id];
|
|
|
|
return rawTasks[pos];
|
|
|
|
};
|
2017-04-11 22:14:25 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
export const addTaskOrg = function(descr, data) {
|
2017-09-14 20:59:58 +08:00
|
|
|
const newTask = {
|
2017-04-11 22:14:25 +08:00
|
|
|
section: currentSection,
|
|
|
|
type: currentSection,
|
|
|
|
description: descr,
|
2019-03-08 00:19:53 +01:00
|
|
|
task: descr,
|
|
|
|
classes: []
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
|
|
|
const taskInfo = compileData(lastTask, data);
|
|
|
|
newTask.startTime = taskInfo.startTime;
|
|
|
|
newTask.endTime = taskInfo.endTime;
|
|
|
|
newTask.id = taskInfo.id;
|
|
|
|
newTask.active = taskInfo.active;
|
|
|
|
newTask.done = taskInfo.done;
|
|
|
|
newTask.crit = taskInfo.crit;
|
|
|
|
newTask.milestone = taskInfo.milestone;
|
|
|
|
lastTask = newTask;
|
|
|
|
tasks.push(newTask);
|
|
|
|
};
|
|
|
|
|
|
|
|
const compileTasks = function() {
|
|
|
|
const compileTask = function(pos) {
|
|
|
|
const task = rawTasks[pos];
|
|
|
|
let startTime = '';
|
2017-04-11 22:14:25 +08:00
|
|
|
switch (rawTasks[pos].raw.startTime.type) {
|
2019-10-27 15:24:56 +01:00
|
|
|
case 'prevTaskEnd': {
|
2019-09-12 12:57:36 -07:00
|
|
|
const prevTask = findTaskById(task.prevTaskId);
|
|
|
|
task.startTime = prevTask.endTime;
|
|
|
|
break;
|
2019-10-27 15:24:56 +01:00
|
|
|
}
|
2017-04-11 22:14:25 +08:00
|
|
|
case 'getStartDate':
|
2019-09-12 12:57:36 -07:00
|
|
|
startTime = getStartDate(undefined, dateFormat, rawTasks[pos].raw.startTime.startData);
|
2017-04-11 22:14:25 +08:00
|
|
|
if (startTime) {
|
2019-09-12 12:57:36 -07:00
|
|
|
rawTasks[pos].startTime = startTime;
|
2015-10-21 21:14:41 +02:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
break;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2015-10-21 21:14:41 +02:00
|
|
|
|
2017-04-11 22:14:25 +08:00
|
|
|
if (rawTasks[pos].startTime) {
|
2019-09-12 12:57:36 -07:00
|
|
|
rawTasks[pos].endTime = getEndDate(
|
|
|
|
rawTasks[pos].startTime,
|
|
|
|
dateFormat,
|
|
|
|
rawTasks[pos].raw.endTime.data,
|
|
|
|
inclusiveEndDates
|
|
|
|
);
|
2017-04-11 22:14:25 +08:00
|
|
|
if (rawTasks[pos].endTime) {
|
2019-09-12 12:57:36 -07:00
|
|
|
rawTasks[pos].processed = true;
|
|
|
|
rawTasks[pos].manualEndTime = moment(
|
|
|
|
rawTasks[pos].raw.endTime.data,
|
|
|
|
'YYYY-MM-DD',
|
|
|
|
true
|
|
|
|
).isValid();
|
|
|
|
checkTaskDates(rawTasks[pos], dateFormat, excludes);
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
|
|
|
}
|
2015-10-24 12:44:47 +02:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
return rawTasks[pos].processed;
|
|
|
|
};
|
2015-10-21 21:14:41 +02:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let allProcessed = true;
|
2017-09-14 20:59:58 +08:00
|
|
|
for (let i = 0; i < rawTasks.length; i++) {
|
2019-09-12 12:57:36 -07:00
|
|
|
compileTask(i);
|
2015-10-24 12:44:47 +02:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
allProcessed = allProcessed && rawTasks[i].processed;
|
2017-04-11 22:14:25 +08:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
return allProcessed;
|
|
|
|
};
|
2017-09-10 21:51:48 +08:00
|
|
|
|
2019-03-08 00:19:53 +01:00
|
|
|
/**
|
|
|
|
* Called by parser when a link is found. Adds the URL to the vertex data.
|
|
|
|
* @param ids Comma separated list of ids
|
|
|
|
* @param linkStr URL to create a link for
|
|
|
|
*/
|
2019-09-12 12:57:36 -07:00
|
|
|
export const setLink = function(ids, _linkStr) {
|
|
|
|
let linkStr = _linkStr;
|
2019-08-11 03:26:44 -07:00
|
|
|
if (config.securityLevel !== 'loose') {
|
2019-09-12 12:57:36 -07:00
|
|
|
linkStr = sanitizeUrl(_linkStr);
|
2019-07-21 07:39:36 -07:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
ids.split(',').forEach(function(id) {
|
|
|
|
let rawTask = findTaskById(id);
|
2019-03-08 00:19:53 +01:00
|
|
|
if (typeof rawTask !== 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
pushFun(id, () => {
|
|
|
|
window.open(linkStr, '_self');
|
|
|
|
});
|
2019-03-08 00:19:53 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
});
|
|
|
|
setClass(ids, 'clickable');
|
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by parser when a special node is found, e.g. a clickable element.
|
|
|
|
* @param ids Comma separated list of ids
|
|
|
|
* @param className Class to add
|
|
|
|
*/
|
2019-09-12 12:57:36 -07:00
|
|
|
export const setClass = function(ids, className) {
|
|
|
|
ids.split(',').forEach(function(id) {
|
|
|
|
let rawTask = findTaskById(id);
|
2019-03-08 00:19:53 +01:00
|
|
|
if (typeof rawTask !== 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
rawTask.classes.push(className);
|
2019-03-08 00:19:53 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
});
|
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
const setClickFun = function(id, functionName, functionArgs) {
|
2019-08-11 03:26:44 -07:00
|
|
|
if (config.securityLevel !== 'loose') {
|
2019-09-12 12:57:36 -07:00
|
|
|
return;
|
2019-07-13 22:50:53 -07:00
|
|
|
}
|
2019-03-08 00:19:53 +01:00
|
|
|
if (typeof functionName === 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
return;
|
2019-03-08 00:19:53 +01:00
|
|
|
}
|
2019-03-10 13:41:59 +01:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let argList = [];
|
2019-03-10 13:41:59 +01:00
|
|
|
if (typeof functionArgs === 'string') {
|
|
|
|
/* Splits functionArgs by ',', ignoring all ',' in double quoted strings */
|
2019-09-12 12:57:36 -07:00
|
|
|
argList = functionArgs.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
|
2019-03-10 13:41:59 +01:00
|
|
|
for (let i = 0; i < argList.length; i++) {
|
2019-09-12 12:57:36 -07:00
|
|
|
let item = argList[i].trim();
|
2019-03-10 13:41:59 +01:00
|
|
|
/* Removes all double quotes at the start and end of an argument */
|
|
|
|
/* This preserves all starting and ending whitespace inside */
|
|
|
|
if (item.charAt(0) === '"' && item.charAt(item.length - 1) === '"') {
|
2019-09-12 12:57:36 -07:00
|
|
|
item = item.substr(1, item.length - 2);
|
2019-03-10 13:41:59 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
argList[i] = item;
|
2019-03-10 13:41:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
let rawTask = findTaskById(id);
|
2019-03-08 00:19:53 +01:00
|
|
|
if (typeof rawTask !== 'undefined') {
|
2019-09-12 12:57:36 -07:00
|
|
|
pushFun(id, () => {
|
|
|
|
window[functionName](...argList);
|
|
|
|
});
|
2019-03-08 00:19:53 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
|
2019-03-09 23:13:53 +01:00
|
|
|
/**
|
|
|
|
* The callbackFunction is executed in a click event bound to the task with the specified id or the task's assigned text
|
|
|
|
* @param id The task's id
|
|
|
|
* @param callbackFunction A function to be executed when clicked on the task or the task's text
|
|
|
|
*/
|
2019-09-12 12:57:36 -07:00
|
|
|
const pushFun = function(id, callbackFunction) {
|
2019-10-27 15:24:56 +01:00
|
|
|
funs.push(function() {
|
2019-07-21 07:39:36 -07:00
|
|
|
// const elem = d3.select(element).select(`[id="${id}"]`)
|
2019-09-12 12:57:36 -07:00
|
|
|
const elem = document.querySelector(`[id="${id}"]`);
|
2019-03-09 23:13:53 +01:00
|
|
|
if (elem !== null) {
|
2019-09-12 12:57:36 -07:00
|
|
|
elem.addEventListener('click', function() {
|
|
|
|
callbackFunction();
|
|
|
|
});
|
2019-03-09 23:13:53 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
});
|
2019-10-27 15:24:56 +01:00
|
|
|
funs.push(function() {
|
2019-07-21 07:39:36 -07:00
|
|
|
// const elem = d3.select(element).select(`[id="${id}-text"]`)
|
2019-09-12 12:57:36 -07:00
|
|
|
const elem = document.querySelector(`[id="${id}-text"]`);
|
2019-03-09 23:13:53 +01:00
|
|
|
if (elem !== null) {
|
2019-09-12 12:57:36 -07:00
|
|
|
elem.addEventListener('click', function() {
|
|
|
|
callbackFunction();
|
|
|
|
});
|
2019-03-09 23:13:53 +01:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
});
|
|
|
|
};
|
2019-03-09 23:13:53 +01:00
|
|
|
|
2019-03-08 00:19:53 +01:00
|
|
|
/**
|
|
|
|
* Called by parser when a click definition is found. Registers an event handler.
|
|
|
|
* @param ids Comma separated list of ids
|
|
|
|
* @param functionName Function to be called on click
|
|
|
|
* @param functionArgs Function args the function should be called with
|
|
|
|
*/
|
2019-09-12 12:57:36 -07:00
|
|
|
export const setClickEvent = function(ids, functionName, functionArgs) {
|
|
|
|
ids.split(',').forEach(function(id) {
|
|
|
|
setClickFun(id, functionName, functionArgs);
|
|
|
|
});
|
|
|
|
setClass(ids, 'clickable');
|
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Binds all functions previously added to fun (specified through click) to the element
|
|
|
|
* @param element
|
|
|
|
*/
|
2019-09-12 12:57:36 -07:00
|
|
|
export const bindFunctions = function(element) {
|
|
|
|
funs.forEach(function(fun) {
|
|
|
|
fun(element);
|
|
|
|
});
|
|
|
|
};
|
2019-03-08 00:19:53 +01:00
|
|
|
|
2017-09-10 21:51:48 +08:00
|
|
|
export default {
|
|
|
|
clear,
|
|
|
|
setDateFormat,
|
2019-07-06 11:54:18 -03:00
|
|
|
getDateFormat,
|
2019-07-07 16:27:28 -03:00
|
|
|
enableInclusiveEndDates,
|
|
|
|
endDatesAreInclusive,
|
2018-03-13 14:01:44 +08:00
|
|
|
setAxisFormat,
|
|
|
|
getAxisFormat,
|
2017-09-10 21:51:48 +08:00
|
|
|
setTitle,
|
|
|
|
getTitle,
|
|
|
|
addSection,
|
2019-07-06 11:54:18 -03:00
|
|
|
getSections,
|
2017-09-10 21:51:48 +08:00
|
|
|
getTasks,
|
|
|
|
addTask,
|
|
|
|
findTaskById,
|
2019-02-06 16:54:09 -02:00
|
|
|
addTaskOrg,
|
2019-06-09 12:40:37 -07:00
|
|
|
setExcludes,
|
2019-07-06 11:54:18 -03:00
|
|
|
getExcludes,
|
2019-03-08 00:19:53 +01:00
|
|
|
setClickEvent,
|
|
|
|
setLink,
|
2019-07-07 17:17:05 -03:00
|
|
|
bindFunctions,
|
|
|
|
durationToDate
|
2019-09-12 12:57:36 -07:00
|
|
|
};
|
2019-02-01 13:27:42 +08:00
|
|
|
|
2019-09-12 12:57:36 -07:00
|
|
|
function getTaskTags(data, task, tags) {
|
|
|
|
let matchFound = true;
|
2019-02-01 13:27:42 +08:00
|
|
|
while (matchFound) {
|
2019-09-12 12:57:36 -07:00
|
|
|
matchFound = false;
|
|
|
|
tags.forEach(function(t) {
|
|
|
|
const pattern = '^\\s*' + t + '\\s*$';
|
|
|
|
const regex = new RegExp(pattern);
|
2019-02-01 14:21:25 +08:00
|
|
|
if (data[0].match(regex)) {
|
2019-09-12 12:57:36 -07:00
|
|
|
task[t] = true;
|
|
|
|
data.shift(1);
|
|
|
|
matchFound = true;
|
2019-02-01 14:21:25 +08:00
|
|
|
}
|
2019-09-12 12:57:36 -07:00
|
|
|
});
|
2019-02-01 13:27:42 +08:00
|
|
|
}
|
|
|
|
}
|