diff --git a/.babelrc b/.babelrc index 2f01e1d..002b4aa 100755 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { "presets": ["env"] -} \ No newline at end of file +} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6cd15c9..769ccc7 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,7 +1,7 @@ name: Publish on NPM on: push: - branches: [ master ] + branches: [master] jobs: publish: diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..53c37a1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json index a7b6f32..86e9e7d 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,4 +1,4 @@ { "tabWidth": 4, "singleQuote": true -} \ No newline at end of file +} diff --git a/README.md b/README.md index 2f2c36e..284efd2 100644 --- a/README.md +++ b/README.md @@ -16,18 +16,22 @@

### Install + ``` npm install frappe-gantt ``` ### Usage + Include it in your HTML: + ``` ``` And start hacking: + ```js var tasks = [ { @@ -45,20 +49,21 @@ var gantt = new Gantt("#gantt", tasks); ``` You can also pass various options to the Gantt constructor: + ```js var gantt = new Gantt("#gantt", tasks, { - header_height: 50, - column_width: 30, - step: 24, - view_modes: ['Quarter Day', 'Half Day', 'Day', 'Week', 'Month'], - bar_height: 20, - bar_corner_radius: 3, - arrow_curve: 5, - padding: 18, - view_mode: 'Day', - date_format: 'YYYY-MM-DD', - language: 'en', // or 'es', 'it', 'ru', 'ptBr', 'fr', 'tr', 'zh', 'de', 'hu' - custom_popup_html: null + header_height: 50, + column_width: 30, + step: 24, + view_modes: ["Quarter Day", "Half Day", "Day", "Week", "Month"], + bar_height: 20, + bar_corner_radius: 3, + arrow_curve: 5, + padding: 18, + view_mode: "Day", + date_format: "YYYY-MM-DD", + language: "en", // or 'es', 'it', 'ru', 'ptBr', 'fr', 'tr', 'zh', 'de', 'hu' + custom_popup_html: null, }); ``` @@ -69,6 +74,7 @@ You can add `dark` class to the container element to apply dark theme. ``` ### Contributing + If you want to contribute enhancements or fixes: 1. Clone this repo. @@ -78,6 +84,7 @@ If you want to contribute enhancements or fixes: 5. Open `index.html` in your browser, make your code changes and test them. ### Publishing + If you have publishing rights (Frappe Team), follow these steps to publish a new version. Assuming the last commit (or a couple of commits) were enhancements or fixes, @@ -85,15 +92,18 @@ Assuming the last commit (or a couple of commits) were enhancements or fixes, 1. Run `yarn build` This will generate files in the `dist/` folder. These files need to be committed. + 1. Run `yarn publish` 1. Type the new version at the prompt Depending on the type of change, you can either bump the patch version or the minor version. For e.g., + ``` 0.5.0 -> 0.6.0 (minor version bump) 0.5.0 -> 0.5.1 (patch version bump) ``` + 1. Now, there will be a commit named after the version you just entered. Include the generated files in `dist/` folder as part of this commit by running the command: ``` git add dist @@ -103,5 +113,6 @@ Assuming the last commit (or a couple of commits) were enhancements or fixes, License: MIT ------------------- +--- + Project maintained by [frappe](https://github.com/frappe) diff --git a/dist/frappe-gantt.css b/dist/frappe-gantt.css index ed1dfe2..a76037c 100644 --- a/dist/frappe-gantt.css +++ b/dist/frappe-gantt.css @@ -66,6 +66,10 @@ border-top-color: #333; } +.gantt { + user-select: none; + -webkit-user-select: none; +} .gantt .grid-background { fill: none; } @@ -94,6 +98,18 @@ fill: #fcf8e3; opacity: 0.5; } +.gantt .week-highlight { + fill: #fcf8e3; + opacity: 0.5; +} +.gantt .month-highlight { + fill: #fcf8e3; + opacity: 0.5; +} +.gantt .year-highlight { + fill: #fcf8e3; + opacity: 0.5; +} .gantt .arrow { fill: none; stroke: #666; @@ -101,10 +117,9 @@ } .gantt .bar { fill: #b8c2cc; - stroke: #8D99A6; + stroke: #8d99a6; stroke-width: 0; transition: stroke-width 0.3s ease; - user-select: none; } .gantt .bar-progress { fill: #acacfa; @@ -114,7 +129,7 @@ } .gantt .bar-invalid { fill: transparent; - stroke: #8D99A6; + stroke: #8d99a6; stroke-width: 1; stroke-dasharray: 5; } @@ -159,7 +174,8 @@ .gantt .bar-wrapper.active .bar-progress { fill: #9494f9; } -.gantt .lower-text, .gantt .upper-text { +.gantt .lower-text, +.gantt .upper-text { font-size: 12px; text-anchor: middle; } diff --git a/dist/frappe-gantt.js b/dist/frappe-gantt.js index 3a88ca6..6c00880 100644 --- a/dist/frappe-gantt.js +++ b/dist/frappe-gantt.js @@ -1,880 +1,913 @@ var Gantt = (function () { - 'use strict'; + 'use strict'; - const YEAR = 'year'; - const MONTH = 'month'; - const DAY = 'day'; - const HOUR = 'hour'; - const MINUTE = 'minute'; - const SECOND = 'second'; - const MILLISECOND = 'millisecond'; + const YEAR = "year"; + const MONTH = "month"; + const DAY = "day"; + const HOUR = "hour"; + const MINUTE = "minute"; + const SECOND = "second"; + const MILLISECOND = "millisecond"; - var date_utils = { - parse(date, date_separator = '-', time_separator = /[.:]/) { - if (date instanceof Date) { - return date; - } - if (typeof date === 'string') { - let date_parts, time_parts; - const parts = date.split(' '); + var date_utils = { + parse_duration(duration) { + const regex = /([0-9])+(y|m|d|h|min|s|ms)/gm; + const matches = regex.exec(duration); - date_parts = parts[0] - .split(date_separator) - .map((val) => parseInt(val, 10)); - time_parts = parts[1] && parts[1].split(time_separator); - - // month is 0 indexed - date_parts[1] = date_parts[1] - 1; - - let vals = date_parts; - - if (time_parts && time_parts.length) { - if (time_parts.length == 4) { - time_parts[3] = '0.' + time_parts[3]; - time_parts[3] = parseFloat(time_parts[3]) * 1000; - } - vals = vals.concat(time_parts); - } - - return new Date(...vals); - } - }, - - to_string(date, with_time = false) { - if (!(date instanceof Date)) { - throw new TypeError('Invalid argument type'); - } - const vals = this.get_date_values(date).map((val, i) => { - if (i === 1) { - // add 1 for month - val = val + 1; - } - - if (i === 6) { - return padStart(val + '', 3, '0'); - } - - return padStart(val + '', 2, '0'); - }); - const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`; - const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`; - - return date_string + (with_time ? ' ' + time_string : ''); - }, - - format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') { - const dateTimeFormat = new Intl.DateTimeFormat(lang, { - month: 'long' - }); - const month_name = dateTimeFormat.format(date); - const month_name_capitalized = - month_name.charAt(0).toUpperCase() + month_name.slice(1); - - const values = this.get_date_values(date).map(d => padStart(d, 2, 0)); - const format_map = { - YYYY: values[0], - MM: padStart(+values[1] + 1, 2, 0), - DD: values[2], - HH: values[3], - mm: values[4], - ss: values[5], - SSS: values[6], - D: values[2], - MMMM: month_name_capitalized, - MMM: month_name_capitalized, - }; - - let str = format_string; - const formatted_values = []; - - Object.keys(format_map) - .sort((a, b) => b.length - a.length) // big string first - .forEach((key) => { - if (str.includes(key)) { - str = str.replace(key, `$${formatted_values.length}`); - formatted_values.push(format_map[key]); - } - }); - - formatted_values.forEach((value, i) => { - str = str.replace(`$${i}`, value); - }); - - return str; - }, - - diff(date_a, date_b, scale = DAY) { - let milliseconds, seconds, hours, minutes, days, months, years; - - milliseconds = date_a - date_b; - seconds = milliseconds / 1000; - minutes = seconds / 60; - hours = minutes / 60; - days = hours / 24; - months = days / 30; - years = months / 12; - - if (!scale.endsWith('s')) { - scale += 's'; - } - - return Math.floor( - { - milliseconds, - seconds, - minutes, - hours, - days, - months, - years, - }[scale] - ); - }, - - today() { - const vals = this.get_date_values(new Date()).slice(0, 3); - return new Date(...vals); - }, - - now() { - return new Date(); - }, - - add(date, qty, scale) { - qty = parseInt(qty, 10); - const vals = [ - date.getFullYear() + (scale === YEAR ? qty : 0), - date.getMonth() + (scale === MONTH ? qty : 0), - date.getDate() + (scale === DAY ? qty : 0), - date.getHours() + (scale === HOUR ? qty : 0), - date.getMinutes() + (scale === MINUTE ? qty : 0), - date.getSeconds() + (scale === SECOND ? qty : 0), - date.getMilliseconds() + (scale === MILLISECOND ? qty : 0), - ]; - return new Date(...vals); - }, - - start_of(date, scale) { - const scores = { - [YEAR]: 6, - [MONTH]: 5, - [DAY]: 4, - [HOUR]: 3, - [MINUTE]: 2, - [SECOND]: 1, - [MILLISECOND]: 0, - }; - - function should_reset(_scale) { - const max_score = scores[scale]; - return scores[_scale] <= max_score; - } - - const vals = [ - date.getFullYear(), - should_reset(YEAR) ? 0 : date.getMonth(), - should_reset(MONTH) ? 1 : date.getDate(), - should_reset(DAY) ? 0 : date.getHours(), - should_reset(HOUR) ? 0 : date.getMinutes(), - should_reset(MINUTE) ? 0 : date.getSeconds(), - should_reset(SECOND) ? 0 : date.getMilliseconds(), - ]; - - return new Date(...vals); - }, - - clone(date) { - return new Date(...this.get_date_values(date)); - }, - - get_date_values(date) { - return [ - date.getFullYear(), - date.getMonth(), - date.getDate(), - date.getHours(), - date.getMinutes(), - date.getSeconds(), - date.getMilliseconds(), - ]; - }, - - get_days_in_month(date) { - const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - - const month = date.getMonth(); - - if (month !== 1) { - return no_of_days[month]; - } - - // Feb - const year = date.getFullYear(); - if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { - return 29; - } - return 28; - }, - }; - - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart - function padStart(str, targetLength, padString) { - str = str + ''; - targetLength = targetLength >> 0; - padString = String(typeof padString !== 'undefined' ? padString : ' '); - if (str.length > targetLength) { - return String(str); - } else { - targetLength = targetLength - str.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); - } - return padString.slice(0, targetLength) + String(str); + if (matches !== null) { + if (matches[2] === "y") { + return { duration: parseInt(matches[1]), scale: `year` }; + } else if (matches[2] === "m") { + return { duration: parseInt(matches[1]), scale: `month` }; + } else if (matches[2] === "d") { + return { duration: parseInt(matches[1]), scale: `day` }; + } else if (matches[2] === "h") { + return { duration: parseInt(matches[1]), scale: `hour` }; + } else if (matches[2] === "min") { + return { duration: parseInt(matches[1]), scale: `minute` }; + } else if (matches[2] === "s") { + return { duration: parseInt(matches[1]), scale: `second` }; + } else if (matches[2] === "ms") { + return { duration: parseInt(matches[1]), scale: `millisecond` }; } - } + } + }, + parse(date, date_separator = "-", time_separator = /[.:]/) { + if (date instanceof Date) { + return date; + } + if (typeof date === "string") { + let date_parts, time_parts; + const parts = date.split(" "); - function $(expr, con) { - return typeof expr === 'string' - ? (con || document).querySelector(expr) - : expr || null; - } + date_parts = parts[0] + .split(date_separator) + .map((val) => parseInt(val, 10)); + time_parts = parts[1] && parts[1].split(time_separator); - function createSVG(tag, attrs) { - const elem = document.createElementNS('http://www.w3.org/2000/svg', tag); - for (let attr in attrs) { - if (attr === 'append_to') { - const parent = attrs.append_to; - parent.appendChild(elem); - } else if (attr === 'innerHTML') { - elem.innerHTML = attrs.innerHTML; - } else { - elem.setAttribute(attr, attrs[attr]); - } + // month is 0 indexed + date_parts[1] = date_parts[1] - 1; + + let vals = date_parts; + + if (time_parts && time_parts.length) { + if (time_parts.length == 4) { + time_parts[3] = "0." + time_parts[3]; + time_parts[3] = parseFloat(time_parts[3]) * 1000; + } + vals = vals.concat(time_parts); } - return elem; - } - function animateSVG(svgElement, attr, from, to) { - const animatedSvgElement = getAnimationElement(svgElement, attr, from, to); + return new Date(...vals); + } + }, - if (animatedSvgElement === svgElement) { - // triggered 2nd time programmatically - // trigger artificial click event - const event = document.createEvent('HTMLEvents'); - event.initEvent('click', true, true); - event.eventName = 'click'; - animatedSvgElement.dispatchEvent(event); + to_string(date, with_time = false) { + if (!(date instanceof Date)) { + throw new TypeError("Invalid argument type"); + } + const vals = this.get_date_values(date).map((val, i) => { + if (i === 1) { + // add 1 for month + val = val + 1; } - } - function getAnimationElement( - svgElement, - attr, + if (i === 6) { + return padStart(val + "", 3, "0"); + } + + return padStart(val + "", 2, "0"); + }); + const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`; + const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`; + + return date_string + (with_time ? " " + time_string : ""); + }, + + format(date, format_string = "YYYY-MM-DD HH:mm:ss.SSS", lang = "en") { + const dateTimeFormat = new Intl.DateTimeFormat(lang, { + month: "long", + }); + const month_name = dateTimeFormat.format(date); + const month_name_capitalized = + month_name.charAt(0).toUpperCase() + month_name.slice(1); + + const values = this.get_date_values(date).map((d) => padStart(d, 2, 0)); + const format_map = { + YYYY: values[0], + MM: padStart(+values[1] + 1, 2, 0), + DD: values[2], + HH: values[3], + mm: values[4], + ss: values[5], + SSS: values[6], + D: values[2], + MMMM: month_name_capitalized, + MMM: month_name_capitalized, + }; + + let str = format_string; + const formatted_values = []; + + Object.keys(format_map) + .sort((a, b) => b.length - a.length) // big string first + .forEach((key) => { + if (str.includes(key)) { + str = str.replace(key, `$${formatted_values.length}`); + formatted_values.push(format_map[key]); + } + }); + + formatted_values.forEach((value, i) => { + str = str.replace(`$${i}`, value); + }); + + return str; + }, + + diff(date_a, date_b, scale = DAY) { + let milliseconds, seconds, hours, minutes, days, months, years; + + milliseconds = date_a - date_b; + seconds = milliseconds / 1000; + minutes = seconds / 60; + hours = minutes / 60; + days = hours / 24; + months = days / 30; + years = months / 12; + + if (!scale.endsWith("s")) { + scale += "s"; + } + + return Math.floor( + { + milliseconds, + seconds, + minutes, + hours, + days, + months, + years, + }[scale], + ); + }, + + today() { + const vals = this.get_date_values(new Date()).slice(0, 3); + return new Date(...vals); + }, + + now() { + return new Date(); + }, + + add(date, qty, scale) { + qty = parseInt(qty, 10); + const vals = [ + date.getFullYear() + (scale === YEAR ? qty : 0), + date.getMonth() + (scale === MONTH ? qty : 0), + date.getDate() + (scale === DAY ? qty : 0), + date.getHours() + (scale === HOUR ? qty : 0), + date.getMinutes() + (scale === MINUTE ? qty : 0), + date.getSeconds() + (scale === SECOND ? qty : 0), + date.getMilliseconds() + (scale === MILLISECOND ? qty : 0), + ]; + return new Date(...vals); + }, + + start_of(date, scale) { + const scores = { + [YEAR]: 6, + [MONTH]: 5, + [DAY]: 4, + [HOUR]: 3, + [MINUTE]: 2, + [SECOND]: 1, + [MILLISECOND]: 0, + }; + + function should_reset(_scale) { + const max_score = scores[scale]; + return scores[_scale] <= max_score; + } + + const vals = [ + date.getFullYear(), + should_reset(YEAR) ? 0 : date.getMonth(), + should_reset(MONTH) ? 1 : date.getDate(), + should_reset(DAY) ? 0 : date.getHours(), + should_reset(HOUR) ? 0 : date.getMinutes(), + should_reset(MINUTE) ? 0 : date.getSeconds(), + should_reset(SECOND) ? 0 : date.getMilliseconds(), + ]; + + return new Date(...vals); + }, + + clone(date) { + return new Date(...this.get_date_values(date)); + }, + + get_date_values(date) { + return [ + date.getFullYear(), + date.getMonth(), + date.getDate(), + date.getHours(), + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds(), + ]; + }, + + get_days_in_month(date) { + const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + + const month = date.getMonth(); + + if (month !== 1) { + return no_of_days[month]; + } + + // Feb + const year = date.getFullYear(); + if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { + return 29; + } + return 28; + }, + }; + + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart + function padStart(str, targetLength, padString) { + str = str + ""; + targetLength = targetLength >> 0; + padString = String(typeof padString !== "undefined" ? padString : " "); + if (str.length > targetLength) { + return String(str); + } else { + targetLength = targetLength - str.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); + } + return padString.slice(0, targetLength) + String(str); + } + } + + function $(expr, con) { + return typeof expr === "string" + ? (con || document).querySelector(expr) + : expr || null; + } + + function createSVG(tag, attrs) { + const elem = document.createElementNS("http://www.w3.org/2000/svg", tag); + for (let attr in attrs) { + if (attr === "append_to") { + const parent = attrs.append_to; + parent.appendChild(elem); + } else if (attr === "innerHTML") { + elem.innerHTML = attrs.innerHTML; + } else { + elem.setAttribute(attr, attrs[attr]); + } + } + return elem; + } + + function animateSVG(svgElement, attr, from, to) { + const animatedSvgElement = getAnimationElement(svgElement, attr, from, to); + + if (animatedSvgElement === svgElement) { + // triggered 2nd time programmatically + // trigger artificial click event + const event = document.createEvent("HTMLEvents"); + event.initEvent("click", true, true); + event.eventName = "click"; + animatedSvgElement.dispatchEvent(event); + } + } + + function getAnimationElement( + svgElement, + attr, + from, + to, + dur = "0.4s", + begin = "0.1s", + ) { + const animEl = svgElement.querySelector("animate"); + if (animEl) { + $.attr(animEl, { + attributeName: attr, from, to, - dur = '0.4s', - begin = '0.1s' - ) { - const animEl = svgElement.querySelector('animate'); - if (animEl) { - $.attr(animEl, { - attributeName: attr, - from, - to, - dur, - begin: 'click + ' + begin, // artificial click - }); - return svgElement; - } - - const animateElement = createSVG('animate', { - attributeName: attr, - from, - to, - dur, - begin, - calcMode: 'spline', - values: from + ';' + to, - keyTimes: '0; 1', - keySplines: cubic_bezier('ease-out'), - }); - svgElement.appendChild(animateElement); - - return svgElement; + dur, + begin: "click + " + begin, // artificial click + }); + return svgElement; } - function cubic_bezier(name) { - return { - ease: '.25 .1 .25 1', - linear: '0 0 1 1', - 'ease-in': '.42 0 1 1', - 'ease-out': '0 0 .58 1', - 'ease-in-out': '.42 0 .58 1', - }[name]; + const animateElement = createSVG("animate", { + attributeName: attr, + from, + to, + dur, + begin, + calcMode: "spline", + values: from + ";" + to, + keyTimes: "0; 1", + keySplines: cubic_bezier("ease-out"), + }); + svgElement.appendChild(animateElement); + + return svgElement; + } + + function cubic_bezier(name) { + return { + ease: ".25 .1 .25 1", + linear: "0 0 1 1", + "ease-in": ".42 0 1 1", + "ease-out": "0 0 .58 1", + "ease-in-out": ".42 0 .58 1", + }[name]; + } + + $.on = (element, event, selector, callback) => { + if (!callback) { + callback = selector; + $.bind(element, event, callback); + } else { + $.delegate(element, event, selector, callback); + } + }; + + $.off = (element, event, handler) => { + element.removeEventListener(event, handler); + }; + + $.bind = (element, event, callback) => { + event.split(/\s+/).forEach(function (event) { + element.addEventListener(event, callback); + }); + }; + + $.delegate = (element, event, selector, callback) => { + element.addEventListener(event, function (e) { + const delegatedTarget = e.target.closest(selector); + if (delegatedTarget) { + e.delegatedTarget = delegatedTarget; + callback.call(this, e, delegatedTarget); + } + }); + }; + + $.closest = (selector, element) => { + if (!element) return null; + + if (element.matches(selector)) { + return element; } - $.on = (element, event, selector, callback) => { - if (!callback) { - callback = selector; - $.bind(element, event, callback); - } else { - $.delegate(element, event, selector, callback); + return $.closest(selector, element.parentNode); + }; + + $.attr = (element, attr, value) => { + if (!value && typeof attr === "string") { + return element.getAttribute(attr); + } + + if (typeof attr === "object") { + for (let key in attr) { + $.attr(element, key, attr[key]); + } + return; + } + + element.setAttribute(attr, value); + }; + + class Bar { + constructor(gantt, task) { + this.set_defaults(gantt, task); + this.prepare(); + this.draw(); + this.bind(); + } + + set_defaults(gantt, task) { + this.action_completed = false; + this.gantt = gantt; + this.task = task; + } + + prepare() { + this.prepare_values(); + this.prepare_helpers(); + } + + prepare_values() { + this.invalid = this.task.invalid; + this.height = this.gantt.options.bar_height; + this.compute_x(); + this.compute_y(); + this.compute_duration(); + this.corner_radius = this.gantt.options.bar_corner_radius; + this.width = this.gantt.options.column_width * this.duration; + this.progress_width = + this.gantt.options.column_width * + this.duration * + (this.task.progress / 100) || 0; + this.group = createSVG("g", { + class: "bar-wrapper " + (this.task.custom_class || ""), + "data-id": this.task.id, + }); + this.bar_group = createSVG("g", { + class: "bar-group", + append_to: this.group, + }); + this.handle_group = createSVG("g", { + class: "handle-group", + append_to: this.group, + }); + } + + prepare_helpers() { + SVGElement.prototype.getX = function () { + return +this.getAttribute("x"); + }; + SVGElement.prototype.getY = function () { + return +this.getAttribute("y"); + }; + SVGElement.prototype.getWidth = function () { + return +this.getAttribute("width"); + }; + SVGElement.prototype.getHeight = function () { + return +this.getAttribute("height"); + }; + SVGElement.prototype.getEndX = function () { + return this.getX() + this.getWidth(); + }; + } + + prepare_expected_progress_values() { + this.compute_expected_progress(); + this.expected_progress_width = + this.gantt.options.column_width * + this.duration * + (this.expected_progress / 100) || 0; + } + + draw() { + this.draw_bar(); + if (this.gantt.options.show_expected_progress) { + this.prepare_expected_progress_values(); + this.draw_expected_progress_bar(); + } + this.draw_progress_bar(); + this.draw_label(); + this.draw_resize_handles(); + } + + draw_bar() { + this.$bar = createSVG("rect", { + x: this.x, + y: this.y, + width: this.width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar", + append_to: this.bar_group, + }); + + animateSVG(this.$bar, "width", 0, this.width); + + if (this.invalid) { + this.$bar.classList.add("bar-invalid"); + } + } + + draw_expected_progress_bar() { + if (this.invalid) return; + this.$expected_bar_progress = createSVG("rect", { + x: this.x, + y: this.y, + width: this.expected_progress_width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar-expected-progress", + append_to: this.bar_group, + }); + + animateSVG( + this.$expected_bar_progress, + "width", + 0, + this.expected_progress_width, + ); + } + + draw_progress_bar() { + if (this.invalid) return; + this.$bar_progress = createSVG("rect", { + x: this.x, + y: this.y, + width: this.progress_width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar-progress", + append_to: this.bar_group, + }); + + animateSVG(this.$bar_progress, "width", 0, this.progress_width); + } + + draw_label() { + createSVG("text", { + x: this.x + this.width / 2, + y: this.y + this.height / 2, + innerHTML: this.task.name, + class: "bar-label", + append_to: this.bar_group, + }); + // labels get BBox in the next tick + requestAnimationFrame(() => this.update_label_position()); + } + + draw_resize_handles() { + if (this.invalid) return; + + const bar = this.$bar; + const handle_width = 8; + + createSVG("rect", { + x: bar.getX() + bar.getWidth() - 9, + y: bar.getY() + 1, + width: handle_width, + height: this.height - 2, + rx: this.corner_radius, + ry: this.corner_radius, + class: "handle right", + append_to: this.handle_group, + }); + + createSVG("rect", { + x: bar.getX() + 1, + y: bar.getY() + 1, + width: handle_width, + height: this.height - 2, + rx: this.corner_radius, + ry: this.corner_radius, + class: "handle left", + append_to: this.handle_group, + }); + + this.$handle_progress = createSVG("polygon", { + points: this.get_progress_polygon_points().join(","), + class: "handle progress", + append_to: this.handle_group, + }); + } + + get_progress_polygon_points() { + const bar_progress = this.$bar_progress; + return [ + bar_progress.getEndX() - 5, + bar_progress.getY() + bar_progress.getHeight(), + bar_progress.getEndX() + 5, + bar_progress.getY() + bar_progress.getHeight(), + bar_progress.getEndX(), + bar_progress.getY() + bar_progress.getHeight() - 8.66, + ]; + } + + bind() { + if (this.invalid) return; + this.setup_click_event(); + } + + setup_click_event() { + $.on(this.group, "focus " + this.gantt.options.popup_trigger, (e) => { + if (this.action_completed) { + // just finished a move action, wait for a few seconds + return; } - }; - $.off = (element, event, handler) => { - element.removeEventListener(event, handler); - }; + this.show_popup(); + this.gantt.unselect_all(); + this.group.classList.add("active"); + }); - $.bind = (element, event, callback) => { - event.split(/\s+/).forEach(function (event) { - element.addEventListener(event, callback); + $.on(this.group, "dblclick", (e) => { + if (this.action_completed) { + // just finished a move action, wait for a few seconds + return; + } + + this.gantt.trigger_event("click", [this.task]); + }); + } + + show_popup() { + if (this.gantt.bar_being_dragged) return; + + const start_date = date_utils.format( + this.task._start, + "MMM D", + this.gantt.options.language, + ); + const end_date = date_utils.format( + date_utils.add(this.task._end, -1, "second"), + "MMM D", + this.gantt.options.language, + ); + const subtitle = start_date + " - " + end_date; + + this.gantt.show_popup({ + target_element: this.$bar, + title: this.task.name, + subtitle: subtitle, + task: this.task, + }); + } + + update_bar_position({ x = null, width = null }) { + const bar = this.$bar; + if (x) { + // get all x values of parent task + const xs = this.task.dependencies.map((dep) => { + return this.gantt.get_bar(dep).$bar.getX(); }); - }; - - $.delegate = (element, event, selector, callback) => { - element.addEventListener(event, function (e) { - const delegatedTarget = e.target.closest(selector); - if (delegatedTarget) { - e.delegatedTarget = delegatedTarget; - callback.call(this, e, delegatedTarget); - } - }); - }; - - $.closest = (selector, element) => { - if (!element) return null; - - if (element.matches(selector)) { - return element; + // child task must not go before parent + const valid_x = xs.reduce((prev, curr) => { + return x >= curr; + }, x); + if (!valid_x) { + width = null; + return; } + this.update_attr(bar, "x", x); + } + if (width) { + this.update_attr(bar, "width", width); + } + this.update_label_position(); + this.update_handle_position(); + if (this.gantt.options.show_expected_progress) { + this.date_changed(); + this.compute_duration(); + this.update_expected_progressbar_position(); + } + this.update_progressbar_position(); + this.update_arrow_position(); + } - return $.closest(selector, element.parentNode); - }; + date_changed() { + let changed = false; + const { new_start_date, new_end_date } = this.compute_start_end_date(); - $.attr = (element, attr, value) => { - if (!value && typeof attr === 'string') { - return element.getAttribute(attr); - } + if (Number(this.task._start) !== Number(new_start_date)) { + changed = true; + this.task._start = new_start_date; + } - if (typeof attr === 'object') { - for (let key in attr) { - $.attr(element, key, attr[key]); - } - return; - } + if (Number(this.task._end) !== Number(new_end_date)) { + changed = true; + this.task._end = new_end_date; + } + if (!changed) return; + + this.gantt.trigger_event("date_change", [ + this.task, + new_start_date, + date_utils.add(new_end_date, -1, "second"), + ]); + } + + progress_changed() { + const new_progress = this.compute_progress(); + this.task.progress = new_progress; + this.gantt.trigger_event("progress_change", [this.task, new_progress]); + } + + set_action_completed() { + this.action_completed = true; + setTimeout(() => (this.action_completed = false), 1000); + } + + compute_start_end_date() { + const bar = this.$bar; + const x_in_units = bar.getX() / this.gantt.options.column_width; + const new_start_date = date_utils.add( + this.gantt.gantt_start, + x_in_units * this.gantt.options.step, + "hour", + ); + const width_in_units = bar.getWidth() / this.gantt.options.column_width; + const new_end_date = date_utils.add( + new_start_date, + width_in_units * this.gantt.options.step, + "hour", + ); + + return { new_start_date, new_end_date }; + } + + compute_progress() { + const progress = + (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100; + return parseInt(progress, 10); + } + + compute_expected_progress() { + this.expected_progress = + date_utils.diff(date_utils.today(), this.task._start, "hour") / + this.gantt.options.step; + this.expected_progress = + ((this.expected_progress < this.duration + ? this.expected_progress + : this.duration) * + 100) / + this.duration; + } + + compute_x() { + const { step, column_width } = this.gantt.options; + const task_start = this.task._start; + const gantt_start = this.gantt.gantt_start; + + const diff = date_utils.diff(task_start, gantt_start, "hour"); + let x = (diff / step) * column_width; + + if (this.gantt.view_is("Month")) { + const diff = date_utils.diff(task_start, gantt_start, "day"); + x = (diff * column_width) / 30; + } + this.x = x; + } + + compute_y() { + this.y = + this.gantt.options.header_height + + this.gantt.options.padding + + this.task._index * (this.height + this.gantt.options.padding); + } + + compute_duration() { + this.duration = + date_utils.diff(this.task._end, this.task._start, "hour") / + this.gantt.options.step; + } + + get_snap_position(dx) { + let odx = dx, + rem, + position; + + if (this.gantt.view_is("Week")) { + rem = dx % (this.gantt.options.column_width / 7); + position = + odx - + rem + + (rem < this.gantt.options.column_width / 14 + ? 0 + : this.gantt.options.column_width / 7); + } else if (this.gantt.view_is("Month")) { + rem = dx % (this.gantt.options.column_width / 30); + position = + odx - + rem + + (rem < this.gantt.options.column_width / 60 + ? 0 + : this.gantt.options.column_width / 30); + } else { + rem = dx % this.gantt.options.column_width; + position = + odx - + rem + + (rem < this.gantt.options.column_width / 2 + ? 0 + : this.gantt.options.column_width); + } + return position; + } + + update_attr(element, attr, value) { + value = +value; + if (!isNaN(value)) { element.setAttribute(attr, value); - }; - - class Bar { - constructor(gantt, task) { - this.set_defaults(gantt, task); - this.prepare(); - this.draw(); - this.bind(); - } - - set_defaults(gantt, task) { - this.action_completed = false; - this.gantt = gantt; - this.task = task; - } - - prepare() { - this.prepare_values(); - this.prepare_helpers(); - } - - prepare_values() { - this.invalid = this.task.invalid; - this.height = this.gantt.options.bar_height; - this.compute_x(); - this.compute_y(); - this.compute_duration(); - this.corner_radius = this.gantt.options.bar_corner_radius; - this.width = this.gantt.options.column_width * this.duration; - this.progress_width = - this.gantt.options.column_width * - this.duration * - (this.task.progress / 100) || 0; - this.group = createSVG('g', { - class: 'bar-wrapper ' + (this.task.custom_class || ''), - 'data-id': this.task.id, - }); - this.bar_group = createSVG('g', { - class: 'bar-group', - append_to: this.group, - }); - this.handle_group = createSVG('g', { - class: 'handle-group', - append_to: this.group, - }); - } - - prepare_helpers() { - SVGElement.prototype.getX = function () { - return +this.getAttribute('x'); - }; - SVGElement.prototype.getY = function () { - return +this.getAttribute('y'); - }; - SVGElement.prototype.getWidth = function () { - return +this.getAttribute('width'); - }; - SVGElement.prototype.getHeight = function () { - return +this.getAttribute('height'); - }; - SVGElement.prototype.getEndX = function () { - return this.getX() + this.getWidth(); - }; - } - - prepare_expected_progress_values() { - this.compute_expected_progress(); - this.expected_progress_width = - this.gantt.options.column_width * - this.duration * - (this.expected_progress / 100) || 0; - } - - draw() { - this.draw_bar(); - if (this.gantt.options.show_expected_progress) { - this.prepare_expected_progress_values(); - this.draw_expected_progress_bar(); - } - this.draw_progress_bar(); - this.draw_label(); - this.draw_resize_handles(); - } - - draw_bar() { - this.$bar = createSVG('rect', { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar', - append_to: this.bar_group, - }); - - animateSVG(this.$bar, 'width', 0, this.width); - - if (this.invalid) { - this.$bar.classList.add('bar-invalid'); - } - } - - draw_expected_progress_bar() { - if (this.invalid) return; - this.$expected_bar_progress = createSVG('rect', { - x: this.x, - y: this.y, - width: this.expected_progress_width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar-expected-progress', - append_to: this.bar_group, - }); - - animateSVG(this.$expected_bar_progress, 'width', 0, this.expected_progress_width); - } - - draw_progress_bar() { - if (this.invalid) return; - this.$bar_progress = createSVG('rect', { - x: this.x, - y: this.y, - width: this.progress_width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar-progress', - append_to: this.bar_group, - }); - - animateSVG(this.$bar_progress, 'width', 0, this.progress_width); - } - - draw_label() { - createSVG('text', { - x: this.x + this.width / 2, - y: this.y + this.height / 2, - innerHTML: this.task.name, - class: 'bar-label', - append_to: this.bar_group, - }); - // labels get BBox in the next tick - requestAnimationFrame(() => this.update_label_position()); - } - - draw_resize_handles() { - if (this.invalid) return; - - const bar = this.$bar; - const handle_width = 8; - - createSVG('rect', { - x: bar.getX() + bar.getWidth() - 9, - y: bar.getY() + 1, - width: handle_width, - height: this.height - 2, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'handle right', - append_to: this.handle_group, - }); - - createSVG('rect', { - x: bar.getX() + 1, - y: bar.getY() + 1, - width: handle_width, - height: this.height - 2, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'handle left', - append_to: this.handle_group, - }); - - if (this.task.progress && this.task.progress < 100) { - this.$handle_progress = createSVG('polygon', { - points: this.get_progress_polygon_points().join(','), - class: 'handle progress', - append_to: this.handle_group, - }); - } - } - - get_progress_polygon_points() { - const bar_progress = this.$bar_progress; - return [ - bar_progress.getEndX() - 5, - bar_progress.getY() + bar_progress.getHeight(), - bar_progress.getEndX() + 5, - bar_progress.getY() + bar_progress.getHeight(), - bar_progress.getEndX(), - bar_progress.getY() + bar_progress.getHeight() - 8.66, - ]; - } - - bind() { - if (this.invalid) return; - this.setup_click_event(); - } - - setup_click_event() { - $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => { - if (this.action_completed) { - // just finished a move action, wait for a few seconds - return; - } - - this.show_popup(); - this.gantt.unselect_all(); - this.group.classList.add('active'); - }); - - $.on(this.group, 'dblclick', (e) => { - if (this.action_completed) { - // just finished a move action, wait for a few seconds - return; - } - - this.gantt.trigger_event('click', [this.task]); - }); - } - - show_popup() { - if (this.gantt.bar_being_dragged) return; - - const start_date = date_utils.format( - this.task._start, - 'MMM D', - this.gantt.options.language - ); - const end_date = date_utils.format( - date_utils.add(this.task._end, -1, 'second'), - 'MMM D', - this.gantt.options.language - ); - const subtitle = start_date + ' - ' + end_date; - - this.gantt.show_popup({ - target_element: this.$bar, - title: this.task.name, - subtitle: subtitle, - task: this.task, - }); - } - - update_bar_position({ x = null, width = null }) { - const bar = this.$bar; - if (x) { - // get all x values of parent task - const xs = this.task.dependencies.map((dep) => { - return this.gantt.get_bar(dep).$bar.getX(); - }); - // child task must not go before parent - const valid_x = xs.reduce((prev, curr) => { - return x >= curr; - }, x); - if (!valid_x) { - width = null; - return; - } - this.update_attr(bar, 'x', x); - } - if (width && width >= this.gantt.options.column_width) { - this.update_attr(bar, 'width', width); - } - this.update_label_position(); - this.update_handle_position(); - if (this.gantt.options.show_expected_progress){ - this.date_changed(); - this.compute_duration(); - this.update_expected_progressbar_position(); - } - this.update_progressbar_position(); - this.update_arrow_position(); - } - - date_changed() { - let changed = false; - const { new_start_date, new_end_date } = this.compute_start_end_date(); - - if (Number(this.task._start) !== Number(new_start_date)) { - changed = true; - this.task._start = new_start_date; - } - - if (Number(this.task._end) !== Number(new_end_date)) { - changed = true; - this.task._end = new_end_date; - } - - if (!changed) return; - - this.gantt.trigger_event('date_change', [ - this.task, - new_start_date, - date_utils.add(new_end_date, -1, 'second'), - ]); - } - - progress_changed() { - const new_progress = this.compute_progress(); - this.task.progress = new_progress; - this.gantt.trigger_event('progress_change', [this.task, new_progress]); - } - - set_action_completed() { - this.action_completed = true; - setTimeout(() => (this.action_completed = false), 1000); - } - - compute_start_end_date() { - const bar = this.$bar; - const x_in_units = bar.getX() / this.gantt.options.column_width; - const new_start_date = date_utils.add( - this.gantt.gantt_start, - x_in_units * this.gantt.options.step, - 'hour' - ); - const width_in_units = bar.getWidth() / this.gantt.options.column_width; - const new_end_date = date_utils.add( - new_start_date, - width_in_units * this.gantt.options.step, - 'hour' - ); - - return { new_start_date, new_end_date }; - } - - compute_progress() { - const progress = - (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100; - return parseInt(progress, 10); - } - - compute_expected_progress() { - this.expected_progress = date_utils.diff(date_utils.today(), this.task._start, 'hour') / this.gantt.options.step; - this.expected_progress = ((this.expected_progress < this.duration) ? this.expected_progress : this.duration) * 100 / this.duration; - } - - compute_x() { - const { step, column_width } = this.gantt.options; - const task_start = this.task._start; - const gantt_start = this.gantt.gantt_start; - - const diff = date_utils.diff(task_start, gantt_start, 'hour'); - let x = (diff / step) * column_width; - - if (this.gantt.view_is('Month')) { - const diff = date_utils.diff(task_start, gantt_start, 'day'); - x = (diff * column_width) / 30; - } - this.x = x; - } - - compute_y() { - this.y = ( - this.gantt.options.header_height + - this.gantt.options.padding + - this.task._index * (this.height + this.gantt.options.padding) - ); - } - - compute_duration() { - this.duration = date_utils.diff(this.task._end, this.task._start, 'hour') / - this.gantt.options.step; - } - - get_snap_position(dx) { - let odx = dx, - rem, - position; - - if (this.gantt.view_is('Week')) { - rem = dx % (this.gantt.options.column_width / 7); - position = - odx - - rem + - (rem < this.gantt.options.column_width / 14 - ? 0 - : this.gantt.options.column_width / 7); - } else if (this.gantt.view_is('Month')) { - rem = dx % (this.gantt.options.column_width / 30); - position = - odx - - rem + - (rem < this.gantt.options.column_width / 60 - ? 0 - : this.gantt.options.column_width / 30); - } else { - rem = dx % this.gantt.options.column_width; - position = - odx - - rem + - (rem < this.gantt.options.column_width / 2 - ? 0 - : this.gantt.options.column_width); - } - return position; - } - - update_attr(element, attr, value) { - value = +value; - if (!isNaN(value)) { - element.setAttribute(attr, value); - } - return element; - } - - update_expected_progressbar_position() { - if (this.invalid) return; - this.$expected_bar_progress.setAttribute('x', this.$bar.getX()); - this.compute_expected_progress(); - this.$expected_bar_progress.setAttribute( - 'width', - this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0 - ); - } - - update_progressbar_position() { - if (this.invalid) return; - this.$bar_progress.setAttribute('x', this.$bar.getX()); - this.$bar_progress.setAttribute( - 'width', - this.$bar.getWidth() * (this.task.progress / 100) - ); - } - - update_label_position() { - const bar = this.$bar, - label = this.group.querySelector('.bar-label'); - - if (label.getBBox().width > bar.getWidth()) { - label.classList.add('big'); - label.setAttribute('x', bar.getX() + bar.getWidth() + 5); - } else { - label.classList.remove('big'); - label.setAttribute('x', bar.getX() + bar.getWidth() / 2); - } - } - - update_handle_position() { - if (this.invalid) return; - const bar = this.$bar; - this.handle_group - .querySelector('.handle.left') - .setAttribute('x', bar.getX() + 1); - this.handle_group - .querySelector('.handle.right') - .setAttribute('x', bar.getEndX() - 9); - const handle = this.group.querySelector('.handle.progress'); - handle && - handle.setAttribute('points', this.get_progress_polygon_points()); - } - - update_arrow_position() { - this.arrows = this.arrows || []; - for (let arrow of this.arrows) { - arrow.update(); - } - } + } + return element; } - class Arrow { - constructor(gantt, from_task, to_task) { - this.gantt = gantt; - this.from_task = from_task; - this.to_task = to_task; + update_expected_progressbar_position() { + if (this.invalid) return; + this.$expected_bar_progress.setAttribute("x", this.$bar.getX()); + this.compute_expected_progress(); + this.$expected_bar_progress.setAttribute( + "width", + this.gantt.options.column_width * + this.duration * + (this.expected_progress / 100) || 0, + ); + } - this.calculate_path(); - this.draw(); - } + update_progressbar_position() { + if (this.invalid) return; + this.$bar_progress.setAttribute("x", this.$bar.getX()); + this.$bar_progress.setAttribute( + "width", + this.$bar.getWidth() * (this.task.progress / 100), + ); + } - calculate_path() { - let start_x = - this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2; + update_label_position() { + const bar = this.$bar, + label = this.group.querySelector(".bar-label"); - const condition = () => - this.to_task.$bar.getX() < start_x + this.gantt.options.padding && - start_x > this.from_task.$bar.getX() + this.gantt.options.padding; + if (label.getBBox().width > bar.getWidth()) { + label.classList.add("big"); + label.setAttribute("x", bar.getX() + bar.getWidth() + 5); + } else { + label.classList.remove("big"); + label.setAttribute("x", bar.getX() + bar.getWidth() / 2); + } + } - while (condition()) { - start_x -= 10; - } + update_handle_position() { + if (this.invalid) return; + const bar = this.$bar; + this.handle_group + .querySelector(".handle.left") + .setAttribute("x", bar.getX() + 1); + this.handle_group + .querySelector(".handle.right") + .setAttribute("x", bar.getEndX() - 9); + const handle = this.group.querySelector(".handle.progress"); + handle && handle.setAttribute("points", this.get_progress_polygon_points()); + } - const start_y = - this.gantt.options.header_height + - this.gantt.options.bar_height + - (this.gantt.options.padding + this.gantt.options.bar_height) * - this.from_task.task._index + - this.gantt.options.padding; + update_arrow_position() { + this.arrows = this.arrows || []; + for (let arrow of this.arrows) { + arrow.update(); + } + } + } - const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2; - const end_y = - this.gantt.options.header_height + - this.gantt.options.bar_height / 2 + - (this.gantt.options.padding + this.gantt.options.bar_height) * - this.to_task.task._index + - this.gantt.options.padding; + class Arrow { + constructor(gantt, from_task, to_task) { + this.gantt = gantt; + this.from_task = from_task; + this.to_task = to_task; - const from_is_below_to = - this.from_task.task._index > this.to_task.task._index; - const curve = this.gantt.options.arrow_curve; - const clockwise = from_is_below_to ? 1 : 0; - const curve_y = from_is_below_to ? -curve : curve; - const offset = from_is_below_to - ? end_y + this.gantt.options.arrow_curve - : end_y - this.gantt.options.arrow_curve; + this.calculate_path(); + this.draw(); + } - this.path = ` + calculate_path() { + let start_x = + this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2; + + const condition = () => + this.to_task.$bar.getX() < start_x + this.gantt.options.padding && + start_x > this.from_task.$bar.getX() + this.gantt.options.padding; + + while (condition()) { + start_x -= 10; + } + + const start_y = + this.gantt.options.header_height + + this.gantt.options.bar_height + + (this.gantt.options.padding + this.gantt.options.bar_height) * + this.from_task.task._index + + this.gantt.options.padding; + + const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2; + const end_y = + this.gantt.options.header_height + + this.gantt.options.bar_height / 2 + + (this.gantt.options.padding + this.gantt.options.bar_height) * + this.to_task.task._index + + this.gantt.options.padding; + + const from_is_below_to = + this.from_task.task._index > this.to_task.task._index; + const curve = this.gantt.options.arrow_curve; + const clockwise = from_is_below_to ? 1 : 0; + const curve_y = from_is_below_to ? -curve : curve; + const offset = from_is_below_to + ? end_y + this.gantt.options.arrow_curve + : end_y - this.gantt.options.arrow_curve; + + this.path = ` M ${start_x} ${start_y} V ${offset} a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y} @@ -883,18 +916,16 @@ var Gantt = (function () { l 5 5 l -5 5`; - if ( - this.to_task.$bar.getX() < - this.from_task.$bar.getX() + this.gantt.options.padding - ) { - const down_1 = this.gantt.options.padding / 2 - curve; - const down_2 = - this.to_task.$bar.getY() + - this.to_task.$bar.getHeight() / 2 - - curve_y; - const left = this.to_task.$bar.getX() - this.gantt.options.padding; + if ( + this.to_task.$bar.getX() < + this.from_task.$bar.getX() + this.gantt.options.padding + ) { + const down_1 = this.gantt.options.padding / 2 - curve; + const down_2 = + this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - curve_y; + const left = this.to_task.$bar.getX() - this.gantt.options.padding; - this.path = ` + this.path = ` M ${start_x} ${start_y} v ${down_1} a ${curve} ${curve} 0 0 1 -${curve} ${curve} @@ -906,1018 +937,1091 @@ var Gantt = (function () { m -5 -5 l 5 5 l -5 5`; - } - } - - draw() { - this.element = createSVG('path', { - d: this.path, - 'data-from': this.from_task.task.id, - 'data-to': this.to_task.task.id, - }); - } - - update() { - this.calculate_path(); - this.element.setAttribute('d', this.path); - } + } } - class Popup { - constructor(parent, custom_html) { - this.parent = parent; - this.custom_html = custom_html; - this.make(); - } + draw() { + this.element = createSVG("path", { + d: this.path, + "data-from": this.from_task.task.id, + "data-to": this.to_task.task.id, + }); + } - make() { - this.parent.innerHTML = ` + update() { + this.calculate_path(); + this.element.setAttribute("d", this.path); + } + } + + class Popup { + constructor(parent, custom_html) { + this.parent = parent; + this.custom_html = custom_html; + this.make(); + } + + make() { + this.parent.innerHTML = `
`; - this.hide(); + this.hide(); - this.title = this.parent.querySelector('.title'); - this.subtitle = this.parent.querySelector('.subtitle'); - this.pointer = this.parent.querySelector('.pointer'); - } - - show(options) { - if (!options.target_element) { - throw new Error('target_element is required to show popup'); - } - if (!options.position) { - options.position = 'left'; - } - const target_element = options.target_element; - - if (this.custom_html) { - let html = this.custom_html(options.task); - html += '
'; - this.parent.innerHTML = html; - this.pointer = this.parent.querySelector('.pointer'); - } else { - // set data - this.title.innerHTML = options.title; - this.subtitle.innerHTML = options.subtitle; - this.parent.style.width = this.parent.clientWidth + 'px'; - } - - // set position - let position_meta; - if (target_element instanceof HTMLElement) { - position_meta = target_element.getBoundingClientRect(); - } else if (target_element instanceof SVGElement) { - position_meta = options.target_element.getBBox(); - } - - if (options.position === 'left') { - this.parent.style.left = - position_meta.x + (position_meta.width + 10) + 'px'; - this.parent.style.top = position_meta.y + 'px'; - - this.pointer.style.transform = 'rotateZ(90deg)'; - this.pointer.style.left = '-7px'; - this.pointer.style.top = '2px'; - } - - // show - this.parent.style.opacity = 1; - } - - hide() { - this.parent.style.opacity = 0; - this.parent.style.left = 0; - } + this.title = this.parent.querySelector(".title"); + this.subtitle = this.parent.querySelector(".subtitle"); + this.pointer = this.parent.querySelector(".pointer"); } - const VIEW_MODE = { - QUARTER_DAY: 'Quarter Day', - HALF_DAY: 'Half Day', - DAY: 'Day', - WEEK: 'Week', - MONTH: 'Month', - YEAR: 'Year', - }; + show(options) { + if (!options.target_element) { + throw new Error("target_element is required to show popup"); + } + if (!options.position) { + options.position = "left"; + } + const target_element = options.target_element; - class Gantt { - constructor(wrapper, tasks, options) { - this.setup_wrapper(wrapper); - this.setup_options(options); - this.setup_tasks(tasks); - // initialize with default view mode - this.change_view_mode(); - this.bind_events(); + if (this.custom_html) { + let html = this.custom_html(options.task); + html += '
'; + this.parent.innerHTML = html; + this.pointer = this.parent.querySelector(".pointer"); + } else { + // set data + this.title.innerHTML = options.title; + this.subtitle.innerHTML = options.subtitle; + this.parent.style.width = this.parent.clientWidth + "px"; + } + + // set position + let position_meta; + if (target_element instanceof HTMLElement) { + position_meta = target_element.getBoundingClientRect(); + } else if (target_element instanceof SVGElement) { + position_meta = options.target_element.getBBox(); + } + + if (options.position === "left") { + this.parent.style.left = + position_meta.x + (position_meta.width + 10) + "px"; + this.parent.style.top = position_meta.y + "px"; + + this.pointer.style.transform = "rotateZ(90deg)"; + this.pointer.style.left = "-7px"; + this.pointer.style.top = "2px"; + } + + // show + this.parent.style.opacity = 1; + } + + hide() { + this.parent.style.opacity = 0; + this.parent.style.left = 0; + } + } + + const VIEW_MODE = { + HOUR: "Hour", + QUARTER_DAY: "Quarter Day", + HALF_DAY: "Half Day", + DAY: "Day", + WEEK: "Week", + MONTH: "Month", + YEAR: "Year", + }; + + const VIEW_MODE_PADDING = { + HOUR: ["7d", "7d"], + QUARTER_DAY: ["7d", "7d"], + HALF_DAY: ["7d", "7d"], + DAY: ["1m", "1m"], + WEEK: ["1m", "1m"], + MONTH: ["1m", "1m"], + YEAR: ["2y", "2y"], + }; + + class Gantt { + constructor(wrapper, tasks, options) { + this.setup_wrapper(wrapper); + this.setup_options(options); + this.setup_tasks(tasks); + // initialize with default view mode + this.change_view_mode(); + this.bind_events(); + } + + setup_wrapper(element) { + let svg_element, wrapper_element; + + // CSS Selector is passed + if (typeof element === "string") { + element = document.querySelector(element); + } + + // get the SVGElement + if (element instanceof HTMLElement) { + wrapper_element = element; + svg_element = element.querySelector("svg"); + } else if (element instanceof SVGElement) { + svg_element = element; + } else { + throw new TypeError( + "Frappé Gantt only supports usage of a string CSS selector," + + " HTML DOM element or SVG DOM element for the 'element' parameter", + ); + } + + // svg element + if (!svg_element) { + // create it + this.$svg = createSVG("svg", { + append_to: wrapper_element, + class: "gantt", + }); + } else { + this.$svg = svg_element; + this.$svg.classList.add("gantt"); + } + + // wrapper element + this.$container = document.createElement("div"); + this.$container.classList.add("gantt-container"); + + const parent_element = this.$svg.parentElement; + parent_element.appendChild(this.$container); + this.$container.appendChild(this.$svg); + + // popup wrapper + this.popup_wrapper = document.createElement("div"); + this.popup_wrapper.classList.add("popup-wrapper"); + this.$container.appendChild(this.popup_wrapper); + } + + setup_options(options) { + const default_options = { + header_height: 50, + column_width: 30, + step: 24, + view_modes: [...Object.values(VIEW_MODE)], + bar_height: 20, + bar_corner_radius: 3, + arrow_curve: 5, + padding: 18, + view_mode: "Day", + date_format: "YYYY-MM-DD", + popup_trigger: "click", + custom_popup_html: null, + language: "en", + }; + this.options = Object.assign({}, default_options, options); + for (let [key, value] of Object.entries(options.view_mode_padding)) { + if (typeof value === "string") { + // Configure for single value given + options.view_mode_padding[key] = [value, value]; + } + } + + console.log(options.view_mode_padding); + this.options.view_mode_padding = { + ...VIEW_MODE_PADDING, + ...options.view_mode_padding, + }; + } + + setup_tasks(tasks) { + // prepare tasks + this.tasks = tasks.map((task, i) => { + // convert to Date objects + task._start = date_utils.parse(task.start); + if (task.end === undefined && task.duration !== undefined) { + task.end = task._start; + let durations = task.duration.split(" "); + + durations.forEach((tmpDuration) => { + let { duration, scale } = date_utils.parse_duration(tmpDuration); + task.end = date_utils.add(task.end, duration, scale); + }); + } + task._end = date_utils.parse(task.end); + + // make task invalid if duration too large + if (date_utils.diff(task._end, task._start, "year") > 10) { + task.end = null; } - setup_wrapper(element) { - let svg_element, wrapper_element; + // cache index + task._index = i; - // CSS Selector is passed - if (typeof element === 'string') { - element = document.querySelector(element); - } - - // get the SVGElement - if (element instanceof HTMLElement) { - wrapper_element = element; - svg_element = element.querySelector('svg'); - } else if (element instanceof SVGElement) { - svg_element = element; - } else { - throw new TypeError( - 'Frappé Gantt only supports usage of a string CSS selector,' + - " HTML DOM element or SVG DOM element for the 'element' parameter" - ); - } - - // svg element - if (!svg_element) { - // create it - this.$svg = createSVG('svg', { - append_to: wrapper_element, - class: 'gantt', - }); - } else { - this.$svg = svg_element; - this.$svg.classList.add('gantt'); - } - - // wrapper element - this.$container = document.createElement('div'); - this.$container.classList.add('gantt-container'); - - const parent_element = this.$svg.parentElement; - parent_element.appendChild(this.$container); - this.$container.appendChild(this.$svg); - - // popup wrapper - this.popup_wrapper = document.createElement('div'); - this.popup_wrapper.classList.add('popup-wrapper'); - this.$container.appendChild(this.popup_wrapper); + // invalid dates + if (!task.start && !task.end) { + const today = date_utils.today(); + task._start = today; + task._end = date_utils.add(today, 2, "day"); } - setup_options(options) { - const default_options = { - header_height: 50, - column_width: 30, - step: 24, - view_modes: [...Object.values(VIEW_MODE)], - bar_height: 20, - bar_corner_radius: 3, - arrow_curve: 5, - padding: 18, - view_mode: 'Day', - date_format: 'YYYY-MM-DD', - popup_trigger: 'click', - custom_popup_html: null, - language: 'en', - }; - this.options = Object.assign({}, default_options, options); + if (!task.start && task.end) { + task._start = date_utils.add(task._end, -2, "day"); } - setup_tasks(tasks) { - // prepare tasks - this.tasks = tasks.map((task, i) => { - // convert to Date objects - task._start = date_utils.parse(task.start); - task._end = date_utils.parse(task.end); - - // make task invalid if duration too large - if (date_utils.diff(task._end, task._start, 'year') > 10) { - task.end = null; - } - - // cache index - task._index = i; - - // invalid dates - if (!task.start && !task.end) { - const today = date_utils.today(); - task._start = today; - task._end = date_utils.add(today, 2, 'day'); - } - - if (!task.start && task.end) { - task._start = date_utils.add(task._end, -2, 'day'); - } - - if (task.start && !task.end) { - task._end = date_utils.add(task._start, 2, 'day'); - } - - // if hours is not set, assume the last day is full day - // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 - const task_end_values = date_utils.get_date_values(task._end); - if (task_end_values.slice(3).every((d) => d === 0)) { - task._end = date_utils.add(task._end, 24, 'hour'); - } - - // invalid flag - if (!task.start || !task.end) { - task.invalid = true; - } - - // dependencies - if (typeof task.dependencies === 'string' || !task.dependencies) { - let deps = []; - if (task.dependencies) { - deps = task.dependencies - .split(',') - .map((d) => d.trim()) - .filter((d) => d); - } - task.dependencies = deps; - } - - // uids - if (!task.id) { - task.id = generate_id(task); - } - - return task; - }); - - this.setup_dependencies(); + if (task.start && !task.end) { + task._end = date_utils.add(task._start, 2, "day"); } - setup_dependencies() { - this.dependency_map = {}; - for (let t of this.tasks) { - for (let d of t.dependencies) { - this.dependency_map[d] = this.dependency_map[d] || []; - this.dependency_map[d].push(t.id); - } - } + // if hours is not set, assume the last day is full day + // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 + const task_end_values = date_utils.get_date_values(task._end); + if (task_end_values.slice(3).every((d) => d === 0)) { + task._end = date_utils.add(task._end, 24, "hour"); } - refresh(tasks) { - this.setup_tasks(tasks); - this.change_view_mode(); + // invalid flag + if (!task.start || !task.end) { + task.invalid = true; } - change_view_mode(mode = this.options.view_mode) { - this.update_view_scale(mode); - this.setup_dates(); - this.render(); - // fire viewmode_change event - this.trigger_event('view_change', [mode]); + // dependencies + if (typeof task.dependencies === "string" || !task.dependencies) { + let deps = []; + if (task.dependencies) { + deps = task.dependencies + .split(",") + .map((d) => d.trim()) + .filter((d) => d); + } + task.dependencies = deps; } - update_view_scale(view_mode) { - this.options.view_mode = view_mode; - - if (view_mode === VIEW_MODE.DAY) { - this.options.step = 24; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.HALF_DAY) { - this.options.step = 24 / 2; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.QUARTER_DAY) { - this.options.step = 24 / 4; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.WEEK) { - this.options.step = 24 * 7; - this.options.column_width = 140; - } else if (view_mode === VIEW_MODE.MONTH) { - this.options.step = 24 * 30; - this.options.column_width = 120; - } else if (view_mode === VIEW_MODE.YEAR) { - this.options.step = 24 * 365; - this.options.column_width = 120; - } + // uids + if (!task.id) { + task.id = generate_id(task); } - setup_dates() { - this.setup_gantt_dates(); - this.setup_date_values(); + return task; + }); + + this.setup_dependencies(); + } + + setup_dependencies() { + this.dependency_map = {}; + for (let t of this.tasks) { + for (let d of t.dependencies) { + this.dependency_map[d] = this.dependency_map[d] || []; + this.dependency_map[d].push(t.id); + } + } + } + + refresh(tasks) { + this.setup_tasks(tasks); + this.change_view_mode(); + } + + change_view_mode(mode = this.options.view_mode) { + this.update_view_scale(mode); + this.setup_dates(); + this.render(); + // fire viewmode_change event + this.trigger_event("view_change", [mode]); + } + + update_view_scale(view_mode) { + this.options.view_mode = view_mode; + if (view_mode === VIEW_MODE.HOUR) { + this.options.step = 24 / 24; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.DAY) { + this.options.step = 24; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.HALF_DAY) { + this.options.step = 24 / 2; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.QUARTER_DAY) { + this.options.step = 24 / 4; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.WEEK) { + this.options.step = 24 * 7; + this.options.column_width = 140; + } else if (view_mode === VIEW_MODE.MONTH) { + this.options.step = 24 * 30; + this.options.column_width = 120; + } else if (view_mode === VIEW_MODE.YEAR) { + this.options.step = 24 * 365; + this.options.column_width = 120; + } + } + + setup_dates() { + this.setup_gantt_dates(); + this.setup_date_values(); + } + + setup_gantt_dates() { + this.gantt_start = this.gantt_end = null; + + for (let task of this.tasks) { + // set global start and end date + if (!this.gantt_start || task._start < this.gantt_start) { + this.gantt_start = task._start; + } + if (!this.gantt_end || task._end > this.gantt_end) { + this.gantt_end = task._end; + } + } + + let gantt_start = date_utils.start_of(this.gantt_start, "day"); + let gantt_end = date_utils.start_of(this.gantt_end, "day"); + // add date padding on both sides + let viewKey; + for (let [key, value] of Object.entries(VIEW_MODE)) { + if (value === this.options.view_mode) { + viewKey = key; + } + } + const [padding_start, padding_end] = this.options.view_mode_padding[ + viewKey + ].map(date_utils.parse_duration); + this.gantt_start = date_utils.add( + gantt_start, + -padding_start.duration, + padding_start.scale, + ); + this.gantt_end = date_utils.add( + gantt_end, + padding_end.duration, + padding_end.scale, + ); + } + + setup_date_values() { + this.dates = []; + let cur_date = null; + + while (cur_date === null || cur_date < this.gantt_end) { + if (!cur_date) { + cur_date = date_utils.clone(this.gantt_start); + } else { + if (this.view_is(VIEW_MODE.YEAR)) { + cur_date = date_utils.add(cur_date, 1, "year"); + } else if (this.view_is(VIEW_MODE.MONTH)) { + cur_date = date_utils.add(cur_date, 1, "month"); + } else { + cur_date = date_utils.add(cur_date, this.options.step, "hour"); + } + } + this.dates.push(cur_date); + } + } + + bind_events() { + this.bind_grid_click(); + this.bind_bar_events(); + } + + render() { + this.clear(); + this.setup_layers(); + this.make_grid(); + this.make_dates(); + this.make_bars(); + this.make_arrows(); + this.map_arrows_on_bars(); + this.set_width(); + this.set_scroll_position(); + } + + setup_layers() { + this.layers = {}; + const layers = ["grid", "date", "arrow", "progress", "bar", "details"]; + // make group layers + for (let layer of layers) { + this.layers[layer] = createSVG("g", { + class: layer, + append_to: this.$svg, + }); + } + } + + make_grid() { + this.make_grid_background(); + this.make_grid_rows(); + this.make_grid_header(); + this.make_grid_ticks(); + this.make_grid_highlights(); + } + + make_grid_background() { + const grid_width = this.dates.length * this.options.column_width; + const grid_height = + this.options.header_height + + this.options.padding + + (this.options.bar_height + this.options.padding) * this.tasks.length; + + createSVG("rect", { + x: 0, + y: 0, + width: grid_width, + height: grid_height, + class: "grid-background", + append_to: this.layers.grid, + }); + + $.attr(this.$svg, { + height: grid_height + this.options.padding + 100, + width: "100%", + }); + } + + make_grid_rows() { + const rows_layer = createSVG("g", { append_to: this.layers.grid }); + const lines_layer = createSVG("g", { append_to: this.layers.grid }); + + const row_width = this.dates.length * this.options.column_width; + const row_height = this.options.bar_height + this.options.padding; + + let row_y = this.options.header_height + this.options.padding / 2; + + for (let task of this.tasks) { + createSVG("rect", { + x: 0, + y: row_y, + width: row_width, + height: row_height, + class: "grid-row", + append_to: rows_layer, + }); + + createSVG("line", { + x1: 0, + y1: row_y + row_height, + x2: row_width, + y2: row_y + row_height, + class: "row-line", + append_to: lines_layer, + }); + + row_y += this.options.bar_height + this.options.padding; + } + } + + make_grid_header() { + const header_width = this.dates.length * this.options.column_width; + const header_height = this.options.header_height + 10; + createSVG("rect", { + x: 0, + y: 0, + width: header_width, + height: header_height, + class: "grid-header", + append_to: this.layers.grid, + }); + } + + make_grid_ticks() { + let tick_x = 0; + let tick_y = this.options.header_height + this.options.padding / 2; + let tick_height = + (this.options.bar_height + this.options.padding) * this.tasks.length; + + for (let date of this.dates) { + let tick_class = "tick"; + // thick tick for monday + if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) { + tick_class += " thick"; + } + // thick tick for first week + if ( + this.view_is(VIEW_MODE.WEEK) && + date.getDate() >= 1 && + date.getDate() < 8 + ) { + tick_class += " thick"; + } + // thick ticks for quarters + if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) { + tick_class += " thick"; } - setup_gantt_dates() { - this.gantt_start = this.gantt_end = null; + createSVG("path", { + d: `M ${tick_x} ${tick_y} v ${tick_height}`, + class: tick_class, + append_to: this.layers.grid, + }); - for (let task of this.tasks) { - // set global start and end date - if (!this.gantt_start || task._start < this.gantt_start) { - this.gantt_start = task._start; - } - if (!this.gantt_end || task._end > this.gantt_end) { - this.gantt_end = task._end; - } - } - - this.gantt_start = date_utils.start_of(this.gantt_start, 'day'); - this.gantt_end = date_utils.start_of(this.gantt_end, 'day'); - - // add date padding on both sides - if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) { - this.gantt_start = date_utils.add(this.gantt_start, -7, 'day'); - this.gantt_end = date_utils.add(this.gantt_end, 7, 'day'); - } else if (this.view_is(VIEW_MODE.MONTH)) { - this.gantt_start = date_utils.start_of(this.gantt_start, 'year'); - this.gantt_end = date_utils.add(this.gantt_end, 1, 'year'); - } else if (this.view_is(VIEW_MODE.YEAR)) { - this.gantt_start = date_utils.add(this.gantt_start, -2, 'year'); - this.gantt_end = date_utils.add(this.gantt_end, 2, 'year'); - } else { - this.gantt_start = date_utils.add(this.gantt_start, -1, 'month'); - this.gantt_end = date_utils.add(this.gantt_end, 1, 'month'); - } + if (this.view_is(VIEW_MODE.MONTH)) { + tick_x += + (date_utils.get_days_in_month(date) * this.options.column_width) / 30; + } else { + tick_x += this.options.column_width; } + } + } - setup_date_values() { - this.dates = []; - let cur_date = null; + //compute the horizontal x distance + computeGridHighlightDimensions(view_mode) { + let xDist = 0; - while (cur_date === null || cur_date < this.gantt_end) { - if (!cur_date) { - cur_date = date_utils.clone(this.gantt_start); - } else { - if (this.view_is(VIEW_MODE.YEAR)) { - cur_date = date_utils.add(cur_date, 1, 'year'); - } else if (this.view_is(VIEW_MODE.MONTH)) { - cur_date = date_utils.add(cur_date, 1, 'month'); - } else { - cur_date = date_utils.add( - cur_date, - this.options.step, - 'hour' - ); - } - } - this.dates.push(cur_date); - } + if (this.view_is(VIEW_MODE.DAY)) { + return ( + (date_utils.diff(date_utils.today(), this.gantt_start, "hour") / + this.options.step) * + this.options.column_width + ); + } + + for (let date of this.dates) { + const todayDate = new Date(); + const startDate = new Date(date); + const endDate = new Date(date); + switch (view_mode) { + case VIEW_MODE.WEEK: + endDate.setDate(date.getDate() + 7); + break; + case VIEW_MODE.MONTH: + endDate.setMonth(date.getMonth() + 1); + break; + case VIEW_MODE.YEAR: + endDate.setFullYear(date.getFullYear() + 1); + break; } - - bind_events() { - this.bind_grid_click(); - this.bind_bar_events(); + if (todayDate >= startDate && todayDate <= endDate) { + break; + } else { + xDist += this.options.column_width; } + } + return xDist; + } - render() { - this.clear(); - this.setup_layers(); - this.make_grid(); - this.make_dates(); - this.make_bars(); - this.make_arrows(); - this.map_arrows_on_bars(); - this.set_width(); - this.set_scroll_position(); + make_grid_highlights() { + // highlight today's | week's | month's | year's + if ( + this.view_is(VIEW_MODE.DAY) || + this.view_is(VIEW_MODE.WEEK) || + this.view_is(VIEW_MODE.MONTH) || + this.view_is(VIEW_MODE.YEAR) + ) { + const x = this.computeGridHighlightDimensions(this.options.view_mode); + const y = 0; + const width = this.options.column_width; + const height = + (this.options.bar_height + this.options.padding) * this.tasks.length + + this.options.header_height + + this.options.padding / 2; + + let className = ""; + switch (this.options.view_mode) { + case VIEW_MODE.DAY: + className = "today-highlight"; + break; + case VIEW_MODE.WEEK: + className = "week-highlight"; + break; + case VIEW_MODE.MONTH: + className = "month-highlight"; + break; + case VIEW_MODE.YEAR: + className = "year-highlight"; + break; } + createSVG("rect", { + x, + y, + width, + height, + class: className, + append_to: this.layers.grid, + }); + } + } - setup_layers() { - this.layers = {}; - const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details']; - // make group layers - for (let layer of layers) { - this.layers[layer] = createSVG('g', { - class: layer, - append_to: this.$svg, - }); - } + make_dates() { + for (let date of this.get_dates_to_draw()) { + createSVG("text", { + x: date.lower_x, + y: date.lower_y, + innerHTML: date.lower_text, + class: "lower-text", + append_to: this.layers.date, + }); + + if (date.upper_text) { + const $upper_text = createSVG("text", { + x: date.upper_x, + y: date.upper_y, + innerHTML: date.upper_text, + class: "upper-text", + append_to: this.layers.date, + }); + + // remove out-of-bound dates + if ($upper_text.getBBox().x2 > this.layers.grid.getBBox().width) { + $upper_text.remove(); + } } + } + } - make_grid() { - this.make_grid_background(); - this.make_grid_rows(); - this.make_grid_header(); - this.make_grid_ticks(); - this.make_grid_highlights(); - } + get_dates_to_draw() { + let last_date = null; + const dates = this.dates.map((date, i) => { + const d = this.get_date_info(date, last_date, i); + last_date = date; + return d; + }); + return dates; + } - make_grid_background() { - const grid_width = this.dates.length * this.options.column_width; - const grid_height = - this.options.header_height + - this.options.padding + - (this.options.bar_height + this.options.padding) * - this.tasks.length; + get_date_info(date, last_date, i) { + if (!last_date) { + last_date = date_utils.add(date, 1, "day"); + } + const date_text = { + Hour_lower: date_utils.format(date, "HH", this.options.language), + "Quarter Day_lower": date_utils.format(date, "HH", this.options.language), + "Half Day_lower": date_utils.format(date, "HH", this.options.language), + Day_lower: + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D", this.options.language) + : "", + Week_lower: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "D MMM", this.options.language) + : date_utils.format(date, "D", this.options.language), + Month_lower: date_utils.format(date, "MMMM", this.options.language), + Year_lower: date_utils.format(date, "YYYY", this.options.language), + Hour_upper: + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D MMMM", this.options.language) + : "", + "Quarter Day_upper": + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D MMM", this.options.language) + : "", + "Half Day_upper": + date.getDate() !== last_date.getDate() + ? date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "D MMM", this.options.language) + : date_utils.format(date, "D", this.options.language) + : "", + Day_upper: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "MMMM", this.options.language) + : "", + Week_upper: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "MMMM", this.options.language) + : "", + Month_upper: + date.getFullYear() !== last_date.getFullYear() + ? date_utils.format(date, "YYYY", this.options.language) + : "", + Year_upper: + date.getFullYear() !== last_date.getFullYear() + ? date_utils.format(date, "YYYY", this.options.language) + : "", + }; - createSVG('rect', { - x: 0, - y: 0, - width: grid_width, - height: grid_height, - class: 'grid-background', - append_to: this.layers.grid, - }); + const base_pos = { + x: i * this.options.column_width, + lower_y: this.options.header_height, + upper_y: this.options.header_height - 25, + }; - $.attr(this.$svg, { - height: grid_height + this.options.padding + 100, - width: '100%', - }); - } + const x_pos = { + Hour_lower: this.options.column_width / 2, + Hour_upper: this.options.column_width * 12, + "Quarter Day_lower": this.options.column_width / 2, + "Quarter Day_upper": this.options.column_width * 2, + "Half Day_lower": this.options.column_width / 2, + "Half Day_upper": this.options.column_width, + Day_lower: this.options.column_width / 2, + Day_upper: (this.options.column_width * 30) / 2, + Week_lower: 0, + Week_upper: (this.options.column_width * 4) / 2, + Month_lower: this.options.column_width / 2, + Month_upper: (this.options.column_width * 12) / 2, + Year_lower: this.options.column_width / 2, + Year_upper: (this.options.column_width * 30) / 2, + }; - make_grid_rows() { - const rows_layer = createSVG('g', { append_to: this.layers.grid }); - const lines_layer = createSVG('g', { append_to: this.layers.grid }); + return { + upper_text: date_text[`${this.options.view_mode}_upper`], + lower_text: date_text[`${this.options.view_mode}_lower`], + upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`], + upper_y: base_pos.upper_y, + lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`], + lower_y: base_pos.lower_y, + }; + } - const row_width = this.dates.length * this.options.column_width; - const row_height = this.options.bar_height + this.options.padding; + make_bars() { + this.bars = this.tasks.map((task) => { + const bar = new Bar(this, task); + this.layers.bar.appendChild(bar.group); + return bar; + }); + } - let row_y = this.options.header_height + this.options.padding / 2; - - for (let task of this.tasks) { - createSVG('rect', { - x: 0, - y: row_y, - width: row_width, - height: row_height, - class: 'grid-row', - append_to: rows_layer, - }); - - createSVG('line', { - x1: 0, - y1: row_y + row_height, - x2: row_width, - y2: row_y + row_height, - class: 'row-line', - append_to: lines_layer, - }); - - row_y += this.options.bar_height + this.options.padding; - } - } - - make_grid_header() { - const header_width = this.dates.length * this.options.column_width; - const header_height = this.options.header_height + 10; - createSVG('rect', { - x: 0, - y: 0, - width: header_width, - height: header_height, - class: 'grid-header', - append_to: this.layers.grid, - }); - } - - make_grid_ticks() { - let tick_x = 0; - let tick_y = this.options.header_height + this.options.padding / 2; - let tick_height = - (this.options.bar_height + this.options.padding) * - this.tasks.length; - - for (let date of this.dates) { - let tick_class = 'tick'; - // thick tick for monday - if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) { - tick_class += ' thick'; - } - // thick tick for first week - if ( - this.view_is(VIEW_MODE.WEEK) && - date.getDate() >= 1 && - date.getDate() < 8 - ) { - tick_class += ' thick'; - } - // thick ticks for quarters - if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) { - tick_class += ' thick'; - } - - createSVG('path', { - d: `M ${tick_x} ${tick_y} v ${tick_height}`, - class: tick_class, - append_to: this.layers.grid, - }); - - if (this.view_is(VIEW_MODE.MONTH)) { - tick_x += - (date_utils.get_days_in_month(date) * - this.options.column_width) / - 30; - } else { - tick_x += this.options.column_width; - } - } - } - - make_grid_highlights() { - // highlight today's date - if (this.view_is(VIEW_MODE.DAY)) { - const x = - (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') / - this.options.step) * - this.options.column_width; - const y = 0; - - const width = this.options.column_width; - const height = - (this.options.bar_height + this.options.padding) * - this.tasks.length + - this.options.header_height + - this.options.padding / 2; - - createSVG('rect', { - x, - y, - width, - height, - class: 'today-highlight', - append_to: this.layers.grid, - }); - } - } - - make_dates() { - for (let date of this.get_dates_to_draw()) { - createSVG('text', { - x: date.lower_x, - y: date.lower_y, - innerHTML: date.lower_text, - class: 'lower-text', - append_to: this.layers.date, - }); - - if (date.upper_text) { - const $upper_text = createSVG('text', { - x: date.upper_x, - y: date.upper_y, - innerHTML: date.upper_text, - class: 'upper-text', - append_to: this.layers.date, - }); - - // remove out-of-bound dates - if ( - $upper_text.getBBox().x2 > this.layers.grid.getBBox().width - ) { - $upper_text.remove(); - } - } - } - } - - get_dates_to_draw() { - let last_date = null; - const dates = this.dates.map((date, i) => { - const d = this.get_date_info(date, last_date, i); - last_date = date; - return d; - }); - return dates; - } - - get_date_info(date, last_date, i) { - if (!last_date) { - last_date = date_utils.add(date, 1, 'year'); - } - const date_text = { - 'Quarter Day_lower': date_utils.format( - date, - 'HH', - this.options.language - ), - 'Half Day_lower': date_utils.format( - date, - 'HH', - this.options.language - ), - Day_lower: - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D', this.options.language) - : '', - Week_lower: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'D MMM', this.options.language) - : date_utils.format(date, 'D', this.options.language), - Month_lower: date_utils.format(date, 'MMMM', this.options.language), - Year_lower: date_utils.format(date, 'YYYY', this.options.language), - 'Quarter Day_upper': - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D MMM', this.options.language) - : '', - 'Half Day_upper': - date.getDate() !== last_date.getDate() - ? date.getMonth() !== last_date.getMonth() - ? date_utils.format( - date, - 'D MMM', - this.options.language - ) - : date_utils.format(date, 'D', this.options.language) - : '', - Day_upper: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Week_upper: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Month_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - Year_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - }; - - const base_pos = { - x: i * this.options.column_width, - lower_y: this.options.header_height, - upper_y: this.options.header_height - 25, - }; - - const x_pos = { - 'Quarter Day_lower': (this.options.column_width * 4) / 2, - 'Quarter Day_upper': 0, - 'Half Day_lower': (this.options.column_width * 2) / 2, - 'Half Day_upper': 0, - Day_lower: this.options.column_width / 2, - Day_upper: (this.options.column_width * 30) / 2, - Week_lower: 0, - Week_upper: (this.options.column_width * 4) / 2, - Month_lower: this.options.column_width / 2, - Month_upper: (this.options.column_width * 12) / 2, - Year_lower: this.options.column_width / 2, - Year_upper: (this.options.column_width * 30) / 2, - }; - - return { - upper_text: date_text[`${this.options.view_mode}_upper`], - lower_text: date_text[`${this.options.view_mode}_lower`], - upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`], - upper_y: base_pos.upper_y, - lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`], - lower_y: base_pos.lower_y, - }; - } - - make_bars() { - this.bars = this.tasks.map((task) => { - const bar = new Bar(this, task); - this.layers.bar.appendChild(bar.group); - return bar; - }); - } - - make_arrows() { - this.arrows = []; - for (let task of this.tasks) { - let arrows = []; - arrows = task.dependencies - .map((task_id) => { - const dependency = this.get_task(task_id); - if (!dependency) return; - const arrow = new Arrow( - this, - this.bars[dependency._index], // from_task - this.bars[task._index] // to_task - ); - this.layers.arrow.appendChild(arrow.element); - return arrow; - }) - .filter(Boolean); // filter falsy values - this.arrows = this.arrows.concat(arrows); - } - } - - map_arrows_on_bars() { - for (let bar of this.bars) { - bar.arrows = this.arrows.filter((arrow) => { - return ( - arrow.from_task.task.id === bar.task.id || - arrow.to_task.task.id === bar.task.id - ); - }); - } - } - - set_width() { - const cur_width = this.$svg.getBoundingClientRect().width; - const actual_width = this.$svg - .querySelector('.grid .grid-row') - .getAttribute('width'); - if (cur_width < actual_width) { - this.$svg.setAttribute('width', actual_width); - } - } - - set_scroll_position() { - const parent_element = this.$svg.parentElement; - if (!parent_element) return; - - const hours_before_first_task = date_utils.diff( - this.get_oldest_starting_date(), - this.gantt_start, - 'hour' + make_arrows() { + this.arrows = []; + for (let task of this.tasks) { + let arrows = []; + arrows = task.dependencies + .map((task_id) => { + const dependency = this.get_task(task_id); + if (!dependency) return; + const arrow = new Arrow( + this, + this.bars[dependency._index], // from_task + this.bars[task._index], // to_task ); + this.layers.arrow.appendChild(arrow.element); + return arrow; + }) + .filter(Boolean); // filter falsy values + this.arrows = this.arrows.concat(arrows); + } + } - const scroll_pos = - (hours_before_first_task / this.options.step) * - this.options.column_width - - this.options.column_width; + map_arrows_on_bars() { + for (let bar of this.bars) { + bar.arrows = this.arrows.filter((arrow) => { + return ( + arrow.from_task.task.id === bar.task.id || + arrow.to_task.task.id === bar.task.id + ); + }); + } + } - parent_element.scrollLeft = scroll_pos; + set_width() { + const cur_width = this.$svg.getBoundingClientRect().width; + const actual_width = this.$svg + .querySelector(".grid .grid-row") + .getAttribute("width"); + if (cur_width < actual_width) { + this.$svg.setAttribute("width", actual_width); + } + } + + set_scroll_position() { + const parent_element = this.$svg.parentElement; + if (!parent_element) return; + + const hours_before_first_task = date_utils.diff( + this.get_oldest_starting_date(), + this.gantt_start, + "hour", + ); + + const scroll_pos = + (hours_before_first_task / this.options.step) * + this.options.column_width - + this.options.column_width; + + parent_element.scrollLeft = scroll_pos; + } + + bind_grid_click() { + $.on( + this.$svg, + this.options.popup_trigger, + ".grid-row, .grid-header", + () => { + this.unselect_all(); + this.hide_popup(); + }, + ); + } + + bind_bar_events() { + let is_dragging = false; + let x_on_start = 0; + let y_on_start = 0; + let is_resizing_left = false; + let is_resizing_right = false; + let parent_bar_id = null; + let bars = []; // instanceof Bar + this.bar_being_dragged = null; + + function action_in_progress() { + return is_dragging || is_resizing_left || is_resizing_right; + } + + $.on(this.$svg, "mousedown", ".bar-wrapper, .handle", (e, element) => { + const bar_wrapper = $.closest(".bar-wrapper", element); + + if (element.classList.contains("left")) { + is_resizing_left = true; + } else if (element.classList.contains("right")) { + is_resizing_right = true; + } else if (element.classList.contains("bar-wrapper")) { + is_dragging = true; } - bind_grid_click() { - $.on( - this.$svg, - this.options.popup_trigger, - '.grid-row, .grid-header', - () => { - this.unselect_all(); - this.hide_popup(); - } - ); - } + bar_wrapper.classList.add("active"); - bind_bar_events() { - let is_dragging = false; - let x_on_start = 0; - let y_on_start = 0; - let is_resizing_left = false; - let is_resizing_right = false; - let parent_bar_id = null; - let bars = []; // instanceof Bar - this.bar_being_dragged = null; + x_on_start = e.offsetX; + y_on_start = e.offsetY; - function action_in_progress() { - return is_dragging || is_resizing_left || is_resizing_right; - } + parent_bar_id = bar_wrapper.getAttribute("data-id"); + const ids = [ + parent_bar_id, + ...this.get_all_dependent_tasks(parent_bar_id), + ]; + bars = ids.map((id) => this.get_bar(id)); - $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => { - const bar_wrapper = $.closest('.bar-wrapper', element); + this.bar_being_dragged = parent_bar_id; - if (element.classList.contains('left')) { - is_resizing_left = true; - } else if (element.classList.contains('right')) { - is_resizing_right = true; - } else if (element.classList.contains('bar-wrapper')) { - is_dragging = true; - } + bars.forEach((bar) => { + const $bar = bar.$bar; + $bar.ox = $bar.getX(); + $bar.oy = $bar.getY(); + $bar.owidth = $bar.getWidth(); + $bar.finaldx = 0; + }); + }); - bar_wrapper.classList.add('active'); + $.on(this.$svg, "mousemove", (e) => { + if (!action_in_progress()) return; + const dx = e.offsetX - x_on_start; + e.offsetY - y_on_start; - x_on_start = e.offsetX; - y_on_start = e.offsetY; - - parent_bar_id = bar_wrapper.getAttribute('data-id'); - const ids = [ - parent_bar_id, - ...this.get_all_dependent_tasks(parent_bar_id), - ]; - bars = ids.map((id) => this.get_bar(id)); - - this.bar_being_dragged = parent_bar_id; - - bars.forEach((bar) => { - const $bar = bar.$bar; - $bar.ox = $bar.getX(); - $bar.oy = $bar.getY(); - $bar.owidth = $bar.getWidth(); - $bar.finaldx = 0; - }); - }); - - $.on(this.$svg, 'mousemove', (e) => { - if (!action_in_progress()) return; - const dx = e.offsetX - x_on_start; - e.offsetY - y_on_start; - - bars.forEach((bar) => { - const $bar = bar.$bar; - $bar.finaldx = this.get_snap_position(dx); - this.hide_popup(); - if (is_resizing_left) { - if (parent_bar_id === bar.task.id) { - bar.update_bar_position({ - x: $bar.ox + $bar.finaldx, - width: $bar.owidth - $bar.finaldx, - }); - } else { - bar.update_bar_position({ - x: $bar.ox + $bar.finaldx, - }); - } - } else if (is_resizing_right) { - if (parent_bar_id === bar.task.id) { - bar.update_bar_position({ - width: $bar.owidth + $bar.finaldx, - }); - } - } else if (is_dragging) { - bar.update_bar_position({ x: $bar.ox + $bar.finaldx }); - } - }); - }); - - document.addEventListener('mouseup', (e) => { - if (is_dragging || is_resizing_left || is_resizing_right) { - bars.forEach((bar) => bar.group.classList.remove('active')); - } - - is_dragging = false; - is_resizing_left = false; - is_resizing_right = false; - }); - - $.on(this.$svg, 'mouseup', (e) => { - this.bar_being_dragged = null; - bars.forEach((bar) => { - const $bar = bar.$bar; - if (!$bar.finaldx) return; - bar.date_changed(); - bar.set_action_completed(); - }); - }); - - this.bind_bar_progress(); - } - - bind_bar_progress() { - let x_on_start = 0; - let y_on_start = 0; - let is_resizing = null; - let bar = null; - let $bar_progress = null; - let $bar = null; - - $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => { - is_resizing = true; - x_on_start = e.offsetX; - y_on_start = e.offsetY; - - const $bar_wrapper = $.closest('.bar-wrapper', handle); - const id = $bar_wrapper.getAttribute('data-id'); - bar = this.get_bar(id); - - $bar_progress = bar.$bar_progress; - $bar = bar.$bar; - - $bar_progress.finaldx = 0; - $bar_progress.owidth = $bar_progress.getWidth(); - $bar_progress.min_dx = -$bar_progress.getWidth(); - $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth(); - }); - - $.on(this.$svg, 'mousemove', (e) => { - if (!is_resizing) return; - let dx = e.offsetX - x_on_start; - e.offsetY - y_on_start; - - if (dx > $bar_progress.max_dx) { - dx = $bar_progress.max_dx; - } - if (dx < $bar_progress.min_dx) { - dx = $bar_progress.min_dx; - } - - const $handle = bar.$handle_progress; - $.attr($bar_progress, 'width', $bar_progress.owidth + dx); - $.attr($handle, 'points', bar.get_progress_polygon_points()); - $bar_progress.finaldx = dx; - }); - - $.on(this.$svg, 'mouseup', () => { - is_resizing = false; - if (!($bar_progress && $bar_progress.finaldx)) return; - bar.progress_changed(); - bar.set_action_completed(); - }); - } - - get_all_dependent_tasks(task_id) { - let out = []; - let to_process = [task_id]; - while (to_process.length) { - const deps = to_process.reduce((acc, curr) => { - acc = acc.concat(this.dependency_map[curr]); - return acc; - }, []); - - out = out.concat(deps); - to_process = deps.filter((d) => !to_process.includes(d)); - } - - return out.filter(Boolean); - } - - get_snap_position(dx) { - let odx = dx, - rem, - position; - - if (this.view_is(VIEW_MODE.WEEK)) { - rem = dx % (this.options.column_width / 7); - position = - odx - - rem + - (rem < this.options.column_width / 14 - ? 0 - : this.options.column_width / 7); - } else if (this.view_is(VIEW_MODE.MONTH)) { - rem = dx % (this.options.column_width / 30); - position = - odx - - rem + - (rem < this.options.column_width / 60 - ? 0 - : this.options.column_width / 30); + bars.forEach((bar) => { + const $bar = bar.$bar; + $bar.finaldx = this.get_snap_position(dx); + this.hide_popup(); + if (is_resizing_left) { + if (parent_bar_id === bar.task.id) { + bar.update_bar_position({ + x: $bar.ox + $bar.finaldx, + width: $bar.owidth - $bar.finaldx, + }); } else { - rem = dx % this.options.column_width; - position = - odx - - rem + - (rem < this.options.column_width / 2 - ? 0 - : this.options.column_width); + bar.update_bar_position({ + x: $bar.ox + $bar.finaldx, + }); } - return position; - } - - unselect_all() { - [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => { - el.classList.remove('active'); - }); - } - - view_is(modes) { - if (typeof modes === 'string') { - return this.options.view_mode === modes; + } else if (is_resizing_right) { + if (parent_bar_id === bar.task.id) { + bar.update_bar_position({ + width: $bar.owidth + $bar.finaldx, + }); } + } else if (is_dragging) { + bar.update_bar_position({ x: $bar.ox + $bar.finaldx }); + } + }); + }); - if (Array.isArray(modes)) { - return modes.some((mode) => this.options.view_mode === mode); - } - - return false; + document.addEventListener("mouseup", (e) => { + if (is_dragging || is_resizing_left || is_resizing_right) { + bars.forEach((bar) => bar.group.classList.remove("active")); } - get_task(id) { - return this.tasks.find((task) => { - return task.id === id; - }); - } + is_dragging = false; + is_resizing_left = false; + is_resizing_right = false; + }); - get_bar(id) { - return this.bars.find((bar) => { - return bar.task.id === id; - }); - } + $.on(this.$svg, "mouseup", (e) => { + this.bar_being_dragged = null; + bars.forEach((bar) => { + const $bar = bar.$bar; + if (!$bar.finaldx) return; + bar.date_changed(); + bar.set_action_completed(); + }); + }); - show_popup(options) { - if (!this.popup) { - this.popup = new Popup( - this.popup_wrapper, - this.options.custom_popup_html - ); - } - this.popup.show(options); - } - - hide_popup() { - this.popup && this.popup.hide(); - } - - trigger_event(event, args) { - if (this.options['on_' + event]) { - this.options['on_' + event].apply(null, args); - } - } - - /** - * Gets the oldest starting date from the list of tasks - * - * @returns Date - * @memberof Gantt - */ - get_oldest_starting_date() { - return this.tasks - .map((task) => task._start) - .reduce((prev_date, cur_date) => - cur_date <= prev_date ? cur_date : prev_date - ); - } - - /** - * Clear all elements from the parent svg element - * - * @memberof Gantt - */ - clear() { - this.$svg.innerHTML = ''; - } + this.bind_bar_progress(); } - Gantt.VIEW_MODE = VIEW_MODE; + bind_bar_progress() { + let x_on_start = 0; + let y_on_start = 0; + let is_resizing = null; + let bar = null; + let $bar_progress = null; + let $bar = null; - function generate_id(task) { - return task.name + '_' + Math.random().toString(36).slice(2, 12); + $.on(this.$svg, "mousedown", ".handle.progress", (e, handle) => { + is_resizing = true; + x_on_start = e.offsetX; + y_on_start = e.offsetY; + + const $bar_wrapper = $.closest(".bar-wrapper", handle); + const id = $bar_wrapper.getAttribute("data-id"); + bar = this.get_bar(id); + + $bar_progress = bar.$bar_progress; + $bar = bar.$bar; + + $bar_progress.finaldx = 0; + $bar_progress.owidth = $bar_progress.getWidth(); + $bar_progress.min_dx = -$bar_progress.getWidth(); + $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth(); + }); + + $.on(this.$svg, "mousemove", (e) => { + if (!is_resizing) return; + let dx = e.offsetX - x_on_start; + e.offsetY - y_on_start; + + if (dx > $bar_progress.max_dx) { + dx = $bar_progress.max_dx; + } + if (dx < $bar_progress.min_dx) { + dx = $bar_progress.min_dx; + } + + const $handle = bar.$handle_progress; + $.attr($bar_progress, "width", $bar_progress.owidth + dx); + $.attr($handle, "points", bar.get_progress_polygon_points()); + $bar_progress.finaldx = dx; + }); + + $.on(this.$svg, "mouseup", () => { + is_resizing = false; + if (!($bar_progress && $bar_progress.finaldx)) return; + bar.progress_changed(); + bar.set_action_completed(); + }); } - return Gantt; + get_all_dependent_tasks(task_id) { + let out = []; + let to_process = [task_id]; + while (to_process.length) { + const deps = to_process.reduce((acc, curr) => { + acc = acc.concat(this.dependency_map[curr]); + return acc; + }, []); + + out = out.concat(deps); + to_process = deps.filter((d) => !to_process.includes(d)); + } + + return out.filter(Boolean); + } + + get_snap_position(dx) { + let odx = dx, + rem, + position; + + if (this.view_is(VIEW_MODE.WEEK)) { + rem = dx % (this.options.column_width / 7); + position = + odx - + rem + + (rem < this.options.column_width / 14 + ? 0 + : this.options.column_width / 7); + } else if (this.view_is(VIEW_MODE.MONTH)) { + rem = dx % (this.options.column_width / 30); + position = + odx - + rem + + (rem < this.options.column_width / 60 + ? 0 + : this.options.column_width / 30); + } else { + rem = dx % this.options.column_width; + position = + odx - + rem + + (rem < this.options.column_width / 2 ? 0 : this.options.column_width); + } + return position; + } + + unselect_all() { + [...this.$svg.querySelectorAll(".bar-wrapper")].forEach((el) => { + el.classList.remove("active"); + }); + } + + view_is(modes) { + if (typeof modes === "string") { + return this.options.view_mode === modes; + } + + if (Array.isArray(modes)) { + return modes.some((mode) => this.options.view_mode === mode); + } + + return false; + } + + get_task(id) { + return this.tasks.find((task) => { + return task.id === id; + }); + } + + get_bar(id) { + return this.bars.find((bar) => { + return bar.task.id === id; + }); + } + + show_popup(options) { + if (!this.popup) { + this.popup = new Popup( + this.popup_wrapper, + this.options.custom_popup_html, + ); + } + this.popup.show(options); + } + + hide_popup() { + this.popup && this.popup.hide(); + } + + trigger_event(event, args) { + if (this.options["on_" + event]) { + this.options["on_" + event].apply(null, args); + } + } + + /** + * Gets the oldest starting date from the list of tasks + * + * @returns Date + * @memberof Gantt + */ + get_oldest_starting_date() { + return this.tasks + .map((task) => task._start) + .reduce((prev_date, cur_date) => + cur_date <= prev_date ? cur_date : prev_date, + ); + } + + /** + * Clear all elements from the parent svg element + * + * @memberof Gantt + */ + clear() { + this.$svg.innerHTML = ""; + } + } + + Gantt.VIEW_MODE = VIEW_MODE; + + function generate_id(task) { + return task.name + "_" + Math.random().toString(36).slice(2, 12); + } + + return Gantt; })(); //# sourceMappingURL=frappe-gantt.js.map diff --git a/dist/frappe-gantt.js.map b/dist/frappe-gantt.js.map index cced8dc..c3d521d 100644 --- a/dist/frappe-gantt.js.map +++ b/dist/frappe-gantt.js.map @@ -1 +1 @@ -{"version":3,"file":"frappe-gantt.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = 'year';\nconst MONTH = 'month';\nconst DAY = 'day';\nconst HOUR = 'hour';\nconst MINUTE = 'minute';\nconst SECOND = 'second';\nconst MILLISECOND = 'millisecond';\n\nexport default {\n parse(date, date_separator = '-', time_separator = /[.:]/) {\n if (date instanceof Date) {\n return date;\n }\n if (typeof date === 'string') {\n let date_parts, time_parts;\n const parts = date.split(' ');\n\n date_parts = parts[0]\n .split(date_separator)\n .map((val) => parseInt(val, 10));\n time_parts = parts[1] && parts[1].split(time_separator);\n\n // month is 0 indexed\n date_parts[1] = date_parts[1] - 1;\n\n let vals = date_parts;\n\n if (time_parts && time_parts.length) {\n if (time_parts.length == 4) {\n time_parts[3] = '0.' + time_parts[3];\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\n }\n vals = vals.concat(time_parts);\n }\n\n return new Date(...vals);\n }\n },\n\n to_string(date, with_time = false) {\n if (!(date instanceof Date)) {\n throw new TypeError('Invalid argument type');\n }\n const vals = this.get_date_values(date).map((val, i) => {\n if (i === 1) {\n // add 1 for month\n val = val + 1;\n }\n\n if (i === 6) {\n return padStart(val + '', 3, '0');\n }\n\n return padStart(val + '', 2, '0');\n });\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\n\n return date_string + (with_time ? ' ' + time_string : '');\n },\n\n format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') {\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\n month: 'long'\n });\n const month_name = dateTimeFormat.format(date);\n const month_name_capitalized =\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\n\n const values = this.get_date_values(date).map(d => padStart(d, 2, 0));\n const format_map = {\n YYYY: values[0],\n MM: padStart(+values[1] + 1, 2, 0),\n DD: values[2],\n HH: values[3],\n mm: values[4],\n ss: values[5],\n SSS: values[6],\n D: values[2],\n MMMM: month_name_capitalized,\n MMM: month_name_capitalized,\n };\n\n let str = format_string;\n const formatted_values = [];\n\n Object.keys(format_map)\n .sort((a, b) => b.length - a.length) // big string first\n .forEach((key) => {\n if (str.includes(key)) {\n str = str.replace(key, `$${formatted_values.length}`);\n formatted_values.push(format_map[key]);\n }\n });\n\n formatted_values.forEach((value, i) => {\n str = str.replace(`$${i}`, value);\n });\n\n return str;\n },\n\n diff(date_a, date_b, scale = DAY) {\n let milliseconds, seconds, hours, minutes, days, months, years;\n\n milliseconds = date_a - date_b;\n seconds = milliseconds / 1000;\n minutes = seconds / 60;\n hours = minutes / 60;\n days = hours / 24;\n months = days / 30;\n years = months / 12;\n\n if (!scale.endsWith('s')) {\n scale += 's';\n }\n\n return Math.floor(\n {\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n months,\n years,\n }[scale]\n );\n },\n\n today() {\n const vals = this.get_date_values(new Date()).slice(0, 3);\n return new Date(...vals);\n },\n\n now() {\n return new Date();\n },\n\n add(date, qty, scale) {\n qty = parseInt(qty, 10);\n const vals = [\n date.getFullYear() + (scale === YEAR ? qty : 0),\n date.getMonth() + (scale === MONTH ? qty : 0),\n date.getDate() + (scale === DAY ? qty : 0),\n date.getHours() + (scale === HOUR ? qty : 0),\n date.getMinutes() + (scale === MINUTE ? qty : 0),\n date.getSeconds() + (scale === SECOND ? qty : 0),\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\n ];\n return new Date(...vals);\n },\n\n start_of(date, scale) {\n const scores = {\n [YEAR]: 6,\n [MONTH]: 5,\n [DAY]: 4,\n [HOUR]: 3,\n [MINUTE]: 2,\n [SECOND]: 1,\n [MILLISECOND]: 0,\n };\n\n function should_reset(_scale) {\n const max_score = scores[scale];\n return scores[_scale] <= max_score;\n }\n\n const vals = [\n date.getFullYear(),\n should_reset(YEAR) ? 0 : date.getMonth(),\n should_reset(MONTH) ? 1 : date.getDate(),\n should_reset(DAY) ? 0 : date.getHours(),\n should_reset(HOUR) ? 0 : date.getMinutes(),\n should_reset(MINUTE) ? 0 : date.getSeconds(),\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\n ];\n\n return new Date(...vals);\n },\n\n clone(date) {\n return new Date(...this.get_date_values(date));\n },\n\n get_date_values(date) {\n return [\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n ];\n },\n\n get_days_in_month(date) {\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n const month = date.getMonth();\n\n if (month !== 1) {\n return no_of_days[month];\n }\n\n // Feb\n const year = date.getFullYear();\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\n return 29;\n }\n return 28;\n },\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\nfunction padStart(str, targetLength, padString) {\n str = str + '';\n targetLength = targetLength >> 0;\n padString = String(typeof padString !== 'undefined' ? padString : ' ');\n if (str.length > targetLength) {\n return String(str);\n } else {\n targetLength = targetLength - str.length;\n if (targetLength > padString.length) {\n padString += padString.repeat(targetLength / padString.length);\n }\n return padString.slice(0, targetLength) + String(str);\n }\n}\n","export function $(expr, con) {\n return typeof expr === 'string'\n ? (con || document).querySelector(expr)\n : expr || null;\n}\n\nexport function createSVG(tag, attrs) {\n const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);\n for (let attr in attrs) {\n if (attr === 'append_to') {\n const parent = attrs.append_to;\n parent.appendChild(elem);\n } else if (attr === 'innerHTML') {\n elem.innerHTML = attrs.innerHTML;\n } else {\n elem.setAttribute(attr, attrs[attr]);\n }\n }\n return elem;\n}\n\nexport function animateSVG(svgElement, attr, from, to) {\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\n\n if (animatedSvgElement === svgElement) {\n // triggered 2nd time programmatically\n // trigger artificial click event\n const event = document.createEvent('HTMLEvents');\n event.initEvent('click', true, true);\n event.eventName = 'click';\n animatedSvgElement.dispatchEvent(event);\n }\n}\n\nfunction getAnimationElement(\n svgElement,\n attr,\n from,\n to,\n dur = '0.4s',\n begin = '0.1s'\n) {\n const animEl = svgElement.querySelector('animate');\n if (animEl) {\n $.attr(animEl, {\n attributeName: attr,\n from,\n to,\n dur,\n begin: 'click + ' + begin, // artificial click\n });\n return svgElement;\n }\n\n const animateElement = createSVG('animate', {\n attributeName: attr,\n from,\n to,\n dur,\n begin,\n calcMode: 'spline',\n values: from + ';' + to,\n keyTimes: '0; 1',\n keySplines: cubic_bezier('ease-out'),\n });\n svgElement.appendChild(animateElement);\n\n return svgElement;\n}\n\nfunction cubic_bezier(name) {\n return {\n ease: '.25 .1 .25 1',\n linear: '0 0 1 1',\n 'ease-in': '.42 0 1 1',\n 'ease-out': '0 0 .58 1',\n 'ease-in-out': '.42 0 .58 1',\n }[name];\n}\n\n$.on = (element, event, selector, callback) => {\n if (!callback) {\n callback = selector;\n $.bind(element, event, callback);\n } else {\n $.delegate(element, event, selector, callback);\n }\n};\n\n$.off = (element, event, handler) => {\n element.removeEventListener(event, handler);\n};\n\n$.bind = (element, event, callback) => {\n event.split(/\\s+/).forEach(function (event) {\n element.addEventListener(event, callback);\n });\n};\n\n$.delegate = (element, event, selector, callback) => {\n element.addEventListener(event, function (e) {\n const delegatedTarget = e.target.closest(selector);\n if (delegatedTarget) {\n e.delegatedTarget = delegatedTarget;\n callback.call(this, e, delegatedTarget);\n }\n });\n};\n\n$.closest = (selector, element) => {\n if (!element) return null;\n\n if (element.matches(selector)) {\n return element;\n }\n\n return $.closest(selector, element.parentNode);\n};\n\n$.attr = (element, attr, value) => {\n if (!value && typeof attr === 'string') {\n return element.getAttribute(attr);\n }\n\n if (typeof attr === 'object') {\n for (let key in attr) {\n $.attr(element, key, attr[key]);\n }\n return;\n }\n\n element.setAttribute(attr, value);\n};\n","import date_utils from './date_utils';\nimport { $, createSVG, animateSVG } from './svg_utils';\n\nexport default class Bar {\n constructor(gantt, task) {\n this.set_defaults(gantt, task);\n this.prepare();\n this.draw();\n this.bind();\n }\n\n set_defaults(gantt, task) {\n this.action_completed = false;\n this.gantt = gantt;\n this.task = task;\n }\n\n prepare() {\n this.prepare_values();\n this.prepare_helpers();\n }\n\n prepare_values() {\n this.invalid = this.task.invalid;\n this.height = this.gantt.options.bar_height;\n this.compute_x();\n this.compute_y();\n this.compute_duration();\n this.corner_radius = this.gantt.options.bar_corner_radius;\n this.width = this.gantt.options.column_width * this.duration;\n this.progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.task.progress / 100) || 0;\n this.group = createSVG('g', {\n class: 'bar-wrapper ' + (this.task.custom_class || ''),\n 'data-id': this.task.id,\n });\n this.bar_group = createSVG('g', {\n class: 'bar-group',\n append_to: this.group,\n });\n this.handle_group = createSVG('g', {\n class: 'handle-group',\n append_to: this.group,\n });\n }\n\n prepare_helpers() {\n SVGElement.prototype.getX = function () {\n return +this.getAttribute('x');\n };\n SVGElement.prototype.getY = function () {\n return +this.getAttribute('y');\n };\n SVGElement.prototype.getWidth = function () {\n return +this.getAttribute('width');\n };\n SVGElement.prototype.getHeight = function () {\n return +this.getAttribute('height');\n };\n SVGElement.prototype.getEndX = function () {\n return this.getX() + this.getWidth();\n };\n }\n\n prepare_expected_progress_values() {\n this.compute_expected_progress();\n this.expected_progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0;\n }\n\n draw() {\n this.draw_bar();\n if (this.gantt.options.show_expected_progress) {\n this.prepare_expected_progress_values();\n this.draw_expected_progress_bar();\n }\n this.draw_progress_bar();\n this.draw_label();\n this.draw_resize_handles();\n }\n\n draw_bar() {\n this.$bar = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar, 'width', 0, this.width);\n\n if (this.invalid) {\n this.$bar.classList.add('bar-invalid');\n }\n }\n\n draw_expected_progress_bar() {\n if (this.invalid) return;\n this.$expected_bar_progress = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.expected_progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar-expected-progress',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$expected_bar_progress, 'width', 0, this.expected_progress_width);\n }\n\n draw_progress_bar() {\n if (this.invalid) return;\n this.$bar_progress = createSVG('rect', {\n x: this.x,\n y: this.y,\n width: this.progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'bar-progress',\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar_progress, 'width', 0, this.progress_width);\n }\n\n draw_label() {\n createSVG('text', {\n x: this.x + this.width / 2,\n y: this.y + this.height / 2,\n innerHTML: this.task.name,\n class: 'bar-label',\n append_to: this.bar_group,\n });\n // labels get BBox in the next tick\n requestAnimationFrame(() => this.update_label_position());\n }\n\n draw_resize_handles() {\n if (this.invalid) return;\n\n const bar = this.$bar;\n const handle_width = 8;\n\n createSVG('rect', {\n x: bar.getX() + bar.getWidth() - 9,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'handle right',\n append_to: this.handle_group,\n });\n\n createSVG('rect', {\n x: bar.getX() + 1,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: 'handle left',\n append_to: this.handle_group,\n });\n\n if (this.task.progress && this.task.progress < 100) {\n this.$handle_progress = createSVG('polygon', {\n points: this.get_progress_polygon_points().join(','),\n class: 'handle progress',\n append_to: this.handle_group,\n });\n }\n }\n\n get_progress_polygon_points() {\n const bar_progress = this.$bar_progress;\n return [\n bar_progress.getEndX() - 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX() + 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX(),\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\n ];\n }\n\n bind() {\n if (this.invalid) return;\n this.setup_click_event();\n }\n\n setup_click_event() {\n $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.show_popup();\n this.gantt.unselect_all();\n this.group.classList.add('active');\n });\n\n $.on(this.group, 'dblclick', (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.gantt.trigger_event('click', [this.task]);\n });\n }\n\n show_popup() {\n if (this.gantt.bar_being_dragged) return;\n\n const start_date = date_utils.format(\n this.task._start,\n 'MMM D',\n this.gantt.options.language\n );\n const end_date = date_utils.format(\n date_utils.add(this.task._end, -1, 'second'),\n 'MMM D',\n this.gantt.options.language\n );\n const subtitle = start_date + ' - ' + end_date;\n\n this.gantt.show_popup({\n target_element: this.$bar,\n title: this.task.name,\n subtitle: subtitle,\n task: this.task,\n });\n }\n\n update_bar_position({ x = null, width = null }) {\n const bar = this.$bar;\n if (x) {\n // get all x values of parent task\n const xs = this.task.dependencies.map((dep) => {\n return this.gantt.get_bar(dep).$bar.getX();\n });\n // child task must not go before parent\n const valid_x = xs.reduce((prev, curr) => {\n return x >= curr;\n }, x);\n if (!valid_x) {\n width = null;\n return;\n }\n this.update_attr(bar, 'x', x);\n }\n if (width && width >= this.gantt.options.column_width) {\n this.update_attr(bar, 'width', width);\n }\n this.update_label_position();\n this.update_handle_position();\n if (this.gantt.options.show_expected_progress){\n this.date_changed();\n this.compute_duration();\n this.update_expected_progressbar_position();\n }\n this.update_progressbar_position();\n this.update_arrow_position();\n }\n\n date_changed() {\n let changed = false;\n const { new_start_date, new_end_date } = this.compute_start_end_date();\n\n if (Number(this.task._start) !== Number(new_start_date)) {\n changed = true;\n this.task._start = new_start_date;\n }\n\n if (Number(this.task._end) !== Number(new_end_date)) {\n changed = true;\n this.task._end = new_end_date;\n }\n\n if (!changed) return;\n\n this.gantt.trigger_event('date_change', [\n this.task,\n new_start_date,\n date_utils.add(new_end_date, -1, 'second'),\n ]);\n }\n\n progress_changed() {\n const new_progress = this.compute_progress();\n this.task.progress = new_progress;\n this.gantt.trigger_event('progress_change', [this.task, new_progress]);\n }\n\n set_action_completed() {\n this.action_completed = true;\n setTimeout(() => (this.action_completed = false), 1000);\n }\n\n compute_start_end_date() {\n const bar = this.$bar;\n const x_in_units = bar.getX() / this.gantt.options.column_width;\n const new_start_date = date_utils.add(\n this.gantt.gantt_start,\n x_in_units * this.gantt.options.step,\n 'hour'\n );\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\n const new_end_date = date_utils.add(\n new_start_date,\n width_in_units * this.gantt.options.step,\n 'hour'\n );\n\n return { new_start_date, new_end_date };\n }\n\n compute_progress() {\n const progress =\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\n return parseInt(progress, 10);\n }\n\n compute_expected_progress() {\n this.expected_progress = date_utils.diff(date_utils.today(), this.task._start, 'hour') / this.gantt.options.step;\n this.expected_progress = ((this.expected_progress < this.duration) ? this.expected_progress : this.duration) * 100 / this.duration;\n }\n\n compute_x() {\n const { step, column_width } = this.gantt.options;\n const task_start = this.task._start;\n const gantt_start = this.gantt.gantt_start;\n\n const diff = date_utils.diff(task_start, gantt_start, 'hour');\n let x = (diff / step) * column_width;\n\n if (this.gantt.view_is('Month')) {\n const diff = date_utils.diff(task_start, gantt_start, 'day');\n x = (diff * column_width) / 30;\n }\n this.x = x;\n }\n\n compute_y() {\n this.y = (\n this.gantt.options.header_height +\n this.gantt.options.padding +\n this.task._index * (this.height + this.gantt.options.padding)\n );\n }\n\n compute_duration() {\n this.duration = date_utils.diff(this.task._end, this.task._start, 'hour') /\n this.gantt.options.step;\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.gantt.view_is('Week')) {\n rem = dx % (this.gantt.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 14\n ? 0\n : this.gantt.options.column_width / 7);\n } else if (this.gantt.view_is('Month')) {\n rem = dx % (this.gantt.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 60\n ? 0\n : this.gantt.options.column_width / 30);\n } else {\n rem = dx % this.gantt.options.column_width;\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 2\n ? 0\n : this.gantt.options.column_width);\n }\n return position;\n }\n\n update_attr(element, attr, value) {\n value = +value;\n if (!isNaN(value)) {\n element.setAttribute(attr, value);\n }\n return element;\n }\n\n update_expected_progressbar_position() {\n if (this.invalid) return;\n this.$expected_bar_progress.setAttribute('x', this.$bar.getX());\n this.compute_expected_progress();\n this.$expected_bar_progress.setAttribute(\n 'width',\n this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0\n );\n }\n\n update_progressbar_position() {\n if (this.invalid) return;\n this.$bar_progress.setAttribute('x', this.$bar.getX());\n this.$bar_progress.setAttribute(\n 'width',\n this.$bar.getWidth() * (this.task.progress / 100)\n );\n }\n\n update_label_position() {\n const bar = this.$bar,\n label = this.group.querySelector('.bar-label');\n\n if (label.getBBox().width > bar.getWidth()) {\n label.classList.add('big');\n label.setAttribute('x', bar.getX() + bar.getWidth() + 5);\n } else {\n label.classList.remove('big');\n label.setAttribute('x', bar.getX() + bar.getWidth() / 2);\n }\n }\n\n update_handle_position() {\n if (this.invalid) return;\n const bar = this.$bar;\n this.handle_group\n .querySelector('.handle.left')\n .setAttribute('x', bar.getX() + 1);\n this.handle_group\n .querySelector('.handle.right')\n .setAttribute('x', bar.getEndX() - 9);\n const handle = this.group.querySelector('.handle.progress');\n handle &&\n handle.setAttribute('points', this.get_progress_polygon_points());\n }\n\n update_arrow_position() {\n this.arrows = this.arrows || [];\n for (let arrow of this.arrows) {\n arrow.update();\n }\n }\n}\n\nfunction isFunction(functionToCheck) {\n var getType = {};\n return (\n functionToCheck &&\n getType.toString.call(functionToCheck) === '[object Function]'\n );\n}\n","import { createSVG } from './svg_utils';\n\nexport default class Arrow {\n constructor(gantt, from_task, to_task) {\n this.gantt = gantt;\n this.from_task = from_task;\n this.to_task = to_task;\n\n this.calculate_path();\n this.draw();\n }\n\n calculate_path() {\n let start_x =\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\n\n const condition = () =>\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\n\n while (condition()) {\n start_x -= 10;\n }\n\n const start_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.from_task.task._index +\n this.gantt.options.padding;\n\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\n const end_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height / 2 +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.to_task.task._index +\n this.gantt.options.padding;\n\n const from_is_below_to =\n this.from_task.task._index > this.to_task.task._index;\n const curve = this.gantt.options.arrow_curve;\n const clockwise = from_is_below_to ? 1 : 0;\n const curve_y = from_is_below_to ? -curve : curve;\n const offset = from_is_below_to\n ? end_y + this.gantt.options.arrow_curve\n : end_y - this.gantt.options.arrow_curve;\n\n this.path = `\n M ${start_x} ${start_y}\n V ${offset}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n\n if (\n this.to_task.$bar.getX() <\n this.from_task.$bar.getX() + this.gantt.options.padding\n ) {\n const down_1 = this.gantt.options.padding / 2 - curve;\n const down_2 =\n this.to_task.$bar.getY() +\n this.to_task.$bar.getHeight() / 2 -\n curve_y;\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\n\n this.path = `\n M ${start_x} ${start_y}\n v ${down_1}\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\n H ${left}\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\n V ${down_2}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n }\n }\n\n draw() {\n this.element = createSVG('path', {\n d: this.path,\n 'data-from': this.from_task.task.id,\n 'data-to': this.to_task.task.id,\n });\n }\n\n update() {\n this.calculate_path();\n this.element.setAttribute('d', this.path);\n }\n}\n","export default class Popup {\n constructor(parent, custom_html) {\n this.parent = parent;\n this.custom_html = custom_html;\n this.make();\n }\n\n make() {\n this.parent.innerHTML = `\n
\n
\n
\n `;\n\n this.hide();\n\n this.title = this.parent.querySelector('.title');\n this.subtitle = this.parent.querySelector('.subtitle');\n this.pointer = this.parent.querySelector('.pointer');\n }\n\n show(options) {\n if (!options.target_element) {\n throw new Error('target_element is required to show popup');\n }\n if (!options.position) {\n options.position = 'left';\n }\n const target_element = options.target_element;\n\n if (this.custom_html) {\n let html = this.custom_html(options.task);\n html += '
';\n this.parent.innerHTML = html;\n this.pointer = this.parent.querySelector('.pointer');\n } else {\n // set data\n this.title.innerHTML = options.title;\n this.subtitle.innerHTML = options.subtitle;\n this.parent.style.width = this.parent.clientWidth + 'px';\n }\n\n // set position\n let position_meta;\n if (target_element instanceof HTMLElement) {\n position_meta = target_element.getBoundingClientRect();\n } else if (target_element instanceof SVGElement) {\n position_meta = options.target_element.getBBox();\n }\n\n if (options.position === 'left') {\n this.parent.style.left =\n position_meta.x + (position_meta.width + 10) + 'px';\n this.parent.style.top = position_meta.y + 'px';\n\n this.pointer.style.transform = 'rotateZ(90deg)';\n this.pointer.style.left = '-7px';\n this.pointer.style.top = '2px';\n }\n\n // show\n this.parent.style.opacity = 1;\n }\n\n hide() {\n this.parent.style.opacity = 0;\n this.parent.style.left = 0;\n }\n}\n","import date_utils from './date_utils';\nimport { $, createSVG } from './svg_utils';\nimport Bar from './bar';\nimport Arrow from './arrow';\nimport Popup from './popup';\n\nimport './gantt.scss';\n\nconst VIEW_MODE = {\n QUARTER_DAY: 'Quarter Day',\n HALF_DAY: 'Half Day',\n DAY: 'Day',\n WEEK: 'Week',\n MONTH: 'Month',\n YEAR: 'Year',\n};\n\nexport default class Gantt {\n constructor(wrapper, tasks, options) {\n this.setup_wrapper(wrapper);\n this.setup_options(options);\n this.setup_tasks(tasks);\n // initialize with default view mode\n this.change_view_mode();\n this.bind_events();\n }\n\n setup_wrapper(element) {\n let svg_element, wrapper_element;\n\n // CSS Selector is passed\n if (typeof element === 'string') {\n element = document.querySelector(element);\n }\n\n // get the SVGElement\n if (element instanceof HTMLElement) {\n wrapper_element = element;\n svg_element = element.querySelector('svg');\n } else if (element instanceof SVGElement) {\n svg_element = element;\n } else {\n throw new TypeError(\n 'Frappé Gantt only supports usage of a string CSS selector,' +\n \" HTML DOM element or SVG DOM element for the 'element' parameter\"\n );\n }\n\n // svg element\n if (!svg_element) {\n // create it\n this.$svg = createSVG('svg', {\n append_to: wrapper_element,\n class: 'gantt',\n });\n } else {\n this.$svg = svg_element;\n this.$svg.classList.add('gantt');\n }\n\n // wrapper element\n this.$container = document.createElement('div');\n this.$container.classList.add('gantt-container');\n\n const parent_element = this.$svg.parentElement;\n parent_element.appendChild(this.$container);\n this.$container.appendChild(this.$svg);\n\n // popup wrapper\n this.popup_wrapper = document.createElement('div');\n this.popup_wrapper.classList.add('popup-wrapper');\n this.$container.appendChild(this.popup_wrapper);\n }\n\n setup_options(options) {\n const default_options = {\n header_height: 50,\n column_width: 30,\n step: 24,\n view_modes: [...Object.values(VIEW_MODE)],\n bar_height: 20,\n bar_corner_radius: 3,\n arrow_curve: 5,\n padding: 18,\n view_mode: 'Day',\n date_format: 'YYYY-MM-DD',\n popup_trigger: 'click',\n custom_popup_html: null,\n language: 'en',\n };\n this.options = Object.assign({}, default_options, options);\n }\n\n setup_tasks(tasks) {\n // prepare tasks\n this.tasks = tasks.map((task, i) => {\n // convert to Date objects\n task._start = date_utils.parse(task.start);\n task._end = date_utils.parse(task.end);\n\n // make task invalid if duration too large\n if (date_utils.diff(task._end, task._start, 'year') > 10) {\n task.end = null;\n }\n\n // cache index\n task._index = i;\n\n // invalid dates\n if (!task.start && !task.end) {\n const today = date_utils.today();\n task._start = today;\n task._end = date_utils.add(today, 2, 'day');\n }\n\n if (!task.start && task.end) {\n task._start = date_utils.add(task._end, -2, 'day');\n }\n\n if (task.start && !task.end) {\n task._end = date_utils.add(task._start, 2, 'day');\n }\n\n // if hours is not set, assume the last day is full day\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\n const task_end_values = date_utils.get_date_values(task._end);\n if (task_end_values.slice(3).every((d) => d === 0)) {\n task._end = date_utils.add(task._end, 24, 'hour');\n }\n\n // invalid flag\n if (!task.start || !task.end) {\n task.invalid = true;\n }\n\n // dependencies\n if (typeof task.dependencies === 'string' || !task.dependencies) {\n let deps = [];\n if (task.dependencies) {\n deps = task.dependencies\n .split(',')\n .map((d) => d.trim())\n .filter((d) => d);\n }\n task.dependencies = deps;\n }\n\n // uids\n if (!task.id) {\n task.id = generate_id(task);\n }\n\n return task;\n });\n\n this.setup_dependencies();\n }\n\n setup_dependencies() {\n this.dependency_map = {};\n for (let t of this.tasks) {\n for (let d of t.dependencies) {\n this.dependency_map[d] = this.dependency_map[d] || [];\n this.dependency_map[d].push(t.id);\n }\n }\n }\n\n refresh(tasks) {\n this.setup_tasks(tasks);\n this.change_view_mode();\n }\n\n change_view_mode(mode = this.options.view_mode) {\n this.update_view_scale(mode);\n this.setup_dates();\n this.render();\n // fire viewmode_change event\n this.trigger_event('view_change', [mode]);\n }\n\n update_view_scale(view_mode) {\n this.options.view_mode = view_mode;\n\n if (view_mode === VIEW_MODE.DAY) {\n this.options.step = 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\n this.options.step = 24 / 2;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\n this.options.step = 24 / 4;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.WEEK) {\n this.options.step = 24 * 7;\n this.options.column_width = 140;\n } else if (view_mode === VIEW_MODE.MONTH) {\n this.options.step = 24 * 30;\n this.options.column_width = 120;\n } else if (view_mode === VIEW_MODE.YEAR) {\n this.options.step = 24 * 365;\n this.options.column_width = 120;\n }\n }\n\n setup_dates() {\n this.setup_gantt_dates();\n this.setup_date_values();\n }\n\n setup_gantt_dates() {\n this.gantt_start = this.gantt_end = null;\n\n for (let task of this.tasks) {\n // set global start and end date\n if (!this.gantt_start || task._start < this.gantt_start) {\n this.gantt_start = task._start;\n }\n if (!this.gantt_end || task._end > this.gantt_end) {\n this.gantt_end = task._end;\n }\n }\n\n this.gantt_start = date_utils.start_of(this.gantt_start, 'day');\n this.gantt_end = date_utils.start_of(this.gantt_end, 'day');\n\n // add date padding on both sides\n if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) {\n this.gantt_start = date_utils.add(this.gantt_start, -7, 'day');\n this.gantt_end = date_utils.add(this.gantt_end, 7, 'day');\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n this.gantt_start = date_utils.start_of(this.gantt_start, 'year');\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'year');\n } else if (this.view_is(VIEW_MODE.YEAR)) {\n this.gantt_start = date_utils.add(this.gantt_start, -2, 'year');\n this.gantt_end = date_utils.add(this.gantt_end, 2, 'year');\n } else {\n this.gantt_start = date_utils.add(this.gantt_start, -1, 'month');\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'month');\n }\n }\n\n setup_date_values() {\n this.dates = [];\n let cur_date = null;\n\n while (cur_date === null || cur_date < this.gantt_end) {\n if (!cur_date) {\n cur_date = date_utils.clone(this.gantt_start);\n } else {\n if (this.view_is(VIEW_MODE.YEAR)) {\n cur_date = date_utils.add(cur_date, 1, 'year');\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n cur_date = date_utils.add(cur_date, 1, 'month');\n } else {\n cur_date = date_utils.add(\n cur_date,\n this.options.step,\n 'hour'\n );\n }\n }\n this.dates.push(cur_date);\n }\n }\n\n bind_events() {\n this.bind_grid_click();\n this.bind_bar_events();\n }\n\n render() {\n this.clear();\n this.setup_layers();\n this.make_grid();\n this.make_dates();\n this.make_bars();\n this.make_arrows();\n this.map_arrows_on_bars();\n this.set_width();\n this.set_scroll_position();\n }\n\n setup_layers() {\n this.layers = {};\n const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details'];\n // make group layers\n for (let layer of layers) {\n this.layers[layer] = createSVG('g', {\n class: layer,\n append_to: this.$svg,\n });\n }\n }\n\n make_grid() {\n this.make_grid_background();\n this.make_grid_rows();\n this.make_grid_header();\n this.make_grid_ticks();\n this.make_grid_highlights();\n }\n\n make_grid_background() {\n const grid_width = this.dates.length * this.options.column_width;\n const grid_height =\n this.options.header_height +\n this.options.padding +\n (this.options.bar_height + this.options.padding) *\n this.tasks.length;\n\n createSVG('rect', {\n x: 0,\n y: 0,\n width: grid_width,\n height: grid_height,\n class: 'grid-background',\n append_to: this.layers.grid,\n });\n\n $.attr(this.$svg, {\n height: grid_height + this.options.padding + 100,\n width: '100%',\n });\n }\n\n make_grid_rows() {\n const rows_layer = createSVG('g', { append_to: this.layers.grid });\n const lines_layer = createSVG('g', { append_to: this.layers.grid });\n\n const row_width = this.dates.length * this.options.column_width;\n const row_height = this.options.bar_height + this.options.padding;\n\n let row_y = this.options.header_height + this.options.padding / 2;\n\n for (let task of this.tasks) {\n createSVG('rect', {\n x: 0,\n y: row_y,\n width: row_width,\n height: row_height,\n class: 'grid-row',\n append_to: rows_layer,\n });\n\n createSVG('line', {\n x1: 0,\n y1: row_y + row_height,\n x2: row_width,\n y2: row_y + row_height,\n class: 'row-line',\n append_to: lines_layer,\n });\n\n row_y += this.options.bar_height + this.options.padding;\n }\n }\n\n make_grid_header() {\n const header_width = this.dates.length * this.options.column_width;\n const header_height = this.options.header_height + 10;\n createSVG('rect', {\n x: 0,\n y: 0,\n width: header_width,\n height: header_height,\n class: 'grid-header',\n append_to: this.layers.grid,\n });\n }\n\n make_grid_ticks() {\n let tick_x = 0;\n let tick_y = this.options.header_height + this.options.padding / 2;\n let tick_height =\n (this.options.bar_height + this.options.padding) *\n this.tasks.length;\n\n for (let date of this.dates) {\n let tick_class = 'tick';\n // thick tick for monday\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\n tick_class += ' thick';\n }\n // thick tick for first week\n if (\n this.view_is(VIEW_MODE.WEEK) &&\n date.getDate() >= 1 &&\n date.getDate() < 8\n ) {\n tick_class += ' thick';\n }\n // thick ticks for quarters\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\n tick_class += ' thick';\n }\n\n createSVG('path', {\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\n class: tick_class,\n append_to: this.layers.grid,\n });\n\n if (this.view_is(VIEW_MODE.MONTH)) {\n tick_x +=\n (date_utils.get_days_in_month(date) *\n this.options.column_width) /\n 30;\n } else {\n tick_x += this.options.column_width;\n }\n }\n }\n\n make_grid_highlights() {\n // highlight today's date\n if (this.view_is(VIEW_MODE.DAY)) {\n const x =\n (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') /\n this.options.step) *\n this.options.column_width;\n const y = 0;\n\n const width = this.options.column_width;\n const height =\n (this.options.bar_height + this.options.padding) *\n this.tasks.length +\n this.options.header_height +\n this.options.padding / 2;\n\n createSVG('rect', {\n x,\n y,\n width,\n height,\n class: 'today-highlight',\n append_to: this.layers.grid,\n });\n }\n }\n\n make_dates() {\n for (let date of this.get_dates_to_draw()) {\n createSVG('text', {\n x: date.lower_x,\n y: date.lower_y,\n innerHTML: date.lower_text,\n class: 'lower-text',\n append_to: this.layers.date,\n });\n\n if (date.upper_text) {\n const $upper_text = createSVG('text', {\n x: date.upper_x,\n y: date.upper_y,\n innerHTML: date.upper_text,\n class: 'upper-text',\n append_to: this.layers.date,\n });\n\n // remove out-of-bound dates\n if (\n $upper_text.getBBox().x2 > this.layers.grid.getBBox().width\n ) {\n $upper_text.remove();\n }\n }\n }\n }\n\n get_dates_to_draw() {\n let last_date = null;\n const dates = this.dates.map((date, i) => {\n const d = this.get_date_info(date, last_date, i);\n last_date = date;\n return d;\n });\n return dates;\n }\n\n get_date_info(date, last_date, i) {\n if (!last_date) {\n last_date = date_utils.add(date, 1, 'year');\n }\n const date_text = {\n 'Quarter Day_lower': date_utils.format(\n date,\n 'HH',\n this.options.language\n ),\n 'Half Day_lower': date_utils.format(\n date,\n 'HH',\n this.options.language\n ),\n Day_lower:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, 'D', this.options.language)\n : '',\n Week_lower:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'D MMM', this.options.language)\n : date_utils.format(date, 'D', this.options.language),\n Month_lower: date_utils.format(date, 'MMMM', this.options.language),\n Year_lower: date_utils.format(date, 'YYYY', this.options.language),\n 'Quarter Day_upper':\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, 'D MMM', this.options.language)\n : '',\n 'Half Day_upper':\n date.getDate() !== last_date.getDate()\n ? date.getMonth() !== last_date.getMonth()\n ? date_utils.format(\n date,\n 'D MMM',\n this.options.language\n )\n : date_utils.format(date, 'D', this.options.language)\n : '',\n Day_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'MMMM', this.options.language)\n : '',\n Week_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, 'MMMM', this.options.language)\n : '',\n Month_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, 'YYYY', this.options.language)\n : '',\n Year_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, 'YYYY', this.options.language)\n : '',\n };\n\n const base_pos = {\n x: i * this.options.column_width,\n lower_y: this.options.header_height,\n upper_y: this.options.header_height - 25,\n };\n\n const x_pos = {\n 'Quarter Day_lower': (this.options.column_width * 4) / 2,\n 'Quarter Day_upper': 0,\n 'Half Day_lower': (this.options.column_width * 2) / 2,\n 'Half Day_upper': 0,\n Day_lower: this.options.column_width / 2,\n Day_upper: (this.options.column_width * 30) / 2,\n Week_lower: 0,\n Week_upper: (this.options.column_width * 4) / 2,\n Month_lower: this.options.column_width / 2,\n Month_upper: (this.options.column_width * 12) / 2,\n Year_lower: this.options.column_width / 2,\n Year_upper: (this.options.column_width * 30) / 2,\n };\n\n return {\n upper_text: date_text[`${this.options.view_mode}_upper`],\n lower_text: date_text[`${this.options.view_mode}_lower`],\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\n upper_y: base_pos.upper_y,\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\n lower_y: base_pos.lower_y,\n };\n }\n\n make_bars() {\n this.bars = this.tasks.map((task) => {\n const bar = new Bar(this, task);\n this.layers.bar.appendChild(bar.group);\n return bar;\n });\n }\n\n make_arrows() {\n this.arrows = [];\n for (let task of this.tasks) {\n let arrows = [];\n arrows = task.dependencies\n .map((task_id) => {\n const dependency = this.get_task(task_id);\n if (!dependency) return;\n const arrow = new Arrow(\n this,\n this.bars[dependency._index], // from_task\n this.bars[task._index] // to_task\n );\n this.layers.arrow.appendChild(arrow.element);\n return arrow;\n })\n .filter(Boolean); // filter falsy values\n this.arrows = this.arrows.concat(arrows);\n }\n }\n\n map_arrows_on_bars() {\n for (let bar of this.bars) {\n bar.arrows = this.arrows.filter((arrow) => {\n return (\n arrow.from_task.task.id === bar.task.id ||\n arrow.to_task.task.id === bar.task.id\n );\n });\n }\n }\n\n set_width() {\n const cur_width = this.$svg.getBoundingClientRect().width;\n const actual_width = this.$svg\n .querySelector('.grid .grid-row')\n .getAttribute('width');\n if (cur_width < actual_width) {\n this.$svg.setAttribute('width', actual_width);\n }\n }\n\n set_scroll_position() {\n const parent_element = this.$svg.parentElement;\n if (!parent_element) return;\n\n const hours_before_first_task = date_utils.diff(\n this.get_oldest_starting_date(),\n this.gantt_start,\n 'hour'\n );\n\n const scroll_pos =\n (hours_before_first_task / this.options.step) *\n this.options.column_width -\n this.options.column_width;\n\n parent_element.scrollLeft = scroll_pos;\n }\n\n bind_grid_click() {\n $.on(\n this.$svg,\n this.options.popup_trigger,\n '.grid-row, .grid-header',\n () => {\n this.unselect_all();\n this.hide_popup();\n }\n );\n }\n\n bind_bar_events() {\n let is_dragging = false;\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing_left = false;\n let is_resizing_right = false;\n let parent_bar_id = null;\n let bars = []; // instanceof Bar\n this.bar_being_dragged = null;\n\n function action_in_progress() {\n return is_dragging || is_resizing_left || is_resizing_right;\n }\n\n $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {\n const bar_wrapper = $.closest('.bar-wrapper', element);\n\n if (element.classList.contains('left')) {\n is_resizing_left = true;\n } else if (element.classList.contains('right')) {\n is_resizing_right = true;\n } else if (element.classList.contains('bar-wrapper')) {\n is_dragging = true;\n }\n\n bar_wrapper.classList.add('active');\n\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n parent_bar_id = bar_wrapper.getAttribute('data-id');\n const ids = [\n parent_bar_id,\n ...this.get_all_dependent_tasks(parent_bar_id),\n ];\n bars = ids.map((id) => this.get_bar(id));\n\n this.bar_being_dragged = parent_bar_id;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.ox = $bar.getX();\n $bar.oy = $bar.getY();\n $bar.owidth = $bar.getWidth();\n $bar.finaldx = 0;\n });\n });\n\n $.on(this.$svg, 'mousemove', (e) => {\n if (!action_in_progress()) return;\n const dx = e.offsetX - x_on_start;\n const dy = e.offsetY - y_on_start;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.finaldx = this.get_snap_position(dx);\n this.hide_popup();\n if (is_resizing_left) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n width: $bar.owidth - $bar.finaldx,\n });\n } else {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n });\n }\n } else if (is_resizing_right) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n width: $bar.owidth + $bar.finaldx,\n });\n }\n } else if (is_dragging) {\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\n }\n });\n });\n\n document.addEventListener('mouseup', (e) => {\n if (is_dragging || is_resizing_left || is_resizing_right) {\n bars.forEach((bar) => bar.group.classList.remove('active'));\n }\n\n is_dragging = false;\n is_resizing_left = false;\n is_resizing_right = false;\n });\n\n $.on(this.$svg, 'mouseup', (e) => {\n this.bar_being_dragged = null;\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n if (!$bar.finaldx) return;\n bar.date_changed();\n bar.set_action_completed();\n });\n });\n\n this.bind_bar_progress();\n }\n\n bind_bar_progress() {\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing = null;\n let bar = null;\n let $bar_progress = null;\n let $bar = null;\n\n $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => {\n is_resizing = true;\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n const $bar_wrapper = $.closest('.bar-wrapper', handle);\n const id = $bar_wrapper.getAttribute('data-id');\n bar = this.get_bar(id);\n\n $bar_progress = bar.$bar_progress;\n $bar = bar.$bar;\n\n $bar_progress.finaldx = 0;\n $bar_progress.owidth = $bar_progress.getWidth();\n $bar_progress.min_dx = -$bar_progress.getWidth();\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\n });\n\n $.on(this.$svg, 'mousemove', (e) => {\n if (!is_resizing) return;\n let dx = e.offsetX - x_on_start;\n let dy = e.offsetY - y_on_start;\n\n if (dx > $bar_progress.max_dx) {\n dx = $bar_progress.max_dx;\n }\n if (dx < $bar_progress.min_dx) {\n dx = $bar_progress.min_dx;\n }\n\n const $handle = bar.$handle_progress;\n $.attr($bar_progress, 'width', $bar_progress.owidth + dx);\n $.attr($handle, 'points', bar.get_progress_polygon_points());\n $bar_progress.finaldx = dx;\n });\n\n $.on(this.$svg, 'mouseup', () => {\n is_resizing = false;\n if (!($bar_progress && $bar_progress.finaldx)) return;\n bar.progress_changed();\n bar.set_action_completed();\n });\n }\n\n get_all_dependent_tasks(task_id) {\n let out = [];\n let to_process = [task_id];\n while (to_process.length) {\n const deps = to_process.reduce((acc, curr) => {\n acc = acc.concat(this.dependency_map[curr]);\n return acc;\n }, []);\n\n out = out.concat(deps);\n to_process = deps.filter((d) => !to_process.includes(d));\n }\n\n return out.filter(Boolean);\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.view_is(VIEW_MODE.WEEK)) {\n rem = dx % (this.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 14\n ? 0\n : this.options.column_width / 7);\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n rem = dx % (this.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 60\n ? 0\n : this.options.column_width / 30);\n } else {\n rem = dx % this.options.column_width;\n position =\n odx -\n rem +\n (rem < this.options.column_width / 2\n ? 0\n : this.options.column_width);\n }\n return position;\n }\n\n unselect_all() {\n [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => {\n el.classList.remove('active');\n });\n }\n\n view_is(modes) {\n if (typeof modes === 'string') {\n return this.options.view_mode === modes;\n }\n\n if (Array.isArray(modes)) {\n return modes.some((mode) => this.options.view_mode === mode);\n }\n\n return false;\n }\n\n get_task(id) {\n return this.tasks.find((task) => {\n return task.id === id;\n });\n }\n\n get_bar(id) {\n return this.bars.find((bar) => {\n return bar.task.id === id;\n });\n }\n\n show_popup(options) {\n if (!this.popup) {\n this.popup = new Popup(\n this.popup_wrapper,\n this.options.custom_popup_html\n );\n }\n this.popup.show(options);\n }\n\n hide_popup() {\n this.popup && this.popup.hide();\n }\n\n trigger_event(event, args) {\n if (this.options['on_' + event]) {\n this.options['on_' + event].apply(null, args);\n }\n }\n\n /**\n * Gets the oldest starting date from the list of tasks\n *\n * @returns Date\n * @memberof Gantt\n */\n get_oldest_starting_date() {\n return this.tasks\n .map((task) => task._start)\n .reduce((prev_date, cur_date) =>\n cur_date <= prev_date ? cur_date : prev_date\n );\n }\n\n /**\n * Clear all elements from the parent svg element\n *\n * @memberof Gantt\n */\n clear() {\n this.$svg.innerHTML = '';\n }\n}\n\nGantt.VIEW_MODE = VIEW_MODE;\n\nfunction generate_id(task) {\n return task.name + '_' + Math.random().toString(36).slice(2, 12);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"frappe-gantt.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = \"year\";\nconst MONTH = \"month\";\nconst DAY = \"day\";\nconst HOUR = \"hour\";\nconst MINUTE = \"minute\";\nconst SECOND = \"second\";\nconst MILLISECOND = \"millisecond\";\n\nexport default {\n parse_duration(duration) {\n const regex = /([0-9])+(y|m|d|h|min|s|ms)/gm;\n const matches = regex.exec(duration);\n\n if (matches !== null) {\n if (matches[2] === \"y\") {\n return { duration: parseInt(matches[1]), scale: `year` };\n } else if (matches[2] === \"m\") {\n return { duration: parseInt(matches[1]), scale: `month` };\n } else if (matches[2] === \"d\") {\n return { duration: parseInt(matches[1]), scale: `day` };\n } else if (matches[2] === \"h\") {\n return { duration: parseInt(matches[1]), scale: `hour` };\n } else if (matches[2] === \"min\") {\n return { duration: parseInt(matches[1]), scale: `minute` };\n } else if (matches[2] === \"s\") {\n return { duration: parseInt(matches[1]), scale: `second` };\n } else if (matches[2] === \"ms\") {\n return { duration: parseInt(matches[1]), scale: `millisecond` };\n }\n }\n },\n parse(date, date_separator = \"-\", time_separator = /[.:]/) {\n if (date instanceof Date) {\n return date;\n }\n if (typeof date === \"string\") {\n let date_parts, time_parts;\n const parts = date.split(\" \");\n\n date_parts = parts[0]\n .split(date_separator)\n .map((val) => parseInt(val, 10));\n time_parts = parts[1] && parts[1].split(time_separator);\n\n // month is 0 indexed\n date_parts[1] = date_parts[1] - 1;\n\n let vals = date_parts;\n\n if (time_parts && time_parts.length) {\n if (time_parts.length == 4) {\n time_parts[3] = \"0.\" + time_parts[3];\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\n }\n vals = vals.concat(time_parts);\n }\n\n return new Date(...vals);\n }\n },\n\n to_string(date, with_time = false) {\n if (!(date instanceof Date)) {\n throw new TypeError(\"Invalid argument type\");\n }\n const vals = this.get_date_values(date).map((val, i) => {\n if (i === 1) {\n // add 1 for month\n val = val + 1;\n }\n\n if (i === 6) {\n return padStart(val + \"\", 3, \"0\");\n }\n\n return padStart(val + \"\", 2, \"0\");\n });\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\n\n return date_string + (with_time ? \" \" + time_string : \"\");\n },\n\n format(date, format_string = \"YYYY-MM-DD HH:mm:ss.SSS\", lang = \"en\") {\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\n month: \"long\",\n });\n const month_name = dateTimeFormat.format(date);\n const month_name_capitalized =\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\n\n const values = this.get_date_values(date).map((d) => padStart(d, 2, 0));\n const format_map = {\n YYYY: values[0],\n MM: padStart(+values[1] + 1, 2, 0),\n DD: values[2],\n HH: values[3],\n mm: values[4],\n ss: values[5],\n SSS: values[6],\n D: values[2],\n MMMM: month_name_capitalized,\n MMM: month_name_capitalized,\n };\n\n let str = format_string;\n const formatted_values = [];\n\n Object.keys(format_map)\n .sort((a, b) => b.length - a.length) // big string first\n .forEach((key) => {\n if (str.includes(key)) {\n str = str.replace(key, `$${formatted_values.length}`);\n formatted_values.push(format_map[key]);\n }\n });\n\n formatted_values.forEach((value, i) => {\n str = str.replace(`$${i}`, value);\n });\n\n return str;\n },\n\n diff(date_a, date_b, scale = DAY) {\n let milliseconds, seconds, hours, minutes, days, months, years;\n\n milliseconds = date_a - date_b;\n seconds = milliseconds / 1000;\n minutes = seconds / 60;\n hours = minutes / 60;\n days = hours / 24;\n months = days / 30;\n years = months / 12;\n\n if (!scale.endsWith(\"s\")) {\n scale += \"s\";\n }\n\n return Math.floor(\n {\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n months,\n years,\n }[scale],\n );\n },\n\n today() {\n const vals = this.get_date_values(new Date()).slice(0, 3);\n return new Date(...vals);\n },\n\n now() {\n return new Date();\n },\n\n add(date, qty, scale) {\n qty = parseInt(qty, 10);\n const vals = [\n date.getFullYear() + (scale === YEAR ? qty : 0),\n date.getMonth() + (scale === MONTH ? qty : 0),\n date.getDate() + (scale === DAY ? qty : 0),\n date.getHours() + (scale === HOUR ? qty : 0),\n date.getMinutes() + (scale === MINUTE ? qty : 0),\n date.getSeconds() + (scale === SECOND ? qty : 0),\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\n ];\n return new Date(...vals);\n },\n\n start_of(date, scale) {\n const scores = {\n [YEAR]: 6,\n [MONTH]: 5,\n [DAY]: 4,\n [HOUR]: 3,\n [MINUTE]: 2,\n [SECOND]: 1,\n [MILLISECOND]: 0,\n };\n\n function should_reset(_scale) {\n const max_score = scores[scale];\n return scores[_scale] <= max_score;\n }\n\n const vals = [\n date.getFullYear(),\n should_reset(YEAR) ? 0 : date.getMonth(),\n should_reset(MONTH) ? 1 : date.getDate(),\n should_reset(DAY) ? 0 : date.getHours(),\n should_reset(HOUR) ? 0 : date.getMinutes(),\n should_reset(MINUTE) ? 0 : date.getSeconds(),\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\n ];\n\n return new Date(...vals);\n },\n\n clone(date) {\n return new Date(...this.get_date_values(date));\n },\n\n get_date_values(date) {\n return [\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n ];\n },\n\n get_days_in_month(date) {\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n const month = date.getMonth();\n\n if (month !== 1) {\n return no_of_days[month];\n }\n\n // Feb\n const year = date.getFullYear();\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\n return 29;\n }\n return 28;\n },\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\nfunction padStart(str, targetLength, padString) {\n str = str + \"\";\n targetLength = targetLength >> 0;\n padString = String(typeof padString !== \"undefined\" ? padString : \" \");\n if (str.length > targetLength) {\n return String(str);\n } else {\n targetLength = targetLength - str.length;\n if (targetLength > padString.length) {\n padString += padString.repeat(targetLength / padString.length);\n }\n return padString.slice(0, targetLength) + String(str);\n }\n}\n","export function $(expr, con) {\n return typeof expr === \"string\"\n ? (con || document).querySelector(expr)\n : expr || null;\n}\n\nexport function createSVG(tag, attrs) {\n const elem = document.createElementNS(\"http://www.w3.org/2000/svg\", tag);\n for (let attr in attrs) {\n if (attr === \"append_to\") {\n const parent = attrs.append_to;\n parent.appendChild(elem);\n } else if (attr === \"innerHTML\") {\n elem.innerHTML = attrs.innerHTML;\n } else {\n elem.setAttribute(attr, attrs[attr]);\n }\n }\n return elem;\n}\n\nexport function animateSVG(svgElement, attr, from, to) {\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\n\n if (animatedSvgElement === svgElement) {\n // triggered 2nd time programmatically\n // trigger artificial click event\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"click\", true, true);\n event.eventName = \"click\";\n animatedSvgElement.dispatchEvent(event);\n }\n}\n\nfunction getAnimationElement(\n svgElement,\n attr,\n from,\n to,\n dur = \"0.4s\",\n begin = \"0.1s\",\n) {\n const animEl = svgElement.querySelector(\"animate\");\n if (animEl) {\n $.attr(animEl, {\n attributeName: attr,\n from,\n to,\n dur,\n begin: \"click + \" + begin, // artificial click\n });\n return svgElement;\n }\n\n const animateElement = createSVG(\"animate\", {\n attributeName: attr,\n from,\n to,\n dur,\n begin,\n calcMode: \"spline\",\n values: from + \";\" + to,\n keyTimes: \"0; 1\",\n keySplines: cubic_bezier(\"ease-out\"),\n });\n svgElement.appendChild(animateElement);\n\n return svgElement;\n}\n\nfunction cubic_bezier(name) {\n return {\n ease: \".25 .1 .25 1\",\n linear: \"0 0 1 1\",\n \"ease-in\": \".42 0 1 1\",\n \"ease-out\": \"0 0 .58 1\",\n \"ease-in-out\": \".42 0 .58 1\",\n }[name];\n}\n\n$.on = (element, event, selector, callback) => {\n if (!callback) {\n callback = selector;\n $.bind(element, event, callback);\n } else {\n $.delegate(element, event, selector, callback);\n }\n};\n\n$.off = (element, event, handler) => {\n element.removeEventListener(event, handler);\n};\n\n$.bind = (element, event, callback) => {\n event.split(/\\s+/).forEach(function (event) {\n element.addEventListener(event, callback);\n });\n};\n\n$.delegate = (element, event, selector, callback) => {\n element.addEventListener(event, function (e) {\n const delegatedTarget = e.target.closest(selector);\n if (delegatedTarget) {\n e.delegatedTarget = delegatedTarget;\n callback.call(this, e, delegatedTarget);\n }\n });\n};\n\n$.closest = (selector, element) => {\n if (!element) return null;\n\n if (element.matches(selector)) {\n return element;\n }\n\n return $.closest(selector, element.parentNode);\n};\n\n$.attr = (element, attr, value) => {\n if (!value && typeof attr === \"string\") {\n return element.getAttribute(attr);\n }\n\n if (typeof attr === \"object\") {\n for (let key in attr) {\n $.attr(element, key, attr[key]);\n }\n return;\n }\n\n element.setAttribute(attr, value);\n};\n","import date_utils from \"./date_utils\";\nimport { $, createSVG, animateSVG } from \"./svg_utils\";\n\nexport default class Bar {\n constructor(gantt, task) {\n this.set_defaults(gantt, task);\n this.prepare();\n this.draw();\n this.bind();\n }\n\n set_defaults(gantt, task) {\n this.action_completed = false;\n this.gantt = gantt;\n this.task = task;\n }\n\n prepare() {\n this.prepare_values();\n this.prepare_helpers();\n }\n\n prepare_values() {\n this.invalid = this.task.invalid;\n this.height = this.gantt.options.bar_height;\n this.compute_x();\n this.compute_y();\n this.compute_duration();\n this.corner_radius = this.gantt.options.bar_corner_radius;\n this.width = this.gantt.options.column_width * this.duration;\n this.progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.task.progress / 100) || 0;\n this.group = createSVG(\"g\", {\n class: \"bar-wrapper \" + (this.task.custom_class || \"\"),\n \"data-id\": this.task.id,\n });\n this.bar_group = createSVG(\"g\", {\n class: \"bar-group\",\n append_to: this.group,\n });\n this.handle_group = createSVG(\"g\", {\n class: \"handle-group\",\n append_to: this.group,\n });\n }\n\n prepare_helpers() {\n SVGElement.prototype.getX = function () {\n return +this.getAttribute(\"x\");\n };\n SVGElement.prototype.getY = function () {\n return +this.getAttribute(\"y\");\n };\n SVGElement.prototype.getWidth = function () {\n return +this.getAttribute(\"width\");\n };\n SVGElement.prototype.getHeight = function () {\n return +this.getAttribute(\"height\");\n };\n SVGElement.prototype.getEndX = function () {\n return this.getX() + this.getWidth();\n };\n }\n\n prepare_expected_progress_values() {\n this.compute_expected_progress();\n this.expected_progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0;\n }\n\n draw() {\n this.draw_bar();\n if (this.gantt.options.show_expected_progress) {\n this.prepare_expected_progress_values();\n this.draw_expected_progress_bar();\n }\n this.draw_progress_bar();\n this.draw_label();\n this.draw_resize_handles();\n }\n\n draw_bar() {\n this.$bar = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar\",\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar, \"width\", 0, this.width);\n\n if (this.invalid) {\n this.$bar.classList.add(\"bar-invalid\");\n }\n }\n\n draw_expected_progress_bar() {\n if (this.invalid) return;\n this.$expected_bar_progress = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.expected_progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar-expected-progress\",\n append_to: this.bar_group,\n });\n\n animateSVG(\n this.$expected_bar_progress,\n \"width\",\n 0,\n this.expected_progress_width,\n );\n }\n\n draw_progress_bar() {\n if (this.invalid) return;\n this.$bar_progress = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar-progress\",\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar_progress, \"width\", 0, this.progress_width);\n }\n\n draw_label() {\n createSVG(\"text\", {\n x: this.x + this.width / 2,\n y: this.y + this.height / 2,\n innerHTML: this.task.name,\n class: \"bar-label\",\n append_to: this.bar_group,\n });\n // labels get BBox in the next tick\n requestAnimationFrame(() => this.update_label_position());\n }\n\n draw_resize_handles() {\n if (this.invalid) return;\n\n const bar = this.$bar;\n const handle_width = 8;\n\n createSVG(\"rect\", {\n x: bar.getX() + bar.getWidth() - 9,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"handle right\",\n append_to: this.handle_group,\n });\n\n createSVG(\"rect\", {\n x: bar.getX() + 1,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"handle left\",\n append_to: this.handle_group,\n });\n\n this.$handle_progress = createSVG(\"polygon\", {\n points: this.get_progress_polygon_points().join(\",\"),\n class: \"handle progress\",\n append_to: this.handle_group,\n });\n }\n\n get_progress_polygon_points() {\n const bar_progress = this.$bar_progress;\n return [\n bar_progress.getEndX() - 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX() + 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX(),\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\n ];\n }\n\n bind() {\n if (this.invalid) return;\n this.setup_click_event();\n }\n\n setup_click_event() {\n $.on(this.group, \"focus \" + this.gantt.options.popup_trigger, (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.show_popup();\n this.gantt.unselect_all();\n this.group.classList.add(\"active\");\n });\n\n $.on(this.group, \"dblclick\", (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.gantt.trigger_event(\"click\", [this.task]);\n });\n }\n\n show_popup() {\n if (this.gantt.bar_being_dragged) return;\n\n const start_date = date_utils.format(\n this.task._start,\n \"MMM D\",\n this.gantt.options.language,\n );\n const end_date = date_utils.format(\n date_utils.add(this.task._end, -1, \"second\"),\n \"MMM D\",\n this.gantt.options.language,\n );\n const subtitle = start_date + \" - \" + end_date;\n\n this.gantt.show_popup({\n target_element: this.$bar,\n title: this.task.name,\n subtitle: subtitle,\n task: this.task,\n });\n }\n\n update_bar_position({ x = null, width = null }) {\n const bar = this.$bar;\n if (x) {\n // get all x values of parent task\n const xs = this.task.dependencies.map((dep) => {\n return this.gantt.get_bar(dep).$bar.getX();\n });\n // child task must not go before parent\n const valid_x = xs.reduce((prev, curr) => {\n return x >= curr;\n }, x);\n if (!valid_x) {\n width = null;\n return;\n }\n this.update_attr(bar, \"x\", x);\n }\n if (width) {\n this.update_attr(bar, \"width\", width);\n }\n this.update_label_position();\n this.update_handle_position();\n if (this.gantt.options.show_expected_progress) {\n this.date_changed();\n this.compute_duration();\n this.update_expected_progressbar_position();\n }\n this.update_progressbar_position();\n this.update_arrow_position();\n }\n\n date_changed() {\n let changed = false;\n const { new_start_date, new_end_date } = this.compute_start_end_date();\n\n if (Number(this.task._start) !== Number(new_start_date)) {\n changed = true;\n this.task._start = new_start_date;\n }\n\n if (Number(this.task._end) !== Number(new_end_date)) {\n changed = true;\n this.task._end = new_end_date;\n }\n\n if (!changed) return;\n\n this.gantt.trigger_event(\"date_change\", [\n this.task,\n new_start_date,\n date_utils.add(new_end_date, -1, \"second\"),\n ]);\n }\n\n progress_changed() {\n const new_progress = this.compute_progress();\n this.task.progress = new_progress;\n this.gantt.trigger_event(\"progress_change\", [this.task, new_progress]);\n }\n\n set_action_completed() {\n this.action_completed = true;\n setTimeout(() => (this.action_completed = false), 1000);\n }\n\n compute_start_end_date() {\n const bar = this.$bar;\n const x_in_units = bar.getX() / this.gantt.options.column_width;\n const new_start_date = date_utils.add(\n this.gantt.gantt_start,\n x_in_units * this.gantt.options.step,\n \"hour\",\n );\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\n const new_end_date = date_utils.add(\n new_start_date,\n width_in_units * this.gantt.options.step,\n \"hour\",\n );\n\n return { new_start_date, new_end_date };\n }\n\n compute_progress() {\n const progress =\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\n return parseInt(progress, 10);\n }\n\n compute_expected_progress() {\n this.expected_progress =\n date_utils.diff(date_utils.today(), this.task._start, \"hour\") /\n this.gantt.options.step;\n this.expected_progress =\n ((this.expected_progress < this.duration\n ? this.expected_progress\n : this.duration) *\n 100) /\n this.duration;\n }\n\n compute_x() {\n const { step, column_width } = this.gantt.options;\n const task_start = this.task._start;\n const gantt_start = this.gantt.gantt_start;\n\n const diff = date_utils.diff(task_start, gantt_start, \"hour\");\n let x = (diff / step) * column_width;\n\n if (this.gantt.view_is(\"Month\")) {\n const diff = date_utils.diff(task_start, gantt_start, \"day\");\n x = (diff * column_width) / 30;\n }\n this.x = x;\n }\n\n compute_y() {\n this.y =\n this.gantt.options.header_height +\n this.gantt.options.padding +\n this.task._index * (this.height + this.gantt.options.padding);\n }\n\n compute_duration() {\n this.duration =\n date_utils.diff(this.task._end, this.task._start, \"hour\") /\n this.gantt.options.step;\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.gantt.view_is(\"Week\")) {\n rem = dx % (this.gantt.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 14\n ? 0\n : this.gantt.options.column_width / 7);\n } else if (this.gantt.view_is(\"Month\")) {\n rem = dx % (this.gantt.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 60\n ? 0\n : this.gantt.options.column_width / 30);\n } else {\n rem = dx % this.gantt.options.column_width;\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 2\n ? 0\n : this.gantt.options.column_width);\n }\n return position;\n }\n\n update_attr(element, attr, value) {\n value = +value;\n if (!isNaN(value)) {\n element.setAttribute(attr, value);\n }\n return element;\n }\n\n update_expected_progressbar_position() {\n if (this.invalid) return;\n this.$expected_bar_progress.setAttribute(\"x\", this.$bar.getX());\n this.compute_expected_progress();\n this.$expected_bar_progress.setAttribute(\n \"width\",\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0,\n );\n }\n\n update_progressbar_position() {\n if (this.invalid) return;\n this.$bar_progress.setAttribute(\"x\", this.$bar.getX());\n this.$bar_progress.setAttribute(\n \"width\",\n this.$bar.getWidth() * (this.task.progress / 100),\n );\n }\n\n update_label_position() {\n const bar = this.$bar,\n label = this.group.querySelector(\".bar-label\");\n\n if (label.getBBox().width > bar.getWidth()) {\n label.classList.add(\"big\");\n label.setAttribute(\"x\", bar.getX() + bar.getWidth() + 5);\n } else {\n label.classList.remove(\"big\");\n label.setAttribute(\"x\", bar.getX() + bar.getWidth() / 2);\n }\n }\n\n update_handle_position() {\n if (this.invalid) return;\n const bar = this.$bar;\n this.handle_group\n .querySelector(\".handle.left\")\n .setAttribute(\"x\", bar.getX() + 1);\n this.handle_group\n .querySelector(\".handle.right\")\n .setAttribute(\"x\", bar.getEndX() - 9);\n const handle = this.group.querySelector(\".handle.progress\");\n handle && handle.setAttribute(\"points\", this.get_progress_polygon_points());\n }\n\n update_arrow_position() {\n this.arrows = this.arrows || [];\n for (let arrow of this.arrows) {\n arrow.update();\n }\n }\n}\n\nfunction isFunction(functionToCheck) {\n var getType = {};\n return (\n functionToCheck &&\n getType.toString.call(functionToCheck) === \"[object Function]\"\n );\n}\n","import { createSVG } from \"./svg_utils\";\n\nexport default class Arrow {\n constructor(gantt, from_task, to_task) {\n this.gantt = gantt;\n this.from_task = from_task;\n this.to_task = to_task;\n\n this.calculate_path();\n this.draw();\n }\n\n calculate_path() {\n let start_x =\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\n\n const condition = () =>\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\n\n while (condition()) {\n start_x -= 10;\n }\n\n const start_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.from_task.task._index +\n this.gantt.options.padding;\n\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\n const end_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height / 2 +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.to_task.task._index +\n this.gantt.options.padding;\n\n const from_is_below_to =\n this.from_task.task._index > this.to_task.task._index;\n const curve = this.gantt.options.arrow_curve;\n const clockwise = from_is_below_to ? 1 : 0;\n const curve_y = from_is_below_to ? -curve : curve;\n const offset = from_is_below_to\n ? end_y + this.gantt.options.arrow_curve\n : end_y - this.gantt.options.arrow_curve;\n\n this.path = `\n M ${start_x} ${start_y}\n V ${offset}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n\n if (\n this.to_task.$bar.getX() <\n this.from_task.$bar.getX() + this.gantt.options.padding\n ) {\n const down_1 = this.gantt.options.padding / 2 - curve;\n const down_2 =\n this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - curve_y;\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\n\n this.path = `\n M ${start_x} ${start_y}\n v ${down_1}\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\n H ${left}\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\n V ${down_2}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n }\n }\n\n draw() {\n this.element = createSVG(\"path\", {\n d: this.path,\n \"data-from\": this.from_task.task.id,\n \"data-to\": this.to_task.task.id,\n });\n }\n\n update() {\n this.calculate_path();\n this.element.setAttribute(\"d\", this.path);\n }\n}\n","export default class Popup {\n constructor(parent, custom_html) {\n this.parent = parent;\n this.custom_html = custom_html;\n this.make();\n }\n\n make() {\n this.parent.innerHTML = `\n
\n
\n
\n `;\n\n this.hide();\n\n this.title = this.parent.querySelector(\".title\");\n this.subtitle = this.parent.querySelector(\".subtitle\");\n this.pointer = this.parent.querySelector(\".pointer\");\n }\n\n show(options) {\n if (!options.target_element) {\n throw new Error(\"target_element is required to show popup\");\n }\n if (!options.position) {\n options.position = \"left\";\n }\n const target_element = options.target_element;\n\n if (this.custom_html) {\n let html = this.custom_html(options.task);\n html += '
';\n this.parent.innerHTML = html;\n this.pointer = this.parent.querySelector(\".pointer\");\n } else {\n // set data\n this.title.innerHTML = options.title;\n this.subtitle.innerHTML = options.subtitle;\n this.parent.style.width = this.parent.clientWidth + \"px\";\n }\n\n // set position\n let position_meta;\n if (target_element instanceof HTMLElement) {\n position_meta = target_element.getBoundingClientRect();\n } else if (target_element instanceof SVGElement) {\n position_meta = options.target_element.getBBox();\n }\n\n if (options.position === \"left\") {\n this.parent.style.left =\n position_meta.x + (position_meta.width + 10) + \"px\";\n this.parent.style.top = position_meta.y + \"px\";\n\n this.pointer.style.transform = \"rotateZ(90deg)\";\n this.pointer.style.left = \"-7px\";\n this.pointer.style.top = \"2px\";\n }\n\n // show\n this.parent.style.opacity = 1;\n }\n\n hide() {\n this.parent.style.opacity = 0;\n this.parent.style.left = 0;\n }\n}\n","import date_utils from \"./date_utils\";\nimport { $, createSVG } from \"./svg_utils\";\nimport Bar from \"./bar\";\nimport Arrow from \"./arrow\";\nimport Popup from \"./popup\";\n\nimport \"./gantt.scss\";\n\nconst VIEW_MODE = {\n HOUR: \"Hour\",\n QUARTER_DAY: \"Quarter Day\",\n HALF_DAY: \"Half Day\",\n DAY: \"Day\",\n WEEK: \"Week\",\n MONTH: \"Month\",\n YEAR: \"Year\",\n};\n\nconst VIEW_MODE_PADDING = {\n HOUR: [\"7d\", \"7d\"],\n QUARTER_DAY: [\"7d\", \"7d\"],\n HALF_DAY: [\"7d\", \"7d\"],\n DAY: [\"1m\", \"1m\"],\n WEEK: [\"1m\", \"1m\"],\n MONTH: [\"1m\", \"1m\"],\n YEAR: [\"2y\", \"2y\"],\n};\n\nexport default class Gantt {\n constructor(wrapper, tasks, options) {\n this.setup_wrapper(wrapper);\n this.setup_options(options);\n this.setup_tasks(tasks);\n // initialize with default view mode\n this.change_view_mode();\n this.bind_events();\n }\n\n setup_wrapper(element) {\n let svg_element, wrapper_element;\n\n // CSS Selector is passed\n if (typeof element === \"string\") {\n element = document.querySelector(element);\n }\n\n // get the SVGElement\n if (element instanceof HTMLElement) {\n wrapper_element = element;\n svg_element = element.querySelector(\"svg\");\n } else if (element instanceof SVGElement) {\n svg_element = element;\n } else {\n throw new TypeError(\n \"Frappé Gantt only supports usage of a string CSS selector,\" +\n \" HTML DOM element or SVG DOM element for the 'element' parameter\",\n );\n }\n\n // svg element\n if (!svg_element) {\n // create it\n this.$svg = createSVG(\"svg\", {\n append_to: wrapper_element,\n class: \"gantt\",\n });\n } else {\n this.$svg = svg_element;\n this.$svg.classList.add(\"gantt\");\n }\n\n // wrapper element\n this.$container = document.createElement(\"div\");\n this.$container.classList.add(\"gantt-container\");\n\n const parent_element = this.$svg.parentElement;\n parent_element.appendChild(this.$container);\n this.$container.appendChild(this.$svg);\n\n // popup wrapper\n this.popup_wrapper = document.createElement(\"div\");\n this.popup_wrapper.classList.add(\"popup-wrapper\");\n this.$container.appendChild(this.popup_wrapper);\n }\n\n setup_options(options) {\n const default_options = {\n header_height: 50,\n column_width: 30,\n step: 24,\n view_modes: [...Object.values(VIEW_MODE)],\n bar_height: 20,\n bar_corner_radius: 3,\n arrow_curve: 5,\n padding: 18,\n view_mode: \"Day\",\n date_format: \"YYYY-MM-DD\",\n popup_trigger: \"click\",\n custom_popup_html: null,\n language: \"en\",\n };\n this.options = Object.assign({}, default_options, options);\n for (let [key, value] of Object.entries(options.view_mode_padding)) {\n if (typeof value === \"string\") {\n // Configure for single value given\n options.view_mode_padding[key] = [value, value];\n }\n }\n\n console.log(options.view_mode_padding);\n this.options.view_mode_padding = {\n ...VIEW_MODE_PADDING,\n ...options.view_mode_padding,\n };\n }\n\n setup_tasks(tasks) {\n // prepare tasks\n this.tasks = tasks.map((task, i) => {\n // convert to Date objects\n task._start = date_utils.parse(task.start);\n if (task.end === undefined && task.duration !== undefined) {\n task.end = task._start;\n let durations = task.duration.split(\" \");\n\n durations.forEach((tmpDuration) => {\n let { duration, scale } = date_utils.parse_duration(tmpDuration);\n task.end = date_utils.add(task.end, duration, scale);\n });\n }\n task._end = date_utils.parse(task.end);\n\n // make task invalid if duration too large\n if (date_utils.diff(task._end, task._start, \"year\") > 10) {\n task.end = null;\n }\n\n // cache index\n task._index = i;\n\n // invalid dates\n if (!task.start && !task.end) {\n const today = date_utils.today();\n task._start = today;\n task._end = date_utils.add(today, 2, \"day\");\n }\n\n if (!task.start && task.end) {\n task._start = date_utils.add(task._end, -2, \"day\");\n }\n\n if (task.start && !task.end) {\n task._end = date_utils.add(task._start, 2, \"day\");\n }\n\n // if hours is not set, assume the last day is full day\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\n const task_end_values = date_utils.get_date_values(task._end);\n if (task_end_values.slice(3).every((d) => d === 0)) {\n task._end = date_utils.add(task._end, 24, \"hour\");\n }\n\n // invalid flag\n if (!task.start || !task.end) {\n task.invalid = true;\n }\n\n // dependencies\n if (typeof task.dependencies === \"string\" || !task.dependencies) {\n let deps = [];\n if (task.dependencies) {\n deps = task.dependencies\n .split(\",\")\n .map((d) => d.trim())\n .filter((d) => d);\n }\n task.dependencies = deps;\n }\n\n // uids\n if (!task.id) {\n task.id = generate_id(task);\n }\n\n return task;\n });\n\n this.setup_dependencies();\n }\n\n setup_dependencies() {\n this.dependency_map = {};\n for (let t of this.tasks) {\n for (let d of t.dependencies) {\n this.dependency_map[d] = this.dependency_map[d] || [];\n this.dependency_map[d].push(t.id);\n }\n }\n }\n\n refresh(tasks) {\n this.setup_tasks(tasks);\n this.change_view_mode();\n }\n\n change_view_mode(mode = this.options.view_mode) {\n this.update_view_scale(mode);\n this.setup_dates();\n this.render();\n // fire viewmode_change event\n this.trigger_event(\"view_change\", [mode]);\n }\n\n update_view_scale(view_mode) {\n this.options.view_mode = view_mode;\n if (view_mode === VIEW_MODE.HOUR) {\n this.options.step = 24 / 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.DAY) {\n this.options.step = 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\n this.options.step = 24 / 2;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\n this.options.step = 24 / 4;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.WEEK) {\n this.options.step = 24 * 7;\n this.options.column_width = 140;\n } else if (view_mode === VIEW_MODE.MONTH) {\n this.options.step = 24 * 30;\n this.options.column_width = 120;\n } else if (view_mode === VIEW_MODE.YEAR) {\n this.options.step = 24 * 365;\n this.options.column_width = 120;\n }\n }\n\n setup_dates() {\n this.setup_gantt_dates();\n this.setup_date_values();\n }\n\n setup_gantt_dates() {\n this.gantt_start = this.gantt_end = null;\n\n for (let task of this.tasks) {\n // set global start and end date\n if (!this.gantt_start || task._start < this.gantt_start) {\n this.gantt_start = task._start;\n }\n if (!this.gantt_end || task._end > this.gantt_end) {\n this.gantt_end = task._end;\n }\n }\n\n let gantt_start = date_utils.start_of(this.gantt_start, \"day\");\n let gantt_end = date_utils.start_of(this.gantt_end, \"day\");\n // add date padding on both sides\n let viewKey;\n for (let [key, value] of Object.entries(VIEW_MODE)) {\n if (value === this.options.view_mode) {\n viewKey = key;\n }\n }\n const [padding_start, padding_end] = this.options.view_mode_padding[\n viewKey\n ].map(date_utils.parse_duration);\n this.gantt_start = date_utils.add(\n gantt_start,\n -padding_start.duration,\n padding_start.scale,\n );\n this.gantt_end = date_utils.add(\n gantt_end,\n padding_end.duration,\n padding_end.scale,\n );\n }\n\n setup_date_values() {\n this.dates = [];\n let cur_date = null;\n\n while (cur_date === null || cur_date < this.gantt_end) {\n if (!cur_date) {\n cur_date = date_utils.clone(this.gantt_start);\n } else {\n if (this.view_is(VIEW_MODE.YEAR)) {\n cur_date = date_utils.add(cur_date, 1, \"year\");\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n cur_date = date_utils.add(cur_date, 1, \"month\");\n } else {\n cur_date = date_utils.add(cur_date, this.options.step, \"hour\");\n }\n }\n this.dates.push(cur_date);\n }\n }\n\n bind_events() {\n this.bind_grid_click();\n this.bind_bar_events();\n }\n\n render() {\n this.clear();\n this.setup_layers();\n this.make_grid();\n this.make_dates();\n this.make_bars();\n this.make_arrows();\n this.map_arrows_on_bars();\n this.set_width();\n this.set_scroll_position();\n }\n\n setup_layers() {\n this.layers = {};\n const layers = [\"grid\", \"date\", \"arrow\", \"progress\", \"bar\", \"details\"];\n // make group layers\n for (let layer of layers) {\n this.layers[layer] = createSVG(\"g\", {\n class: layer,\n append_to: this.$svg,\n });\n }\n }\n\n make_grid() {\n this.make_grid_background();\n this.make_grid_rows();\n this.make_grid_header();\n this.make_grid_ticks();\n this.make_grid_highlights();\n }\n\n make_grid_background() {\n const grid_width = this.dates.length * this.options.column_width;\n const grid_height =\n this.options.header_height +\n this.options.padding +\n (this.options.bar_height + this.options.padding) * this.tasks.length;\n\n createSVG(\"rect\", {\n x: 0,\n y: 0,\n width: grid_width,\n height: grid_height,\n class: \"grid-background\",\n append_to: this.layers.grid,\n });\n\n $.attr(this.$svg, {\n height: grid_height + this.options.padding + 100,\n width: \"100%\",\n });\n }\n\n make_grid_rows() {\n const rows_layer = createSVG(\"g\", { append_to: this.layers.grid });\n const lines_layer = createSVG(\"g\", { append_to: this.layers.grid });\n\n const row_width = this.dates.length * this.options.column_width;\n const row_height = this.options.bar_height + this.options.padding;\n\n let row_y = this.options.header_height + this.options.padding / 2;\n\n for (let task of this.tasks) {\n createSVG(\"rect\", {\n x: 0,\n y: row_y,\n width: row_width,\n height: row_height,\n class: \"grid-row\",\n append_to: rows_layer,\n });\n\n createSVG(\"line\", {\n x1: 0,\n y1: row_y + row_height,\n x2: row_width,\n y2: row_y + row_height,\n class: \"row-line\",\n append_to: lines_layer,\n });\n\n row_y += this.options.bar_height + this.options.padding;\n }\n }\n\n make_grid_header() {\n const header_width = this.dates.length * this.options.column_width;\n const header_height = this.options.header_height + 10;\n createSVG(\"rect\", {\n x: 0,\n y: 0,\n width: header_width,\n height: header_height,\n class: \"grid-header\",\n append_to: this.layers.grid,\n });\n }\n\n make_grid_ticks() {\n let tick_x = 0;\n let tick_y = this.options.header_height + this.options.padding / 2;\n let tick_height =\n (this.options.bar_height + this.options.padding) * this.tasks.length;\n\n for (let date of this.dates) {\n let tick_class = \"tick\";\n // thick tick for monday\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\n tick_class += \" thick\";\n }\n // thick tick for first week\n if (\n this.view_is(VIEW_MODE.WEEK) &&\n date.getDate() >= 1 &&\n date.getDate() < 8\n ) {\n tick_class += \" thick\";\n }\n // thick ticks for quarters\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\n tick_class += \" thick\";\n }\n\n createSVG(\"path\", {\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\n class: tick_class,\n append_to: this.layers.grid,\n });\n\n if (this.view_is(VIEW_MODE.MONTH)) {\n tick_x +=\n (date_utils.get_days_in_month(date) * this.options.column_width) / 30;\n } else {\n tick_x += this.options.column_width;\n }\n }\n }\n\n //compute the horizontal x distance\n computeGridHighlightDimensions(view_mode) {\n let xDist = 0;\n\n if (this.view_is(VIEW_MODE.DAY)) {\n return (\n (date_utils.diff(date_utils.today(), this.gantt_start, \"hour\") /\n this.options.step) *\n this.options.column_width\n );\n }\n\n for (let date of this.dates) {\n const todayDate = new Date();\n const startDate = new Date(date);\n const endDate = new Date(date);\n switch (view_mode) {\n case VIEW_MODE.WEEK:\n endDate.setDate(date.getDate() + 7);\n break;\n case VIEW_MODE.MONTH:\n endDate.setMonth(date.getMonth() + 1);\n break;\n case VIEW_MODE.YEAR:\n endDate.setFullYear(date.getFullYear() + 1);\n break;\n }\n if (todayDate >= startDate && todayDate <= endDate) {\n break;\n } else {\n xDist += this.options.column_width;\n }\n }\n return xDist;\n }\n\n make_grid_highlights() {\n // highlight today's | week's | month's | year's\n if (\n this.view_is(VIEW_MODE.DAY) ||\n this.view_is(VIEW_MODE.WEEK) ||\n this.view_is(VIEW_MODE.MONTH) ||\n this.view_is(VIEW_MODE.YEAR)\n ) {\n const x = this.computeGridHighlightDimensions(this.options.view_mode);\n const y = 0;\n const width = this.options.column_width;\n const height =\n (this.options.bar_height + this.options.padding) * this.tasks.length +\n this.options.header_height +\n this.options.padding / 2;\n\n let className = \"\";\n switch (this.options.view_mode) {\n case VIEW_MODE.DAY:\n className = \"today-highlight\";\n break;\n case VIEW_MODE.WEEK:\n className = \"week-highlight\";\n break;\n case VIEW_MODE.MONTH:\n className = \"month-highlight\";\n break;\n case VIEW_MODE.YEAR:\n className = \"year-highlight\";\n break;\n }\n createSVG(\"rect\", {\n x,\n y,\n width,\n height,\n class: className,\n append_to: this.layers.grid,\n });\n }\n }\n\n make_dates() {\n for (let date of this.get_dates_to_draw()) {\n createSVG(\"text\", {\n x: date.lower_x,\n y: date.lower_y,\n innerHTML: date.lower_text,\n class: \"lower-text\",\n append_to: this.layers.date,\n });\n\n if (date.upper_text) {\n const $upper_text = createSVG(\"text\", {\n x: date.upper_x,\n y: date.upper_y,\n innerHTML: date.upper_text,\n class: \"upper-text\",\n append_to: this.layers.date,\n });\n\n // remove out-of-bound dates\n if ($upper_text.getBBox().x2 > this.layers.grid.getBBox().width) {\n $upper_text.remove();\n }\n }\n }\n }\n\n get_dates_to_draw() {\n let last_date = null;\n const dates = this.dates.map((date, i) => {\n const d = this.get_date_info(date, last_date, i);\n last_date = date;\n return d;\n });\n return dates;\n }\n\n get_date_info(date, last_date, i) {\n if (!last_date) {\n last_date = date_utils.add(date, 1, \"day\");\n }\n const date_text = {\n Hour_lower: date_utils.format(date, \"HH\", this.options.language),\n \"Quarter Day_lower\": date_utils.format(date, \"HH\", this.options.language),\n \"Half Day_lower\": date_utils.format(date, \"HH\", this.options.language),\n Day_lower:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D\", this.options.language)\n : \"\",\n Week_lower:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : date_utils.format(date, \"D\", this.options.language),\n Month_lower: date_utils.format(date, \"MMMM\", this.options.language),\n Year_lower: date_utils.format(date, \"YYYY\", this.options.language),\n Hour_upper:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D MMMM\", this.options.language)\n : \"\",\n \"Quarter Day_upper\":\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : \"\",\n \"Half Day_upper\":\n date.getDate() !== last_date.getDate()\n ? date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : date_utils.format(date, \"D\", this.options.language)\n : \"\",\n Day_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"MMMM\", this.options.language)\n : \"\",\n Week_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"MMMM\", this.options.language)\n : \"\",\n Month_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, \"YYYY\", this.options.language)\n : \"\",\n Year_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, \"YYYY\", this.options.language)\n : \"\",\n };\n\n const base_pos = {\n x: i * this.options.column_width,\n lower_y: this.options.header_height,\n upper_y: this.options.header_height - 25,\n };\n\n const x_pos = {\n Hour_lower: this.options.column_width / 2,\n Hour_upper: this.options.column_width * 12,\n \"Quarter Day_lower\": this.options.column_width / 2,\n \"Quarter Day_upper\": this.options.column_width * 2,\n \"Half Day_lower\": this.options.column_width / 2,\n \"Half Day_upper\": this.options.column_width,\n Day_lower: this.options.column_width / 2,\n Day_upper: (this.options.column_width * 30) / 2,\n Week_lower: 0,\n Week_upper: (this.options.column_width * 4) / 2,\n Month_lower: this.options.column_width / 2,\n Month_upper: (this.options.column_width * 12) / 2,\n Year_lower: this.options.column_width / 2,\n Year_upper: (this.options.column_width * 30) / 2,\n };\n\n return {\n upper_text: date_text[`${this.options.view_mode}_upper`],\n lower_text: date_text[`${this.options.view_mode}_lower`],\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\n upper_y: base_pos.upper_y,\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\n lower_y: base_pos.lower_y,\n };\n }\n\n make_bars() {\n this.bars = this.tasks.map((task) => {\n const bar = new Bar(this, task);\n this.layers.bar.appendChild(bar.group);\n return bar;\n });\n }\n\n make_arrows() {\n this.arrows = [];\n for (let task of this.tasks) {\n let arrows = [];\n arrows = task.dependencies\n .map((task_id) => {\n const dependency = this.get_task(task_id);\n if (!dependency) return;\n const arrow = new Arrow(\n this,\n this.bars[dependency._index], // from_task\n this.bars[task._index], // to_task\n );\n this.layers.arrow.appendChild(arrow.element);\n return arrow;\n })\n .filter(Boolean); // filter falsy values\n this.arrows = this.arrows.concat(arrows);\n }\n }\n\n map_arrows_on_bars() {\n for (let bar of this.bars) {\n bar.arrows = this.arrows.filter((arrow) => {\n return (\n arrow.from_task.task.id === bar.task.id ||\n arrow.to_task.task.id === bar.task.id\n );\n });\n }\n }\n\n set_width() {\n const cur_width = this.$svg.getBoundingClientRect().width;\n const actual_width = this.$svg\n .querySelector(\".grid .grid-row\")\n .getAttribute(\"width\");\n if (cur_width < actual_width) {\n this.$svg.setAttribute(\"width\", actual_width);\n }\n }\n\n set_scroll_position() {\n const parent_element = this.$svg.parentElement;\n if (!parent_element) return;\n\n const hours_before_first_task = date_utils.diff(\n this.get_oldest_starting_date(),\n this.gantt_start,\n \"hour\",\n );\n\n const scroll_pos =\n (hours_before_first_task / this.options.step) *\n this.options.column_width -\n this.options.column_width;\n\n parent_element.scrollLeft = scroll_pos;\n }\n\n bind_grid_click() {\n $.on(\n this.$svg,\n this.options.popup_trigger,\n \".grid-row, .grid-header\",\n () => {\n this.unselect_all();\n this.hide_popup();\n },\n );\n }\n\n bind_bar_events() {\n let is_dragging = false;\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing_left = false;\n let is_resizing_right = false;\n let parent_bar_id = null;\n let bars = []; // instanceof Bar\n this.bar_being_dragged = null;\n\n function action_in_progress() {\n return is_dragging || is_resizing_left || is_resizing_right;\n }\n\n $.on(this.$svg, \"mousedown\", \".bar-wrapper, .handle\", (e, element) => {\n const bar_wrapper = $.closest(\".bar-wrapper\", element);\n\n if (element.classList.contains(\"left\")) {\n is_resizing_left = true;\n } else if (element.classList.contains(\"right\")) {\n is_resizing_right = true;\n } else if (element.classList.contains(\"bar-wrapper\")) {\n is_dragging = true;\n }\n\n bar_wrapper.classList.add(\"active\");\n\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n parent_bar_id = bar_wrapper.getAttribute(\"data-id\");\n const ids = [\n parent_bar_id,\n ...this.get_all_dependent_tasks(parent_bar_id),\n ];\n bars = ids.map((id) => this.get_bar(id));\n\n this.bar_being_dragged = parent_bar_id;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.ox = $bar.getX();\n $bar.oy = $bar.getY();\n $bar.owidth = $bar.getWidth();\n $bar.finaldx = 0;\n });\n });\n\n $.on(this.$svg, \"mousemove\", (e) => {\n if (!action_in_progress()) return;\n const dx = e.offsetX - x_on_start;\n const dy = e.offsetY - y_on_start;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.finaldx = this.get_snap_position(dx);\n this.hide_popup();\n if (is_resizing_left) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n width: $bar.owidth - $bar.finaldx,\n });\n } else {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n });\n }\n } else if (is_resizing_right) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n width: $bar.owidth + $bar.finaldx,\n });\n }\n } else if (is_dragging) {\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\n }\n });\n });\n\n document.addEventListener(\"mouseup\", (e) => {\n if (is_dragging || is_resizing_left || is_resizing_right) {\n bars.forEach((bar) => bar.group.classList.remove(\"active\"));\n }\n\n is_dragging = false;\n is_resizing_left = false;\n is_resizing_right = false;\n });\n\n $.on(this.$svg, \"mouseup\", (e) => {\n this.bar_being_dragged = null;\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n if (!$bar.finaldx) return;\n bar.date_changed();\n bar.set_action_completed();\n });\n });\n\n this.bind_bar_progress();\n }\n\n bind_bar_progress() {\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing = null;\n let bar = null;\n let $bar_progress = null;\n let $bar = null;\n\n $.on(this.$svg, \"mousedown\", \".handle.progress\", (e, handle) => {\n is_resizing = true;\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n const $bar_wrapper = $.closest(\".bar-wrapper\", handle);\n const id = $bar_wrapper.getAttribute(\"data-id\");\n bar = this.get_bar(id);\n\n $bar_progress = bar.$bar_progress;\n $bar = bar.$bar;\n\n $bar_progress.finaldx = 0;\n $bar_progress.owidth = $bar_progress.getWidth();\n $bar_progress.min_dx = -$bar_progress.getWidth();\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\n });\n\n $.on(this.$svg, \"mousemove\", (e) => {\n if (!is_resizing) return;\n let dx = e.offsetX - x_on_start;\n let dy = e.offsetY - y_on_start;\n\n if (dx > $bar_progress.max_dx) {\n dx = $bar_progress.max_dx;\n }\n if (dx < $bar_progress.min_dx) {\n dx = $bar_progress.min_dx;\n }\n\n const $handle = bar.$handle_progress;\n $.attr($bar_progress, \"width\", $bar_progress.owidth + dx);\n $.attr($handle, \"points\", bar.get_progress_polygon_points());\n $bar_progress.finaldx = dx;\n });\n\n $.on(this.$svg, \"mouseup\", () => {\n is_resizing = false;\n if (!($bar_progress && $bar_progress.finaldx)) return;\n bar.progress_changed();\n bar.set_action_completed();\n });\n }\n\n get_all_dependent_tasks(task_id) {\n let out = [];\n let to_process = [task_id];\n while (to_process.length) {\n const deps = to_process.reduce((acc, curr) => {\n acc = acc.concat(this.dependency_map[curr]);\n return acc;\n }, []);\n\n out = out.concat(deps);\n to_process = deps.filter((d) => !to_process.includes(d));\n }\n\n return out.filter(Boolean);\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.view_is(VIEW_MODE.WEEK)) {\n rem = dx % (this.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 14\n ? 0\n : this.options.column_width / 7);\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n rem = dx % (this.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 60\n ? 0\n : this.options.column_width / 30);\n } else {\n rem = dx % this.options.column_width;\n position =\n odx -\n rem +\n (rem < this.options.column_width / 2 ? 0 : this.options.column_width);\n }\n return position;\n }\n\n unselect_all() {\n [...this.$svg.querySelectorAll(\".bar-wrapper\")].forEach((el) => {\n el.classList.remove(\"active\");\n });\n }\n\n view_is(modes) {\n if (typeof modes === \"string\") {\n return this.options.view_mode === modes;\n }\n\n if (Array.isArray(modes)) {\n return modes.some((mode) => this.options.view_mode === mode);\n }\n\n return false;\n }\n\n get_task(id) {\n return this.tasks.find((task) => {\n return task.id === id;\n });\n }\n\n get_bar(id) {\n return this.bars.find((bar) => {\n return bar.task.id === id;\n });\n }\n\n show_popup(options) {\n if (!this.popup) {\n this.popup = new Popup(\n this.popup_wrapper,\n this.options.custom_popup_html,\n );\n }\n this.popup.show(options);\n }\n\n hide_popup() {\n this.popup && this.popup.hide();\n }\n\n trigger_event(event, args) {\n if (this.options[\"on_\" + event]) {\n this.options[\"on_\" + event].apply(null, args);\n }\n }\n\n /**\n * Gets the oldest starting date from the list of tasks\n *\n * @returns Date\n * @memberof Gantt\n */\n get_oldest_starting_date() {\n return this.tasks\n .map((task) => task._start)\n .reduce((prev_date, cur_date) =>\n cur_date <= prev_date ? cur_date : prev_date,\n );\n }\n\n /**\n * Clear all elements from the parent svg element\n *\n * @memberof Gantt\n */\n clear() {\n this.$svg.innerHTML = \"\";\n }\n}\n\nGantt.VIEW_MODE = VIEW_MODE;\n\nfunction generate_id(task) {\n return task.name + \"_\" + Math.random().toString(36).slice(2, 12);\n}\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/frappe-gantt.min.css b/dist/frappe-gantt.min.css index 9ae6319..a1b7e36 100644 --- a/dist/frappe-gantt.min.css +++ b/dist/frappe-gantt.min.css @@ -1 +1 @@ -.dark>.gantt-container .gantt .grid-header{fill:#252525;stroke:#616161}.dark>.gantt-container .gantt .grid-row{fill:#252525}.dark>.gantt-container .gantt .grid-row:nth-child(even){fill:#3e3e3e}.dark>.gantt-container .gantt .row-line{stroke:#3e3e3e}.dark>.gantt-container .gantt .tick{stroke:#616161}.dark>.gantt-container .gantt .today-highlight{opacity:.2}.dark>.gantt-container .gantt .arrow{stroke:#eee}.dark>.gantt-container .gantt .bar{fill:#616161;stroke:none}.dark>.gantt-container .gantt .bar-progress{fill:#8a8aff}.dark>.gantt-container .gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#c6ccd2}.dark>.gantt-container .gantt .bar-invalid~.bar-label{fill:#ececec}.dark>.gantt-container .gantt .bar-label.big{fill:#ececec}.dark>.gantt-container .gantt .bar-wrapper:hover .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper:hover .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .bar-wrapper.active .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper.active .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .upper-text{fill:#a2a2a2}.dark>.gantt-container .gantt .lower-text{fill:#f7f7f7}.dark>.gantt-container .popup-wrapper{background-color:#333}.dark>.gantt-container .popup-wrapper .title{border-color:#a4a4ff}.dark>.gantt-container .popup-wrapper .pointer{border-top-color:#333}.gantt .grid-background{fill:none}.gantt .grid-header{fill:#fff;stroke:#e0e0e0;stroke-width:1.4}.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(even){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke-width:.4}.gantt .today-highlight{fill:#fcf8e3;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{fill:#b8c2cc;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease;user-select:none}.gantt .bar-progress{fill:#a3a3ff}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#8d99a6;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;dominant-baseline:central;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .handle{fill:#ddd;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar{fill:#a9b5c1}.gantt .bar-wrapper:hover .bar-progress{fill:#8a8aff}.gantt .bar-wrapper:hover .handle{visibility:visible;opacity:1}.gantt .bar-wrapper.active .bar{fill:#a9b5c1}.gantt .bar-wrapper.active .bar-progress{fill:#8a8aff}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:rgba(0,0,0,.8);padding:0;color:#959da5;border-radius:3px}.gantt-container .popup-wrapper .title{border-bottom:3px solid #a3a3ff;padding:10px}.gantt-container .popup-wrapper .subtitle{padding:10px;color:#dfe2e5}.gantt-container .popup-wrapper .pointer{position:absolute;height:5px;margin:0 0 0 -5px;border:5px solid rgba(0,0,0,0);border-top-color:rgba(0,0,0,.8)} \ No newline at end of file +.dark>.gantt-container .gantt .grid-header{fill:#252525;stroke:#616161}.dark>.gantt-container .gantt .grid-row{fill:#252525}.dark>.gantt-container .gantt .grid-row:nth-child(even){fill:#3e3e3e}.dark>.gantt-container .gantt .row-line{stroke:#3e3e3e}.dark>.gantt-container .gantt .tick{stroke:#616161}.dark>.gantt-container .gantt .today-highlight{opacity:.2}.dark>.gantt-container .gantt .arrow{stroke:#eee}.dark>.gantt-container .gantt .bar{fill:#616161;stroke:none}.dark>.gantt-container .gantt .bar-progress{fill:#8a8aff}.dark>.gantt-container .gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#c6ccd2}.dark>.gantt-container .gantt .bar-invalid~.bar-label{fill:#ececec}.dark>.gantt-container .gantt .bar-label.big{fill:#ececec}.dark>.gantt-container .gantt .bar-wrapper:hover .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper:hover .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .bar-wrapper.active .bar{fill:#6e6e6e}.dark>.gantt-container .gantt .bar-wrapper.active .bar-progress{fill:#a4a4ff}.dark>.gantt-container .gantt .upper-text{fill:#a2a2a2}.dark>.gantt-container .gantt .lower-text{fill:#f7f7f7}.dark>.gantt-container .popup-wrapper{background-color:#333}.dark>.gantt-container .popup-wrapper .title{border-color:#a4a4ff}.dark>.gantt-container .popup-wrapper .pointer{border-top-color:#333}.gantt{user-select:none;-webkit-user-select:none}.gantt .grid-background{fill:none}.gantt .grid-header{fill:#fff;stroke:#e0e0e0;stroke-width:1.4}.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(even){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.2}.gantt .tick.thick{stroke-width:.4}.gantt .today-highlight{fill:#fcf8e3;opacity:.5}.gantt .week-highlight{fill:#fcf8e3;opacity:.5}.gantt .month-highlight{fill:#fcf8e3;opacity:.5}.gantt .year-highlight{fill:#fcf8e3;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{fill:#b8c2cc;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-progress{fill:#acacfa}.gantt .bar-expected-progress{fill:#c4c4e9}.gantt .bar-invalid{fill:rgba(0,0,0,0);stroke:#8d99a6;stroke-width:1;stroke-dasharray:5}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;dominant-baseline:central;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .handle{fill:#ddd;cursor:ew-resize;opacity:0;visibility:hidden;transition:opacity .3s ease}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar{fill:#a9b5c1}.gantt .bar-wrapper:hover .bar-progress{fill:#9494f9}.gantt .bar-wrapper:hover .handle{visibility:visible;opacity:1}.gantt .bar-wrapper.active .bar{fill:#a9b5c1}.gantt .bar-wrapper.active .bar-progress{fill:#9494f9}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{position:relative;overflow:auto;font-size:12px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:rgba(0,0,0,.8);padding:0;color:#959da5;border-radius:3px}.gantt-container .popup-wrapper .title{border-bottom:3px solid #acacfa;padding:10px}.gantt-container .popup-wrapper .subtitle{padding:10px;color:#dfe2e5}.gantt-container .popup-wrapper .pointer{position:absolute;height:5px;margin:0 0 0 -5px;border:5px solid rgba(0,0,0,0);border-top-color:rgba(0,0,0,.8)} \ No newline at end of file diff --git a/dist/frappe-gantt.min.js b/dist/frappe-gantt.min.js index 3c05faa..4fbfc0b 100644 --- a/dist/frappe-gantt.min.js +++ b/dist/frappe-gantt.min.js @@ -1,2 +1,2 @@ -var Gantt=function(){"use strict";const t="year",e="month",s="day",i="hour",n="minute",a="second",o="millisecond";var r={parse(t,e="-",s=/[.:]/){if(t instanceof Date)return t;if("string"==typeof t){let i,n;const a=t.split(" ");i=a[0].split(e).map((t=>parseInt(t,10))),n=a[1]&&a[1].split(s),i[1]=i[1]-1;let o=i;return n&&n.length&&(4==n.length&&(n[3]="0."+n[3],n[3]=1e3*parseFloat(n[3])),o=o.concat(n)),new Date(...o)}},to_string(t,e=!1){if(!(t instanceof Date))throw new TypeError("Invalid argument type");const s=this.get_date_values(t).map(((t,e)=>(1===e&&(t+=1),h(t+"",6===e?3:2,"0")))),i=`${s[0]}-${s[1]}-${s[2]}`,n=`${s[3]}:${s[4]}:${s[5]}.${s[6]}`;return i+(e?" "+n:"")},format(t,e="YYYY-MM-DD HH:mm:ss.SSS",s="en"){const i=new Intl.DateTimeFormat(s,{month:"long"}).format(t),n=i.charAt(0).toUpperCase()+i.slice(1),a=this.get_date_values(t).map((t=>h(t,2,0))),o={YYYY:a[0],MM:h(+a[1]+1,2,0),DD:a[2],HH:a[3],mm:a[4],ss:a[5],SSS:a[6],D:a[2],MMMM:n,MMM:n};let r=e;const p=[];return Object.keys(o).sort(((t,e)=>e.length-t.length)).forEach((t=>{r.includes(t)&&(r=r.replace(t,`$${p.length}`),p.push(o[t]))})),p.forEach(((t,e)=>{r=r.replace(`$${e}`,t)})),r},diff(t,e,i=s){let n,a,o,r,h,p,d;return n=t-e,a=n/1e3,r=a/60,o=r/60,h=o/24,p=h/30,d=p/12,i.endsWith("s")||(i+="s"),Math.floor({milliseconds:n,seconds:a,minutes:r,hours:o,days:h,months:p,years:d}[i])},today(){const t=this.get_date_values(new Date).slice(0,3);return new Date(...t)},now:()=>new Date,add(r,h,p){h=parseInt(h,10);const d=[r.getFullYear()+(p===t?h:0),r.getMonth()+(p===e?h:0),r.getDate()+(p===s?h:0),r.getHours()+(p===i?h:0),r.getMinutes()+(p===n?h:0),r.getSeconds()+(p===a?h:0),r.getMilliseconds()+(p===o?h:0)];return new Date(...d)},start_of(r,h){const p={[t]:6,[e]:5,[s]:4,[i]:3,[n]:2,[a]:1,[o]:0};function d(t){return p[t]<=p[h]}const _=[r.getFullYear(),d(t)?0:r.getMonth(),d(e)?1:r.getDate(),d(s)?0:r.getHours(),d(i)?0:r.getMinutes(),d(n)?0:r.getSeconds(),d(a)?0:r.getMilliseconds()];return new Date(..._)},clone(t){return new Date(...this.get_date_values(t))},get_date_values:t=>[t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()],get_days_in_month(t){const e=[31,28,31,30,31,30,31,31,30,31,30,31],s=t.getMonth();if(1!==s)return e[s];const i=t.getFullYear();return i%4==0&&i%100!=0||i%400==0?29:28}};function h(t,e,s){return t+="",e>>=0,s=String(void 0!==s?s:" "),t.length>e?String(t):((e-=t.length)>s.length&&(s+=s.repeat(e/s.length)),s.slice(0,e)+String(t))}function p(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function d(t,e){const s=document.createElementNS("http://www.w3.org/2000/svg",t);for(let t in e)if("append_to"===t){e.append_to.appendChild(s)}else"innerHTML"===t?s.innerHTML=e.innerHTML:s.setAttribute(t,e[t]);return s}function _(t,e,s,i){const n=function(t,e,s,i,n="0.4s",a="0.1s"){const o=t.querySelector("animate");if(o)return p.attr(o,{attributeName:e,from:s,to:i,dur:n,begin:"click + "+a}),t;const r=d("animate",{attributeName:e,from:s,to:i,dur:n,begin:a,calcMode:"spline",values:s+";"+i,keyTimes:"0; 1",keySplines:g("ease-out")});return t.appendChild(r),t}(t,e,s,i);if(n===t){const t=document.createEvent("HTMLEvents");t.initEvent("click",!0,!0),t.eventName="click",n.dispatchEvent(t)}}function g(t){return{ease:".25 .1 .25 1",linear:"0 0 1 1","ease-in":".42 0 1 1","ease-out":"0 0 .58 1","ease-in-out":".42 0 .58 1"}[t]}p.on=(t,e,s,i)=>{i?p.delegate(t,e,s,i):(i=s,p.bind(t,e,i))},p.off=(t,e,s)=>{t.removeEventListener(e,s)},p.bind=(t,e,s)=>{e.split(/\s+/).forEach((function(e){t.addEventListener(e,s)}))},p.delegate=(t,e,s,i)=>{t.addEventListener(e,(function(t){const e=t.target.closest(s);e&&(t.delegatedTarget=e,i.call(this,t,e))}))},p.closest=(t,e)=>e?e.matches(t)?e:p.closest(t,e.parentNode):null,p.attr=(t,e,s)=>{if(!s&&"string"==typeof e)return t.getAttribute(e);if("object"!=typeof e)t.setAttribute(e,s);else for(let s in e)p.attr(t,s,e[s])};class l{constructor(t,e){this.set_defaults(t,e),this.prepare(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e}prepare(){this.prepare_values(),this.prepare_helpers()}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.options.column_width*this.duration,this.progress_width=this.gantt.options.column_width*this.duration*(this.task.progress/100)||0,this.group=d("g",{class:"bar-wrapper "+(this.task.custom_class||""),"data-id":this.task.id}),this.bar_group=d("g",{class:"bar-group",append_to:this.group}),this.handle_group=d("g",{class:"handle-group",append_to:this.group})}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_progress_bar(),this.draw_label(),this.draw_resize_handles()}draw_bar(){this.$bar=d("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),_(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=d("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),_(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){this.invalid||(this.$bar_progress=d("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-progress",append_to:this.bar_group}),_(this.$bar_progress,"width",0,this.progress_width))}draw_label(){d("text",{x:this.x+this.width/2,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame((()=>this.update_label_position()))}draw_resize_handles(){if(this.invalid)return;const t=this.$bar;d("rect",{x:t.getX()+t.getWidth()-9,y:t.getY()+1,width:8,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle right",append_to:this.handle_group}),d("rect",{x:t.getX()+1,y:t.getY()+1,width:8,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle left",append_to:this.handle_group}),this.task.progress&&this.task.progress<100&&(this.$handle_progress=d("polygon",{points:this.get_progress_polygon_points().join(","),class:"handle progress",append_to:this.handle_group}))}get_progress_polygon_points(){const t=this.$bar_progress;return[t.getEndX()-5,t.getY()+t.getHeight(),t.getEndX()+5,t.getY()+t.getHeight(),t.getEndX(),t.getY()+t.getHeight()-8.66]}bind(){this.invalid||this.setup_click_event()}setup_click_event(){p.on(this.group,"focus "+this.gantt.options.popup_trigger,(t=>{this.action_completed||(this.show_popup(),this.gantt.unselect_all(),this.group.classList.add("active"))})),p.on(this.group,"dblclick",(t=>{this.action_completed||this.gantt.trigger_event("click",[this.task])}))}show_popup(){if(this.gantt.bar_being_dragged)return;const t=r.format(this.task._start,"MMM D",this.gantt.options.language)+" - "+r.format(r.add(this.task._end,-1,"second"),"MMM D",this.gantt.options.language);this.gantt.show_popup({target_element:this.$bar,title:this.task.name,subtitle:t,task:this.task})}update_bar_position({x:t=null,width:e=null}){const s=this.$bar;if(t){if(!this.task.dependencies.map((t=>this.gantt.get_bar(t).$bar.getX())).reduce(((e,s)=>t>=s),t))return void(e=null);this.update_attr(s,"x",t)}e&&e>=this.gantt.options.column_width&&this.update_attr(s,"width",e),this.update_label_position(),this.update_handle_position(),this.gantt.options.show_expected_progress&&(this.date_changed(),this.compute_duration(),this.update_expected_progressbar_position()),this.update_progressbar_position(),this.update_arrow_position()}date_changed(){let t=!1;const{new_start_date:e,new_end_date:s}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(s)&&(t=!0,this.task._end=s),t&&this.gantt.trigger_event("date_change",[this.task,e,r.add(s,-1,"second")])}progress_changed(){const t=this.compute_progress();this.task.progress=t,this.gantt.trigger_event("progress_change",[this.task,t])}set_action_completed(){this.action_completed=!0,setTimeout((()=>this.action_completed=!1),1e3)}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.options.column_width,s=r.add(this.gantt.gantt_start,e*this.gantt.options.step,"hour"),i=t.getWidth()/this.gantt.options.column_width;return{new_start_date:s,new_end_date:r.add(s,i*this.gantt.options.step,"hour")}}compute_progress(){const t=this.$bar_progress.getWidth()/this.$bar.getWidth()*100;return parseInt(t,10)}compute_expected_progress(){this.expected_progress=r.diff(r.today(),this.task._start,"hour")/this.gantt.options.step,this.expected_progress=100*(this.expected_progresst.getWidth()?(e.classList.add("big"),e.setAttribute("x",t.getX()+t.getWidth()+5)):(e.classList.remove("big"),e.setAttribute("x",t.getX()+t.getWidth()/2))}update_handle_position(){if(this.invalid)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()+1),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()-9);const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("points",this.get_progress_polygon_points())}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class u{constructor(t,e,s){this.gantt=t,this.from_task=e,this.to_task=s,this.calculate_path(),this.draw()}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;const s=this.gantt.options.header_height+this.gantt.options.bar_height+(this.gantt.options.padding+this.gantt.options.bar_height)*this.from_task.task._index+this.gantt.options.padding,i=this.to_task.$bar.getX()-this.gantt.options.padding/2,n=this.gantt.options.header_height+this.gantt.options.bar_height/2+(this.gantt.options.padding+this.gantt.options.bar_height)*this.to_task.task._index+this.gantt.options.padding,a=this.from_task.task._index>this.to_task.task._index,o=this.gantt.options.arrow_curve,r=a?1:0,h=a?-o:o,p=a?n+this.gantt.options.arrow_curve:n-this.gantt.options.arrow_curve;if(this.path=`\n M ${t} ${s}\n V ${p}\n a ${o} ${o} 0 0 ${r} ${o} ${h}\n L ${i} ${n}\n m -5 -5\n l 5 5\n l -5 5`,this.to_task.$bar.getX()\n
\n
\n ',this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.pointer=this.parent.querySelector(".pointer")}show(t){if(!t.target_element)throw new Error("target_element is required to show popup");t.position||(t.position="left");const e=t.target_element;if(this.custom_html){let e=this.custom_html(t.task);e+='
',this.parent.innerHTML=e,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle,this.parent.style.width=this.parent.clientWidth+"px";let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),"left"===t.position&&(this.parent.style.left=s.x+(s.width+10)+"px",this.parent.style.top=s.y+"px",this.pointer.style.transform="rotateZ(90deg)",this.pointer.style.left="-7px",this.pointer.style.top="2px"),this.parent.style.opacity=1}hide(){this.parent.style.opacity=0,this.parent.style.left=0}}const m={QUARTER_DAY:"Quarter Day",HALF_DAY:"Half Day",DAY:"Day",WEEK:"Week",MONTH:"Month",YEAR:"Year"};class w{constructor(t,e,s){this.setup_wrapper(t),this.setup_options(s),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,s;if("string"==typeof t&&(t=document.querySelector(t)),t instanceof HTMLElement)s=t,e=t.querySelector("svg");else{if(!(t instanceof SVGElement))throw new TypeError("Frappé Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e=t}e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=d("svg",{append_to:s,class:"gantt"}),this.$container=document.createElement("div"),this.$container.classList.add("gantt-container");this.$svg.parentElement.appendChild(this.$container),this.$container.appendChild(this.$svg),this.popup_wrapper=document.createElement("div"),this.popup_wrapper.classList.add("popup-wrapper"),this.$container.appendChild(this.popup_wrapper)}setup_options(t){const e={header_height:50,column_width:30,step:24,view_modes:[...Object.values(m)],bar_height:20,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",popup_trigger:"click",custom_popup_html:null,language:"en"};this.options=Object.assign({},e,t)}setup_tasks(t){this.tasks=t.map(((t,e)=>{if(t._start=r.parse(t.start),t._end=r.parse(t.end),r.diff(t._end,t._start,"year")>10&&(t.end=null),t._index=e,!t.start&&!t.end){const e=r.today();t._start=e,t._end=r.add(e,2,"day")}!t.start&&t.end&&(t._start=r.add(t._end,-2,"day")),t.start&&!t.end&&(t._end=r.add(t._start,2,"day"));if(r.get_date_values(t._end).slice(3).every((t=>0===t))&&(t._end=r.add(t._end,24,"hour")),t.start&&t.end||(t.invalid=!0),"string"==typeof t.dependencies||!t.dependencies){let e=[];t.dependencies&&(e=t.dependencies.split(",").map((t=>t.trim())).filter((t=>t))),t.dependencies=e}return t.id||(t.id=function(t){return t.name+"_"+Math.random().toString(36).slice(2,12)}(t)),t})),this.setup_dependencies()}setup_dependencies(){this.dependency_map={};for(let t of this.tasks)for(let e of t.dependencies)this.dependency_map[e]=this.dependency_map[e]||[],this.dependency_map[e].push(t.id)}refresh(t){this.setup_tasks(t),this.change_view_mode()}change_view_mode(t=this.options.view_mode){this.update_view_scale(t),this.setup_dates(),this.render(),this.trigger_event("view_change",[t])}update_view_scale(t){this.options.view_mode=t,t===m.DAY?(this.options.step=24,this.options.column_width=38):t===m.HALF_DAY?(this.options.step=12,this.options.column_width=38):t===m.QUARTER_DAY?(this.options.step=6,this.options.column_width=38):t===m.WEEK?(this.options.step=168,this.options.column_width=140):t===m.MONTH?(this.options.step=720,this.options.column_width=120):t===m.YEAR&&(this.options.step=8760,this.options.column_width=120)}setup_dates(){this.setup_gantt_dates(),this.setup_date_values()}setup_gantt_dates(){this.gantt_start=this.gantt_end=null;for(let t of this.tasks)(!this.gantt_start||t._startthis.gantt_end)&&(this.gantt_end=t._end);this.gantt_start=r.start_of(this.gantt_start,"day"),this.gantt_end=r.start_of(this.gantt_end,"day"),this.view_is([m.QUARTER_DAY,m.HALF_DAY])?(this.gantt_start=r.add(this.gantt_start,-7,"day"),this.gantt_end=r.add(this.gantt_end,7,"day")):this.view_is(m.MONTH)?(this.gantt_start=r.start_of(this.gantt_start,"year"),this.gantt_end=r.add(this.gantt_end,1,"year")):this.view_is(m.YEAR)?(this.gantt_start=r.add(this.gantt_start,-2,"year"),this.gantt_end=r.add(this.gantt_end,2,"year")):(this.gantt_start=r.add(this.gantt_start,-1,"month"),this.gantt_end=r.add(this.gantt_end,1,"month"))}setup_date_values(){this.dates=[];let t=null;for(;null===t||t=1&&i.getDate()<8&&(n+=" thick"),this.view_is(m.MONTH)&&i.getMonth()%3==0&&(n+=" thick"),d("path",{d:`M ${t} ${e} v ${s}`,class:n,append_to:this.layers.grid}),this.view_is(m.MONTH)?t+=r.get_days_in_month(i)*this.options.column_width/30:t+=this.options.column_width}}make_grid_highlights(){if(this.view_is(m.DAY)){d("rect",{x:r.diff(r.today(),this.gantt_start,"hour")/this.options.step*this.options.column_width,y:0,width:this.options.column_width,height:(this.options.bar_height+this.options.padding)*this.tasks.length+this.options.header_height+this.options.padding/2,class:"today-highlight",append_to:this.layers.grid})}}make_dates(){for(let t of this.get_dates_to_draw())if(d("text",{x:t.lower_x,y:t.lower_y,innerHTML:t.lower_text,class:"lower-text",append_to:this.layers.date}),t.upper_text){const e=d("text",{x:t.upper_x,y:t.upper_y,innerHTML:t.upper_text,class:"upper-text",append_to:this.layers.date});e.getBBox().x2>this.layers.grid.getBBox().width&&e.remove()}}get_dates_to_draw(){let t=null;return this.dates.map(((e,s)=>{const i=this.get_date_info(e,t,s);return t=e,i}))}get_date_info(t,e,s){e||(e=r.add(t,1,"year"));const i={"Quarter Day_lower":r.format(t,"HH",this.options.language),"Half Day_lower":r.format(t,"HH",this.options.language),Day_lower:t.getDate()!==e.getDate()?r.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==e.getMonth()?r.format(t,"D MMM",this.options.language):r.format(t,"D",this.options.language),Month_lower:r.format(t,"MMMM",this.options.language),Year_lower:r.format(t,"YYYY",this.options.language),"Quarter Day_upper":t.getDate()!==e.getDate()?r.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==e.getDate()?t.getMonth()!==e.getMonth()?r.format(t,"D MMM",this.options.language):r.format(t,"D",this.options.language):"",Day_upper:t.getMonth()!==e.getMonth()?r.format(t,"MMMM",this.options.language):"",Week_upper:t.getMonth()!==e.getMonth()?r.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==e.getFullYear()?r.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==e.getFullYear()?r.format(t,"YYYY",this.options.language):""},n={x:s*this.options.column_width,lower_y:this.options.header_height,upper_y:this.options.header_height-25},a={"Quarter Day_lower":4*this.options.column_width/2,"Quarter Day_upper":0,"Half Day_lower":2*this.options.column_width/2,"Half Day_upper":0,Day_lower:this.options.column_width/2,Day_upper:30*this.options.column_width/2,Week_lower:0,Week_upper:4*this.options.column_width/2,Month_lower:this.options.column_width/2,Month_upper:12*this.options.column_width/2,Year_lower:this.options.column_width/2,Year_upper:30*this.options.column_width/2};return{upper_text:i[`${this.options.view_mode}_upper`],lower_text:i[`${this.options.view_mode}_lower`],upper_x:n.x+a[`${this.options.view_mode}_upper`],upper_y:n.upper_y,lower_x:n.x+a[`${this.options.view_mode}_lower`],lower_y:n.lower_y}}make_bars(){this.bars=this.tasks.map((t=>{const e=new l(this,t);return this.layers.bar.appendChild(e.group),e}))}make_arrows(){this.arrows=[];for(let t of this.tasks){let e=[];e=t.dependencies.map((e=>{const s=this.get_task(e);if(!s)return;const i=new u(this,this.bars[s._index],this.bars[t._index]);return this.layers.arrow.appendChild(i.element),i})).filter(Boolean),this.arrows=this.arrows.concat(e)}}map_arrows_on_bars(){for(let t of this.bars)t.arrows=this.arrows.filter((e=>e.from_task.task.id===t.task.id||e.to_task.task.id===t.task.id))}set_width(){const t=this.$svg.getBoundingClientRect().width,e=this.$svg.querySelector(".grid .grid-row").getAttribute("width");t{this.unselect_all(),this.hide_popup()}))}bind_bar_events(){let t=!1,e=0,s=0,i=!1,n=!1,a=null,o=[];this.bar_being_dragged=null,p.on(this.$svg,"mousedown",".bar-wrapper, .handle",((r,h)=>{const d=p.closest(".bar-wrapper",h);h.classList.contains("left")?i=!0:h.classList.contains("right")?n=!0:h.classList.contains("bar-wrapper")&&(t=!0),d.classList.add("active"),e=r.offsetX,s=r.offsetY,a=d.getAttribute("data-id");const _=[a,...this.get_all_dependent_tasks(a)];o=_.map((t=>this.get_bar(t))),this.bar_being_dragged=a,o.forEach((t=>{const e=t.$bar;e.ox=e.getX(),e.oy=e.getY(),e.owidth=e.getWidth(),e.finaldx=0}))})),p.on(this.$svg,"mousemove",(s=>{if(!(t||i||n))return;const r=s.offsetX-e;s.offsetY,o.forEach((e=>{const s=e.$bar;s.finaldx=this.get_snap_position(r),this.hide_popup(),i?a===e.task.id?e.update_bar_position({x:s.ox+s.finaldx,width:s.owidth-s.finaldx}):e.update_bar_position({x:s.ox+s.finaldx}):n?a===e.task.id&&e.update_bar_position({width:s.owidth+s.finaldx}):t&&e.update_bar_position({x:s.ox+s.finaldx})}))})),document.addEventListener("mouseup",(e=>{(t||i||n)&&o.forEach((t=>t.group.classList.remove("active"))),t=!1,i=!1,n=!1})),p.on(this.$svg,"mouseup",(t=>{this.bar_being_dragged=null,o.forEach((t=>{t.$bar.finaldx&&(t.date_changed(),t.set_action_completed())}))})),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=0,s=null,i=null,n=null,a=null;p.on(this.$svg,"mousedown",".handle.progress",((o,r)=>{s=!0,t=o.offsetX,e=o.offsetY;const h=p.closest(".bar-wrapper",r).getAttribute("data-id");i=this.get_bar(h),n=i.$bar_progress,a=i.$bar,n.finaldx=0,n.owidth=n.getWidth(),n.min_dx=-n.getWidth(),n.max_dx=a.getWidth()-n.getWidth()})),p.on(this.$svg,"mousemove",(e=>{if(!s)return;let a=e.offsetX-t;e.offsetY,a>n.max_dx&&(a=n.max_dx),a{s=!1,n&&n.finaldx&&(i.progress_changed(),i.set_action_completed())}))}get_all_dependent_tasks(t){let e=[],s=[t];for(;s.length;){const t=s.reduce(((t,e)=>t=t.concat(this.dependency_map[e])),[]);e=e.concat(t),s=t.filter((t=>!s.includes(t)))}return e.filter(Boolean)}get_snap_position(t){let e,s,i=t;return this.view_is(m.WEEK)?(e=t%(this.options.column_width/7),s=i-e+(e{t.classList.remove("active")}))}view_is(t){return"string"==typeof t?this.options.view_mode===t:!!Array.isArray(t)&&t.some((t=>this.options.view_mode===t))}get_task(t){return this.tasks.find((e=>e.id===t))}get_bar(t){return this.bars.find((e=>e.task.id===t))}show_popup(t){this.popup||(this.popup=new c(this.popup_wrapper,this.options.custom_popup_html)),this.popup.show(t)}hide_popup(){this.popup&&this.popup.hide()}trigger_event(t,e){this.options["on_"+t]&&this.options["on_"+t].apply(null,e)}get_oldest_starting_date(){return this.tasks.map((t=>t._start)).reduce(((t,e)=>e<=t?e:t))}clear(){this.$svg.innerHTML=""}}return w.VIEW_MODE=m,w}(); +var Gantt=function(){"use strict";const t="year",e="month",s="day",i="hour",o="minute",n="second",a="millisecond";var r={parse_duration(t){const e=/([0-9])+(y|m|d|h|min|s|ms)/gm.exec(t);if(null!==e){if("y"===e[2])return{duration:parseInt(e[1]),scale:"year"};if("m"===e[2])return{duration:parseInt(e[1]),scale:"month"};if("d"===e[2])return{duration:parseInt(e[1]),scale:"day"};if("h"===e[2])return{duration:parseInt(e[1]),scale:"hour"};if("min"===e[2])return{duration:parseInt(e[1]),scale:"minute"};if("s"===e[2])return{duration:parseInt(e[1]),scale:"second"};if("ms"===e[2])return{duration:parseInt(e[1]),scale:"millisecond"}}},parse(t,e="-",s=/[.:]/){if(t instanceof Date)return t;if("string"==typeof t){let i,o;const n=t.split(" ");i=n[0].split(e).map((t=>parseInt(t,10))),o=n[1]&&n[1].split(s),i[1]=i[1]-1;let a=i;return o&&o.length&&(4==o.length&&(o[3]="0."+o[3],o[3]=1e3*parseFloat(o[3])),a=a.concat(o)),new Date(...a)}},to_string(t,e=!1){if(!(t instanceof Date))throw new TypeError("Invalid argument type");const s=this.get_date_values(t).map(((t,e)=>(1===e&&(t+=1),h(t+"",6===e?3:2,"0")))),i=`${s[0]}-${s[1]}-${s[2]}`,o=`${s[3]}:${s[4]}:${s[5]}.${s[6]}`;return i+(e?" "+o:"")},format(t,e="YYYY-MM-DD HH:mm:ss.SSS",s="en"){const i=new Intl.DateTimeFormat(s,{month:"long"}).format(t),o=i.charAt(0).toUpperCase()+i.slice(1),n=this.get_date_values(t).map((t=>h(t,2,0))),a={YYYY:n[0],MM:h(+n[1]+1,2,0),DD:n[2],HH:n[3],mm:n[4],ss:n[5],SSS:n[6],D:n[2],MMMM:o,MMM:o};let r=e;const p=[];return Object.keys(a).sort(((t,e)=>e.length-t.length)).forEach((t=>{r.includes(t)&&(r=r.replace(t,`$${p.length}`),p.push(a[t]))})),p.forEach(((t,e)=>{r=r.replace(`$${e}`,t)})),r},diff(t,e,i=s){let o,n,a,r,h,p,d;return o=t-e,n=o/1e3,r=n/60,a=r/60,h=a/24,p=h/30,d=p/12,i.endsWith("s")||(i+="s"),Math.floor({milliseconds:o,seconds:n,minutes:r,hours:a,days:h,months:p,years:d}[i])},today(){const t=this.get_date_values(new Date).slice(0,3);return new Date(...t)},now:()=>new Date,add(r,h,p){h=parseInt(h,10);const d=[r.getFullYear()+(p===t?h:0),r.getMonth()+(p===e?h:0),r.getDate()+(p===s?h:0),r.getHours()+(p===i?h:0),r.getMinutes()+(p===o?h:0),r.getSeconds()+(p===n?h:0),r.getMilliseconds()+(p===a?h:0)];return new Date(...d)},start_of(r,h){const p={[t]:6,[e]:5,[s]:4,[i]:3,[o]:2,[n]:1,[a]:0};function d(t){return p[t]<=p[h]}const _=[r.getFullYear(),d(t)?0:r.getMonth(),d(e)?1:r.getDate(),d(s)?0:r.getHours(),d(i)?0:r.getMinutes(),d(o)?0:r.getSeconds(),d(n)?0:r.getMilliseconds()];return new Date(..._)},clone(t){return new Date(...this.get_date_values(t))},get_date_values:t=>[t.getFullYear(),t.getMonth(),t.getDate(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds()],get_days_in_month(t){const e=[31,28,31,30,31,30,31,31,30,31,30,31],s=t.getMonth();if(1!==s)return e[s];const i=t.getFullYear();return i%4==0&&i%100!=0||i%400==0?29:28}};function h(t,e,s){return t+="",e>>=0,s=String(void 0!==s?s:" "),t.length>e?String(t):((e-=t.length)>s.length&&(s+=s.repeat(e/s.length)),s.slice(0,e)+String(t))}function p(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function d(t,e){const s=document.createElementNS("http://www.w3.org/2000/svg",t);for(let t in e)if("append_to"===t){e.append_to.appendChild(s)}else"innerHTML"===t?s.innerHTML=e.innerHTML:s.setAttribute(t,e[t]);return s}function _(t,e,s,i){const o=function(t,e,s,i,o="0.4s",n="0.1s"){const a=t.querySelector("animate");if(a)return p.attr(a,{attributeName:e,from:s,to:i,dur:o,begin:"click + "+n}),t;const r=d("animate",{attributeName:e,from:s,to:i,dur:o,begin:n,calcMode:"spline",values:s+";"+i,keyTimes:"0; 1",keySplines:g("ease-out")});return t.appendChild(r),t}(t,e,s,i);if(o===t){const t=document.createEvent("HTMLEvents");t.initEvent("click",!0,!0),t.eventName="click",o.dispatchEvent(t)}}function g(t){return{ease:".25 .1 .25 1",linear:"0 0 1 1","ease-in":".42 0 1 1","ease-out":"0 0 .58 1","ease-in-out":".42 0 .58 1"}[t]}p.on=(t,e,s,i)=>{i?p.delegate(t,e,s,i):(i=s,p.bind(t,e,i))},p.off=(t,e,s)=>{t.removeEventListener(e,s)},p.bind=(t,e,s)=>{e.split(/\s+/).forEach((function(e){t.addEventListener(e,s)}))},p.delegate=(t,e,s,i)=>{t.addEventListener(e,(function(t){const e=t.target.closest(s);e&&(t.delegatedTarget=e,i.call(this,t,e))}))},p.closest=(t,e)=>e?e.matches(t)?e:p.closest(t,e.parentNode):null,p.attr=(t,e,s)=>{if(!s&&"string"==typeof e)return t.getAttribute(e);if("object"!=typeof e)t.setAttribute(e,s);else for(let s in e)p.attr(t,s,e[s])};class l{constructor(t,e){this.set_defaults(t,e),this.prepare(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e}prepare(){this.prepare_values(),this.prepare_helpers()}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.options.column_width*this.duration,this.progress_width=this.gantt.options.column_width*this.duration*(this.task.progress/100)||0,this.group=d("g",{class:"bar-wrapper "+(this.task.custom_class||""),"data-id":this.task.id}),this.bar_group=d("g",{class:"bar-group",append_to:this.group}),this.handle_group=d("g",{class:"handle-group",append_to:this.group})}prepare_helpers(){SVGElement.prototype.getX=function(){return+this.getAttribute("x")},SVGElement.prototype.getY=function(){return+this.getAttribute("y")},SVGElement.prototype.getWidth=function(){return+this.getAttribute("width")},SVGElement.prototype.getHeight=function(){return+this.getAttribute("height")},SVGElement.prototype.getEndX=function(){return this.getX()+this.getWidth()}}prepare_expected_progress_values(){this.compute_expected_progress(),this.expected_progress_width=this.gantt.options.column_width*this.duration*(this.expected_progress/100)||0}draw(){this.draw_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_progress_bar(),this.draw_label(),this.draw_resize_handles()}draw_bar(){this.$bar=d("rect",{x:this.x,y:this.y,width:this.width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar",append_to:this.bar_group}),_(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=d("rect",{x:this.x,y:this.y,width:this.expected_progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-expected-progress",append_to:this.bar_group}),_(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){this.invalid||(this.$bar_progress=d("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:this.corner_radius,ry:this.corner_radius,class:"bar-progress",append_to:this.bar_group}),_(this.$bar_progress,"width",0,this.progress_width))}draw_label(){d("text",{x:this.x+this.width/2,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame((()=>this.update_label_position()))}draw_resize_handles(){if(this.invalid)return;const t=this.$bar;d("rect",{x:t.getX()+t.getWidth()-9,y:t.getY()+1,width:8,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle right",append_to:this.handle_group}),d("rect",{x:t.getX()+1,y:t.getY()+1,width:8,height:this.height-2,rx:this.corner_radius,ry:this.corner_radius,class:"handle left",append_to:this.handle_group}),this.$handle_progress=d("polygon",{points:this.get_progress_polygon_points().join(","),class:"handle progress",append_to:this.handle_group})}get_progress_polygon_points(){const t=this.$bar_progress;return[t.getEndX()-5,t.getY()+t.getHeight(),t.getEndX()+5,t.getY()+t.getHeight(),t.getEndX(),t.getY()+t.getHeight()-8.66]}bind(){this.invalid||this.setup_click_event()}setup_click_event(){p.on(this.group,"focus "+this.gantt.options.popup_trigger,(t=>{this.action_completed||(this.show_popup(),this.gantt.unselect_all(),this.group.classList.add("active"))})),p.on(this.group,"dblclick",(t=>{this.action_completed||this.gantt.trigger_event("click",[this.task])}))}show_popup(){if(this.gantt.bar_being_dragged)return;const t=r.format(this.task._start,"MMM D",this.gantt.options.language)+" - "+r.format(r.add(this.task._end,-1,"second"),"MMM D",this.gantt.options.language);this.gantt.show_popup({target_element:this.$bar,title:this.task.name,subtitle:t,task:this.task})}update_bar_position({x:t=null,width:e=null}){const s=this.$bar;if(t){if(!this.task.dependencies.map((t=>this.gantt.get_bar(t).$bar.getX())).reduce(((e,s)=>t>=s),t))return void(e=null);this.update_attr(s,"x",t)}e&&this.update_attr(s,"width",e),this.update_label_position(),this.update_handle_position(),this.gantt.options.show_expected_progress&&(this.date_changed(),this.compute_duration(),this.update_expected_progressbar_position()),this.update_progressbar_position(),this.update_arrow_position()}date_changed(){let t=!1;const{new_start_date:e,new_end_date:s}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(s)&&(t=!0,this.task._end=s),t&&this.gantt.trigger_event("date_change",[this.task,e,r.add(s,-1,"second")])}progress_changed(){const t=this.compute_progress();this.task.progress=t,this.gantt.trigger_event("progress_change",[this.task,t])}set_action_completed(){this.action_completed=!0,setTimeout((()=>this.action_completed=!1),1e3)}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.options.column_width,s=r.add(this.gantt.gantt_start,e*this.gantt.options.step,"hour"),i=t.getWidth()/this.gantt.options.column_width;return{new_start_date:s,new_end_date:r.add(s,i*this.gantt.options.step,"hour")}}compute_progress(){const t=this.$bar_progress.getWidth()/this.$bar.getWidth()*100;return parseInt(t,10)}compute_expected_progress(){this.expected_progress=r.diff(r.today(),this.task._start,"hour")/this.gantt.options.step,this.expected_progress=100*(this.expected_progresst.getWidth()?(e.classList.add("big"),e.setAttribute("x",t.getX()+t.getWidth()+5)):(e.classList.remove("big"),e.setAttribute("x",t.getX()+t.getWidth()/2))}update_handle_position(){if(this.invalid)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()+1),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()-9);const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("points",this.get_progress_polygon_points())}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class u{constructor(t,e,s){this.gantt=t,this.from_task=e,this.to_task=s,this.calculate_path(),this.draw()}calculate_path(){let t=this.from_task.$bar.getX()+this.from_task.$bar.getWidth()/2;const e=()=>this.to_task.$bar.getX()this.from_task.$bar.getX()+this.gantt.options.padding;for(;e();)t-=10;const s=this.gantt.options.header_height+this.gantt.options.bar_height+(this.gantt.options.padding+this.gantt.options.bar_height)*this.from_task.task._index+this.gantt.options.padding,i=this.to_task.$bar.getX()-this.gantt.options.padding/2,o=this.gantt.options.header_height+this.gantt.options.bar_height/2+(this.gantt.options.padding+this.gantt.options.bar_height)*this.to_task.task._index+this.gantt.options.padding,n=this.from_task.task._index>this.to_task.task._index,a=this.gantt.options.arrow_curve,r=n?1:0,h=n?-a:a,p=n?o+this.gantt.options.arrow_curve:o-this.gantt.options.arrow_curve;if(this.path=`\n M ${t} ${s}\n V ${p}\n a ${a} ${a} 0 0 ${r} ${a} ${h}\n L ${i} ${o}\n m -5 -5\n l 5 5\n l -5 5`,this.to_task.$bar.getX()\n
\n
\n ',this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.pointer=this.parent.querySelector(".pointer")}show(t){if(!t.target_element)throw new Error("target_element is required to show popup");t.position||(t.position="left");const e=t.target_element;if(this.custom_html){let e=this.custom_html(t.task);e+='
',this.parent.innerHTML=e,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle,this.parent.style.width=this.parent.clientWidth+"px";let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),"left"===t.position&&(this.parent.style.left=s.x+(s.width+10)+"px",this.parent.style.top=s.y+"px",this.pointer.style.transform="rotateZ(90deg)",this.pointer.style.left="-7px",this.pointer.style.top="2px"),this.parent.style.opacity=1}hide(){this.parent.style.opacity=0,this.parent.style.left=0}}const m={HOUR:"Hour",QUARTER_DAY:"Quarter Day",HALF_DAY:"Half Day",DAY:"Day",WEEK:"Week",MONTH:"Month",YEAR:"Year"},w={HOUR:["7d","7d"],QUARTER_DAY:["7d","7d"],HALF_DAY:["7d","7d"],DAY:["1m","1m"],WEEK:["1m","1m"],MONTH:["1m","1m"],YEAR:["2y","2y"]};class f{constructor(t,e,s){this.setup_wrapper(t),this.setup_options(s),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,s;if("string"==typeof t&&(t=document.querySelector(t)),t instanceof HTMLElement)s=t,e=t.querySelector("svg");else{if(!(t instanceof SVGElement))throw new TypeError("Frappé Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e=t}e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=d("svg",{append_to:s,class:"gantt"}),this.$container=document.createElement("div"),this.$container.classList.add("gantt-container");this.$svg.parentElement.appendChild(this.$container),this.$container.appendChild(this.$svg),this.popup_wrapper=document.createElement("div"),this.popup_wrapper.classList.add("popup-wrapper"),this.$container.appendChild(this.popup_wrapper)}setup_options(t){const e={header_height:50,column_width:30,step:24,view_modes:[...Object.values(m)],bar_height:20,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",popup_trigger:"click",custom_popup_html:null,language:"en"};this.options=Object.assign({},e,t);for(let[e,s]of Object.entries(t.view_mode_padding))"string"==typeof s&&(t.view_mode_padding[e]=[s,s]);console.log(t.view_mode_padding),this.options.view_mode_padding={...w,...t.view_mode_padding}}setup_tasks(t){this.tasks=t.map(((t,e)=>{if(t._start=r.parse(t.start),void 0===t.end&&void 0!==t.duration){t.end=t._start,t.duration.split(" ").forEach((e=>{let{duration:s,scale:i}=r.parse_duration(e);t.end=r.add(t.end,s,i)}))}if(t._end=r.parse(t.end),r.diff(t._end,t._start,"year")>10&&(t.end=null),t._index=e,!t.start&&!t.end){const e=r.today();t._start=e,t._end=r.add(e,2,"day")}!t.start&&t.end&&(t._start=r.add(t._end,-2,"day")),t.start&&!t.end&&(t._end=r.add(t._start,2,"day"));if(r.get_date_values(t._end).slice(3).every((t=>0===t))&&(t._end=r.add(t._end,24,"hour")),t.start&&t.end||(t.invalid=!0),"string"==typeof t.dependencies||!t.dependencies){let e=[];t.dependencies&&(e=t.dependencies.split(",").map((t=>t.trim())).filter((t=>t))),t.dependencies=e}return t.id||(t.id=function(t){return t.name+"_"+Math.random().toString(36).slice(2,12)}(t)),t})),this.setup_dependencies()}setup_dependencies(){this.dependency_map={};for(let t of this.tasks)for(let e of t.dependencies)this.dependency_map[e]=this.dependency_map[e]||[],this.dependency_map[e].push(t.id)}refresh(t){this.setup_tasks(t),this.change_view_mode()}change_view_mode(t=this.options.view_mode){this.update_view_scale(t),this.setup_dates(),this.render(),this.trigger_event("view_change",[t])}update_view_scale(t){this.options.view_mode=t,t===m.HOUR?(this.options.step=1,this.options.column_width=38):t===m.DAY?(this.options.step=24,this.options.column_width=38):t===m.HALF_DAY?(this.options.step=12,this.options.column_width=38):t===m.QUARTER_DAY?(this.options.step=6,this.options.column_width=38):t===m.WEEK?(this.options.step=168,this.options.column_width=140):t===m.MONTH?(this.options.step=720,this.options.column_width=120):t===m.YEAR&&(this.options.step=8760,this.options.column_width=120)}setup_dates(){this.setup_gantt_dates(),this.setup_date_values()}setup_gantt_dates(){this.gantt_start=this.gantt_end=null;for(let t of this.tasks)(!this.gantt_start||t._startthis.gantt_end)&&(this.gantt_end=t._end);let t,e=r.start_of(this.gantt_start,"day"),s=r.start_of(this.gantt_end,"day");for(let[e,s]of Object.entries(m))s===this.options.view_mode&&(t=e);const[i,o]=this.options.view_mode_padding[t].map(r.parse_duration);this.gantt_start=r.add(e,-i.duration,i.scale),this.gantt_end=r.add(s,o.duration,o.scale)}setup_date_values(){this.dates=[];let t=null;for(;null===t||t=1&&i.getDate()<8&&(o+=" thick"),this.view_is(m.MONTH)&&i.getMonth()%3==0&&(o+=" thick"),d("path",{d:`M ${t} ${e} v ${s}`,class:o,append_to:this.layers.grid}),this.view_is(m.MONTH)?t+=r.get_days_in_month(i)*this.options.column_width/30:t+=this.options.column_width}}computeGridHighlightDimensions(t){let e=0;if(this.view_is(m.DAY))return r.diff(r.today(),this.gantt_start,"hour")/this.options.step*this.options.column_width;for(let s of this.dates){const i=new Date,o=new Date(s),n=new Date(s);switch(t){case m.WEEK:n.setDate(s.getDate()+7);break;case m.MONTH:n.setMonth(s.getMonth()+1);break;case m.YEAR:n.setFullYear(s.getFullYear()+1)}if(i>=o&&i<=n)break;e+=this.options.column_width}return e}make_grid_highlights(){if(this.view_is(m.DAY)||this.view_is(m.WEEK)||this.view_is(m.MONTH)||this.view_is(m.YEAR)){const t=this.computeGridHighlightDimensions(this.options.view_mode),e=0,s=this.options.column_width,i=(this.options.bar_height+this.options.padding)*this.tasks.length+this.options.header_height+this.options.padding/2;let o="";switch(this.options.view_mode){case m.DAY:o="today-highlight";break;case m.WEEK:o="week-highlight";break;case m.MONTH:o="month-highlight";break;case m.YEAR:o="year-highlight"}d("rect",{x:t,y:e,width:s,height:i,class:o,append_to:this.layers.grid})}}make_dates(){for(let t of this.get_dates_to_draw())if(d("text",{x:t.lower_x,y:t.lower_y,innerHTML:t.lower_text,class:"lower-text",append_to:this.layers.date}),t.upper_text){const e=d("text",{x:t.upper_x,y:t.upper_y,innerHTML:t.upper_text,class:"upper-text",append_to:this.layers.date});e.getBBox().x2>this.layers.grid.getBBox().width&&e.remove()}}get_dates_to_draw(){let t=null;return this.dates.map(((e,s)=>{const i=this.get_date_info(e,t,s);return t=e,i}))}get_date_info(t,e,s){e||(e=r.add(t,1,"day"));const i={Hour_lower:r.format(t,"HH",this.options.language),"Quarter Day_lower":r.format(t,"HH",this.options.language),"Half Day_lower":r.format(t,"HH",this.options.language),Day_lower:t.getDate()!==e.getDate()?r.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==e.getMonth()?r.format(t,"D MMM",this.options.language):r.format(t,"D",this.options.language),Month_lower:r.format(t,"MMMM",this.options.language),Year_lower:r.format(t,"YYYY",this.options.language),Hour_upper:t.getDate()!==e.getDate()?r.format(t,"D MMMM",this.options.language):"","Quarter Day_upper":t.getDate()!==e.getDate()?r.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==e.getDate()?t.getMonth()!==e.getMonth()?r.format(t,"D MMM",this.options.language):r.format(t,"D",this.options.language):"",Day_upper:t.getMonth()!==e.getMonth()?r.format(t,"MMMM",this.options.language):"",Week_upper:t.getMonth()!==e.getMonth()?r.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==e.getFullYear()?r.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==e.getFullYear()?r.format(t,"YYYY",this.options.language):""},o={x:s*this.options.column_width,lower_y:this.options.header_height,upper_y:this.options.header_height-25},n={Hour_lower:this.options.column_width/2,Hour_upper:12*this.options.column_width,"Quarter Day_lower":this.options.column_width/2,"Quarter Day_upper":2*this.options.column_width,"Half Day_lower":this.options.column_width/2,"Half Day_upper":this.options.column_width,Day_lower:this.options.column_width/2,Day_upper:30*this.options.column_width/2,Week_lower:0,Week_upper:4*this.options.column_width/2,Month_lower:this.options.column_width/2,Month_upper:12*this.options.column_width/2,Year_lower:this.options.column_width/2,Year_upper:30*this.options.column_width/2};return{upper_text:i[`${this.options.view_mode}_upper`],lower_text:i[`${this.options.view_mode}_lower`],upper_x:o.x+n[`${this.options.view_mode}_upper`],upper_y:o.upper_y,lower_x:o.x+n[`${this.options.view_mode}_lower`],lower_y:o.lower_y}}make_bars(){this.bars=this.tasks.map((t=>{const e=new l(this,t);return this.layers.bar.appendChild(e.group),e}))}make_arrows(){this.arrows=[];for(let t of this.tasks){let e=[];e=t.dependencies.map((e=>{const s=this.get_task(e);if(!s)return;const i=new u(this,this.bars[s._index],this.bars[t._index]);return this.layers.arrow.appendChild(i.element),i})).filter(Boolean),this.arrows=this.arrows.concat(e)}}map_arrows_on_bars(){for(let t of this.bars)t.arrows=this.arrows.filter((e=>e.from_task.task.id===t.task.id||e.to_task.task.id===t.task.id))}set_width(){const t=this.$svg.getBoundingClientRect().width,e=this.$svg.querySelector(".grid .grid-row").getAttribute("width");t{this.unselect_all(),this.hide_popup()}))}bind_bar_events(){let t=!1,e=0,s=0,i=!1,o=!1,n=null,a=[];this.bar_being_dragged=null,p.on(this.$svg,"mousedown",".bar-wrapper, .handle",((r,h)=>{const d=p.closest(".bar-wrapper",h);h.classList.contains("left")?i=!0:h.classList.contains("right")?o=!0:h.classList.contains("bar-wrapper")&&(t=!0),d.classList.add("active"),e=r.offsetX,s=r.offsetY,n=d.getAttribute("data-id");const _=[n,...this.get_all_dependent_tasks(n)];a=_.map((t=>this.get_bar(t))),this.bar_being_dragged=n,a.forEach((t=>{const e=t.$bar;e.ox=e.getX(),e.oy=e.getY(),e.owidth=e.getWidth(),e.finaldx=0}))})),p.on(this.$svg,"mousemove",(s=>{if(!(t||i||o))return;const r=s.offsetX-e;s.offsetY,a.forEach((e=>{const s=e.$bar;s.finaldx=this.get_snap_position(r),this.hide_popup(),i?n===e.task.id?e.update_bar_position({x:s.ox+s.finaldx,width:s.owidth-s.finaldx}):e.update_bar_position({x:s.ox+s.finaldx}):o?n===e.task.id&&e.update_bar_position({width:s.owidth+s.finaldx}):t&&e.update_bar_position({x:s.ox+s.finaldx})}))})),document.addEventListener("mouseup",(e=>{(t||i||o)&&a.forEach((t=>t.group.classList.remove("active"))),t=!1,i=!1,o=!1})),p.on(this.$svg,"mouseup",(t=>{this.bar_being_dragged=null,a.forEach((t=>{t.$bar.finaldx&&(t.date_changed(),t.set_action_completed())}))})),this.bind_bar_progress()}bind_bar_progress(){let t=0,e=0,s=null,i=null,o=null,n=null;p.on(this.$svg,"mousedown",".handle.progress",((a,r)=>{s=!0,t=a.offsetX,e=a.offsetY;const h=p.closest(".bar-wrapper",r).getAttribute("data-id");i=this.get_bar(h),o=i.$bar_progress,n=i.$bar,o.finaldx=0,o.owidth=o.getWidth(),o.min_dx=-o.getWidth(),o.max_dx=n.getWidth()-o.getWidth()})),p.on(this.$svg,"mousemove",(e=>{if(!s)return;let n=e.offsetX-t;e.offsetY,n>o.max_dx&&(n=o.max_dx),n{s=!1,o&&o.finaldx&&(i.progress_changed(),i.set_action_completed())}))}get_all_dependent_tasks(t){let e=[],s=[t];for(;s.length;){const t=s.reduce(((t,e)=>t=t.concat(this.dependency_map[e])),[]);e=e.concat(t),s=t.filter((t=>!s.includes(t)))}return e.filter(Boolean)}get_snap_position(t){let e,s,i=t;return this.view_is(m.WEEK)?(e=t%(this.options.column_width/7),s=i-e+(e{t.classList.remove("active")}))}view_is(t){return"string"==typeof t?this.options.view_mode===t:!!Array.isArray(t)&&t.some((t=>this.options.view_mode===t))}get_task(t){return this.tasks.find((e=>e.id===t))}get_bar(t){return this.bars.find((e=>e.task.id===t))}show_popup(t){this.popup||(this.popup=new c(this.popup_wrapper,this.options.custom_popup_html)),this.popup.show(t)}hide_popup(){this.popup&&this.popup.hide()}trigger_event(t,e){this.options["on_"+t]&&this.options["on_"+t].apply(null,e)}get_oldest_starting_date(){return this.tasks.map((t=>t._start)).reduce(((t,e)=>e<=t?e:t))}clear(){this.$svg.innerHTML=""}}return f.VIEW_MODE=m,f}(); //# sourceMappingURL=frappe-gantt.min.js.map diff --git a/dist/frappe-gantt.min.js.map b/dist/frappe-gantt.min.js.map index a3cd5d6..5960861 100644 --- a/dist/frappe-gantt.min.js.map +++ b/dist/frappe-gantt.min.js.map @@ -1 +1 @@ -{"version":3,"file":"frappe-gantt.min.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = 'year';\r\nconst MONTH = 'month';\r\nconst DAY = 'day';\r\nconst HOUR = 'hour';\r\nconst MINUTE = 'minute';\r\nconst SECOND = 'second';\r\nconst MILLISECOND = 'millisecond';\r\n\r\nexport default {\r\n parse(date, date_separator = '-', time_separator = /[.:]/) {\r\n if (date instanceof Date) {\r\n return date;\r\n }\r\n if (typeof date === 'string') {\r\n let date_parts, time_parts;\r\n const parts = date.split(' ');\r\n\r\n date_parts = parts[0]\r\n .split(date_separator)\r\n .map((val) => parseInt(val, 10));\r\n time_parts = parts[1] && parts[1].split(time_separator);\r\n\r\n // month is 0 indexed\r\n date_parts[1] = date_parts[1] - 1;\r\n\r\n let vals = date_parts;\r\n\r\n if (time_parts && time_parts.length) {\r\n if (time_parts.length == 4) {\r\n time_parts[3] = '0.' + time_parts[3];\r\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\r\n }\r\n vals = vals.concat(time_parts);\r\n }\r\n\r\n return new Date(...vals);\r\n }\r\n },\r\n\r\n to_string(date, with_time = false) {\r\n if (!(date instanceof Date)) {\r\n throw new TypeError('Invalid argument type');\r\n }\r\n const vals = this.get_date_values(date).map((val, i) => {\r\n if (i === 1) {\r\n // add 1 for month\r\n val = val + 1;\r\n }\r\n\r\n if (i === 6) {\r\n return padStart(val + '', 3, '0');\r\n }\r\n\r\n return padStart(val + '', 2, '0');\r\n });\r\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\r\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\r\n\r\n return date_string + (with_time ? ' ' + time_string : '');\r\n },\r\n\r\n format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') {\r\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\r\n month: 'long'\r\n });\r\n const month_name = dateTimeFormat.format(date);\r\n const month_name_capitalized =\r\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\r\n\r\n const values = this.get_date_values(date).map(d => padStart(d, 2, 0));\r\n const format_map = {\r\n YYYY: values[0],\r\n MM: padStart(+values[1] + 1, 2, 0),\r\n DD: values[2],\r\n HH: values[3],\r\n mm: values[4],\r\n ss: values[5],\r\n SSS: values[6],\r\n D: values[2],\r\n MMMM: month_name_capitalized,\r\n MMM: month_name_capitalized,\r\n };\r\n\r\n let str = format_string;\r\n const formatted_values = [];\r\n\r\n Object.keys(format_map)\r\n .sort((a, b) => b.length - a.length) // big string first\r\n .forEach((key) => {\r\n if (str.includes(key)) {\r\n str = str.replace(key, `$${formatted_values.length}`);\r\n formatted_values.push(format_map[key]);\r\n }\r\n });\r\n\r\n formatted_values.forEach((value, i) => {\r\n str = str.replace(`$${i}`, value);\r\n });\r\n\r\n return str;\r\n },\r\n\r\n diff(date_a, date_b, scale = DAY) {\r\n let milliseconds, seconds, hours, minutes, days, months, years;\r\n\r\n milliseconds = date_a - date_b;\r\n seconds = milliseconds / 1000;\r\n minutes = seconds / 60;\r\n hours = minutes / 60;\r\n days = hours / 24;\r\n months = days / 30;\r\n years = months / 12;\r\n\r\n if (!scale.endsWith('s')) {\r\n scale += 's';\r\n }\r\n\r\n return Math.floor(\r\n {\r\n milliseconds,\r\n seconds,\r\n minutes,\r\n hours,\r\n days,\r\n months,\r\n years,\r\n }[scale]\r\n );\r\n },\r\n\r\n today() {\r\n const vals = this.get_date_values(new Date()).slice(0, 3);\r\n return new Date(...vals);\r\n },\r\n\r\n now() {\r\n return new Date();\r\n },\r\n\r\n add(date, qty, scale) {\r\n qty = parseInt(qty, 10);\r\n const vals = [\r\n date.getFullYear() + (scale === YEAR ? qty : 0),\r\n date.getMonth() + (scale === MONTH ? qty : 0),\r\n date.getDate() + (scale === DAY ? qty : 0),\r\n date.getHours() + (scale === HOUR ? qty : 0),\r\n date.getMinutes() + (scale === MINUTE ? qty : 0),\r\n date.getSeconds() + (scale === SECOND ? qty : 0),\r\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\r\n ];\r\n return new Date(...vals);\r\n },\r\n\r\n start_of(date, scale) {\r\n const scores = {\r\n [YEAR]: 6,\r\n [MONTH]: 5,\r\n [DAY]: 4,\r\n [HOUR]: 3,\r\n [MINUTE]: 2,\r\n [SECOND]: 1,\r\n [MILLISECOND]: 0,\r\n };\r\n\r\n function should_reset(_scale) {\r\n const max_score = scores[scale];\r\n return scores[_scale] <= max_score;\r\n }\r\n\r\n const vals = [\r\n date.getFullYear(),\r\n should_reset(YEAR) ? 0 : date.getMonth(),\r\n should_reset(MONTH) ? 1 : date.getDate(),\r\n should_reset(DAY) ? 0 : date.getHours(),\r\n should_reset(HOUR) ? 0 : date.getMinutes(),\r\n should_reset(MINUTE) ? 0 : date.getSeconds(),\r\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\r\n ];\r\n\r\n return new Date(...vals);\r\n },\r\n\r\n clone(date) {\r\n return new Date(...this.get_date_values(date));\r\n },\r\n\r\n get_date_values(date) {\r\n return [\r\n date.getFullYear(),\r\n date.getMonth(),\r\n date.getDate(),\r\n date.getHours(),\r\n date.getMinutes(),\r\n date.getSeconds(),\r\n date.getMilliseconds(),\r\n ];\r\n },\r\n\r\n get_days_in_month(date) {\r\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\n\r\n const month = date.getMonth();\r\n\r\n if (month !== 1) {\r\n return no_of_days[month];\r\n }\r\n\r\n // Feb\r\n const year = date.getFullYear();\r\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\r\n return 29;\r\n }\r\n return 28;\r\n },\r\n};\r\n\r\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\r\nfunction padStart(str, targetLength, padString) {\r\n str = str + '';\r\n targetLength = targetLength >> 0;\r\n padString = String(typeof padString !== 'undefined' ? padString : ' ');\r\n if (str.length > targetLength) {\r\n return String(str);\r\n } else {\r\n targetLength = targetLength - str.length;\r\n if (targetLength > padString.length) {\r\n padString += padString.repeat(targetLength / padString.length);\r\n }\r\n return padString.slice(0, targetLength) + String(str);\r\n }\r\n}\r\n","export function $(expr, con) {\r\n return typeof expr === 'string'\r\n ? (con || document).querySelector(expr)\r\n : expr || null;\r\n}\r\n\r\nexport function createSVG(tag, attrs) {\r\n const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);\r\n for (let attr in attrs) {\r\n if (attr === 'append_to') {\r\n const parent = attrs.append_to;\r\n parent.appendChild(elem);\r\n } else if (attr === 'innerHTML') {\r\n elem.innerHTML = attrs.innerHTML;\r\n } else {\r\n elem.setAttribute(attr, attrs[attr]);\r\n }\r\n }\r\n return elem;\r\n}\r\n\r\nexport function animateSVG(svgElement, attr, from, to) {\r\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\r\n\r\n if (animatedSvgElement === svgElement) {\r\n // triggered 2nd time programmatically\r\n // trigger artificial click event\r\n const event = document.createEvent('HTMLEvents');\r\n event.initEvent('click', true, true);\r\n event.eventName = 'click';\r\n animatedSvgElement.dispatchEvent(event);\r\n }\r\n}\r\n\r\nfunction getAnimationElement(\r\n svgElement,\r\n attr,\r\n from,\r\n to,\r\n dur = '0.4s',\r\n begin = '0.1s'\r\n) {\r\n const animEl = svgElement.querySelector('animate');\r\n if (animEl) {\r\n $.attr(animEl, {\r\n attributeName: attr,\r\n from,\r\n to,\r\n dur,\r\n begin: 'click + ' + begin, // artificial click\r\n });\r\n return svgElement;\r\n }\r\n\r\n const animateElement = createSVG('animate', {\r\n attributeName: attr,\r\n from,\r\n to,\r\n dur,\r\n begin,\r\n calcMode: 'spline',\r\n values: from + ';' + to,\r\n keyTimes: '0; 1',\r\n keySplines: cubic_bezier('ease-out'),\r\n });\r\n svgElement.appendChild(animateElement);\r\n\r\n return svgElement;\r\n}\r\n\r\nfunction cubic_bezier(name) {\r\n return {\r\n ease: '.25 .1 .25 1',\r\n linear: '0 0 1 1',\r\n 'ease-in': '.42 0 1 1',\r\n 'ease-out': '0 0 .58 1',\r\n 'ease-in-out': '.42 0 .58 1',\r\n }[name];\r\n}\r\n\r\n$.on = (element, event, selector, callback) => {\r\n if (!callback) {\r\n callback = selector;\r\n $.bind(element, event, callback);\r\n } else {\r\n $.delegate(element, event, selector, callback);\r\n }\r\n};\r\n\r\n$.off = (element, event, handler) => {\r\n element.removeEventListener(event, handler);\r\n};\r\n\r\n$.bind = (element, event, callback) => {\r\n event.split(/\\s+/).forEach(function (event) {\r\n element.addEventListener(event, callback);\r\n });\r\n};\r\n\r\n$.delegate = (element, event, selector, callback) => {\r\n element.addEventListener(event, function (e) {\r\n const delegatedTarget = e.target.closest(selector);\r\n if (delegatedTarget) {\r\n e.delegatedTarget = delegatedTarget;\r\n callback.call(this, e, delegatedTarget);\r\n }\r\n });\r\n};\r\n\r\n$.closest = (selector, element) => {\r\n if (!element) return null;\r\n\r\n if (element.matches(selector)) {\r\n return element;\r\n }\r\n\r\n return $.closest(selector, element.parentNode);\r\n};\r\n\r\n$.attr = (element, attr, value) => {\r\n if (!value && typeof attr === 'string') {\r\n return element.getAttribute(attr);\r\n }\r\n\r\n if (typeof attr === 'object') {\r\n for (let key in attr) {\r\n $.attr(element, key, attr[key]);\r\n }\r\n return;\r\n }\r\n\r\n element.setAttribute(attr, value);\r\n};\r\n","import date_utils from './date_utils';\r\nimport { $, createSVG, animateSVG } from './svg_utils';\r\n\r\nexport default class Bar {\r\n constructor(gantt, task) {\r\n this.set_defaults(gantt, task);\r\n this.prepare();\r\n this.draw();\r\n this.bind();\r\n }\r\n\r\n set_defaults(gantt, task) {\r\n this.action_completed = false;\r\n this.gantt = gantt;\r\n this.task = task;\r\n }\r\n\r\n prepare() {\r\n this.prepare_values();\r\n this.prepare_helpers();\r\n }\r\n\r\n prepare_values() {\r\n this.invalid = this.task.invalid;\r\n this.height = this.gantt.options.bar_height;\r\n this.x = this.compute_x();\r\n this.y = this.compute_y();\r\n this.corner_radius = this.gantt.options.bar_corner_radius;\r\n this.duration =\r\n date_utils.diff(this.task._end, this.task._start, 'hour') /\r\n this.gantt.options.step;\r\n this.width = this.gantt.options.column_width * this.duration;\r\n this.progress_width =\r\n this.gantt.options.column_width *\r\n this.duration *\r\n (this.task.progress / 100) || 0;\r\n this.group = createSVG('g', {\r\n class: 'bar-wrapper ' + (this.task.custom_class || ''),\r\n 'data-id': this.task.id,\r\n });\r\n this.bar_group = createSVG('g', {\r\n class: 'bar-group',\r\n append_to: this.group,\r\n });\r\n this.handle_group = createSVG('g', {\r\n class: 'handle-group',\r\n append_to: this.group,\r\n });\r\n }\r\n\r\n prepare_helpers() {\r\n SVGElement.prototype.getX = function () {\r\n return +this.getAttribute('x');\r\n };\r\n SVGElement.prototype.getY = function () {\r\n return +this.getAttribute('y');\r\n };\r\n SVGElement.prototype.getWidth = function () {\r\n return +this.getAttribute('width');\r\n };\r\n SVGElement.prototype.getHeight = function () {\r\n return +this.getAttribute('height');\r\n };\r\n SVGElement.prototype.getEndX = function () {\r\n return this.getX() + this.getWidth();\r\n };\r\n }\r\n\r\n draw() {\r\n this.draw_bar();\r\n this.draw_progress_bar();\r\n this.draw_label();\r\n this.draw_resize_handles();\r\n }\r\n\r\n draw_bar() {\r\n this.$bar = createSVG('rect', {\r\n x: this.x,\r\n y: this.y,\r\n width: this.width,\r\n height: this.height,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'bar',\r\n append_to: this.bar_group,\r\n });\r\n\r\n animateSVG(this.$bar, 'width', 0, this.width);\r\n\r\n if (this.invalid) {\r\n this.$bar.classList.add('bar-invalid');\r\n }\r\n }\r\n\r\n draw_progress_bar() {\r\n if (this.invalid) return;\r\n this.$bar_progress = createSVG('rect', {\r\n x: this.x,\r\n y: this.y,\r\n width: this.progress_width,\r\n height: this.height,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'bar-progress',\r\n append_to: this.bar_group,\r\n });\r\n\r\n animateSVG(this.$bar_progress, 'width', 0, this.progress_width);\r\n }\r\n\r\n draw_label() {\r\n createSVG('text', {\r\n x: this.x + this.width / 2,\r\n y: this.y + this.height / 2,\r\n innerHTML: this.task.name,\r\n class: 'bar-label',\r\n append_to: this.bar_group,\r\n });\r\n // labels get BBox in the next tick\r\n requestAnimationFrame(() => this.update_label_position());\r\n }\r\n\r\n draw_resize_handles() {\r\n if (this.invalid) return;\r\n\r\n const bar = this.$bar;\r\n const handle_width = 8;\r\n\r\n createSVG('rect', {\r\n x: bar.getX() + bar.getWidth() - 9,\r\n y: bar.getY() + 1,\r\n width: handle_width,\r\n height: this.height - 2,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'handle right',\r\n append_to: this.handle_group,\r\n });\r\n\r\n createSVG('rect', {\r\n x: bar.getX() + 1,\r\n y: bar.getY() + 1,\r\n width: handle_width,\r\n height: this.height - 2,\r\n rx: this.corner_radius,\r\n ry: this.corner_radius,\r\n class: 'handle left',\r\n append_to: this.handle_group,\r\n });\r\n\r\n if (this.task.progress && this.task.progress < 100) {\r\n this.$handle_progress = createSVG('polygon', {\r\n points: this.get_progress_polygon_points().join(','),\r\n class: 'handle progress',\r\n append_to: this.handle_group,\r\n });\r\n }\r\n }\r\n\r\n get_progress_polygon_points() {\r\n const bar_progress = this.$bar_progress;\r\n return [\r\n bar_progress.getEndX() - 5,\r\n bar_progress.getY() + bar_progress.getHeight(),\r\n bar_progress.getEndX() + 5,\r\n bar_progress.getY() + bar_progress.getHeight(),\r\n bar_progress.getEndX(),\r\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\r\n ];\r\n }\r\n\r\n bind() {\r\n if (this.invalid) return;\r\n this.setup_click_event();\r\n }\r\n\r\n setup_click_event() {\r\n $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => {\r\n if (this.action_completed) {\r\n // just finished a move action, wait for a few seconds\r\n return;\r\n }\r\n\r\n this.show_popup();\r\n this.gantt.unselect_all();\r\n this.group.classList.add('active');\r\n });\r\n\r\n $.on(this.group, 'dblclick', (e) => {\r\n if (this.action_completed) {\r\n // just finished a move action, wait for a few seconds\r\n return;\r\n }\r\n\r\n this.gantt.trigger_event('click', [this.task]);\r\n });\r\n }\r\n\r\n show_popup() {\r\n if (this.gantt.bar_being_dragged) return;\r\n\r\n const start_date = date_utils.format(\r\n this.task._start,\r\n 'MMM D',\r\n this.gantt.options.language\r\n );\r\n const end_date = date_utils.format(\r\n date_utils.add(this.task._end, -1, 'second'),\r\n 'MMM D',\r\n this.gantt.options.language\r\n );\r\n const subtitle = start_date + ' - ' + end_date;\r\n\r\n this.gantt.show_popup({\r\n target_element: this.$bar,\r\n title: this.task.name,\r\n subtitle: subtitle,\r\n task: this.task,\r\n });\r\n }\r\n\r\n update_bar_position({ x = null, width = null }) {\r\n const bar = this.$bar;\r\n if (x) {\r\n // get all x values of parent task\r\n const xs = this.task.dependencies.map((dep) => {\r\n return this.gantt.get_bar(dep).$bar.getX();\r\n });\r\n // child task must not go before parent\r\n const valid_x = xs.reduce((prev, curr) => {\r\n return x >= curr;\r\n }, x);\r\n if (!valid_x) {\r\n width = null;\r\n return;\r\n }\r\n this.update_attr(bar, 'x', x);\r\n }\r\n if (width && width >= this.gantt.options.column_width) {\r\n this.update_attr(bar, 'width', width);\r\n }\r\n this.update_label_position();\r\n this.update_handle_position();\r\n this.update_progressbar_position();\r\n this.update_arrow_position();\r\n }\r\n\r\n date_changed() {\r\n let changed = false;\r\n const { new_start_date, new_end_date } = this.compute_start_end_date();\r\n\r\n if (Number(this.task._start) !== Number(new_start_date)) {\r\n changed = true;\r\n this.task._start = new_start_date;\r\n }\r\n\r\n if (Number(this.task._end) !== Number(new_end_date)) {\r\n changed = true;\r\n this.task._end = new_end_date;\r\n }\r\n\r\n if (!changed) return;\r\n\r\n this.gantt.trigger_event('date_change', [\r\n this.task,\r\n new_start_date,\r\n date_utils.add(new_end_date, -1, 'second'),\r\n ]);\r\n }\r\n\r\n progress_changed() {\r\n const new_progress = this.compute_progress();\r\n this.task.progress = new_progress;\r\n this.gantt.trigger_event('progress_change', [this.task, new_progress]);\r\n }\r\n\r\n set_action_completed() {\r\n this.action_completed = true;\r\n setTimeout(() => (this.action_completed = false), 1000);\r\n }\r\n\r\n compute_start_end_date() {\r\n const bar = this.$bar;\r\n const x_in_units = bar.getX() / this.gantt.options.column_width;\r\n const new_start_date = date_utils.add(\r\n this.gantt.gantt_start,\r\n x_in_units * this.gantt.options.step,\r\n 'hour'\r\n );\r\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\r\n const new_end_date = date_utils.add(\r\n new_start_date,\r\n width_in_units * this.gantt.options.step,\r\n 'hour'\r\n );\r\n\r\n return { new_start_date, new_end_date };\r\n }\r\n\r\n compute_progress() {\r\n const progress =\r\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\r\n return parseInt(progress, 10);\r\n }\r\n\r\n compute_x() {\r\n const { step, column_width } = this.gantt.options;\r\n const task_start = this.task._start;\r\n const gantt_start = this.gantt.gantt_start;\r\n\r\n const diff = date_utils.diff(task_start, gantt_start, 'hour');\r\n let x = (diff / step) * column_width;\r\n\r\n if (this.gantt.view_is('Month')) {\r\n const diff = date_utils.diff(task_start, gantt_start, 'day');\r\n x = (diff * column_width) / 30;\r\n }\r\n return x;\r\n }\r\n\r\n compute_y() {\r\n return (\r\n this.gantt.options.header_height +\r\n this.gantt.options.padding +\r\n this.task._index * (this.height + this.gantt.options.padding)\r\n );\r\n }\r\n\r\n get_snap_position(dx) {\r\n let odx = dx,\r\n rem,\r\n position;\r\n\r\n if (this.gantt.view_is('Week')) {\r\n rem = dx % (this.gantt.options.column_width / 7);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 14\r\n ? 0\r\n : this.gantt.options.column_width / 7);\r\n } else if (this.gantt.view_is('Month')) {\r\n rem = dx % (this.gantt.options.column_width / 30);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 60\r\n ? 0\r\n : this.gantt.options.column_width / 30);\r\n } else {\r\n rem = dx % this.gantt.options.column_width;\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.gantt.options.column_width / 2\r\n ? 0\r\n : this.gantt.options.column_width);\r\n }\r\n return position;\r\n }\r\n\r\n update_attr(element, attr, value) {\r\n value = +value;\r\n if (!isNaN(value)) {\r\n element.setAttribute(attr, value);\r\n }\r\n return element;\r\n }\r\n\r\n update_progressbar_position() {\r\n if (this.invalid) return;\r\n this.$bar_progress.setAttribute('x', this.$bar.getX());\r\n this.$bar_progress.setAttribute(\r\n 'width',\r\n this.$bar.getWidth() * (this.task.progress / 100)\r\n );\r\n }\r\n\r\n update_label_position() {\r\n const bar = this.$bar,\r\n label = this.group.querySelector('.bar-label');\r\n\r\n if (label.getBBox().width > bar.getWidth()) {\r\n label.classList.add('big');\r\n label.setAttribute('x', bar.getX() + bar.getWidth() + 5);\r\n } else {\r\n label.classList.remove('big');\r\n label.setAttribute('x', bar.getX() + bar.getWidth() / 2);\r\n }\r\n }\r\n\r\n update_handle_position() {\r\n if (this.invalid) return;\r\n const bar = this.$bar;\r\n this.handle_group\r\n .querySelector('.handle.left')\r\n .setAttribute('x', bar.getX() + 1);\r\n this.handle_group\r\n .querySelector('.handle.right')\r\n .setAttribute('x', bar.getEndX() - 9);\r\n const handle = this.group.querySelector('.handle.progress');\r\n handle &&\r\n handle.setAttribute('points', this.get_progress_polygon_points());\r\n }\r\n\r\n update_arrow_position() {\r\n this.arrows = this.arrows || [];\r\n for (let arrow of this.arrows) {\r\n arrow.update();\r\n }\r\n }\r\n}\r\n\r\nfunction isFunction(functionToCheck) {\r\n var getType = {};\r\n return (\r\n functionToCheck &&\r\n getType.toString.call(functionToCheck) === '[object Function]'\r\n );\r\n}\r\n","import { createSVG } from './svg_utils';\r\n\r\nexport default class Arrow {\r\n constructor(gantt, from_task, to_task) {\r\n this.gantt = gantt;\r\n this.from_task = from_task;\r\n this.to_task = to_task;\r\n\r\n this.calculate_path();\r\n this.draw();\r\n }\r\n\r\n calculate_path() {\r\n let start_x =\r\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\r\n\r\n const condition = () =>\r\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\r\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\r\n\r\n while (condition()) {\r\n start_x -= 10;\r\n }\r\n\r\n const start_y =\r\n this.gantt.options.header_height +\r\n this.gantt.options.bar_height +\r\n (this.gantt.options.padding + this.gantt.options.bar_height) *\r\n this.from_task.task._index +\r\n this.gantt.options.padding;\r\n\r\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\r\n const end_y =\r\n this.gantt.options.header_height +\r\n this.gantt.options.bar_height / 2 +\r\n (this.gantt.options.padding + this.gantt.options.bar_height) *\r\n this.to_task.task._index +\r\n this.gantt.options.padding;\r\n\r\n const from_is_below_to =\r\n this.from_task.task._index > this.to_task.task._index;\r\n const curve = this.gantt.options.arrow_curve;\r\n const clockwise = from_is_below_to ? 1 : 0;\r\n const curve_y = from_is_below_to ? -curve : curve;\r\n const offset = from_is_below_to\r\n ? end_y + this.gantt.options.arrow_curve\r\n : end_y - this.gantt.options.arrow_curve;\r\n\r\n this.path = `\r\n M ${start_x} ${start_y}\r\n V ${offset}\r\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\r\n L ${end_x} ${end_y}\r\n m -5 -5\r\n l 5 5\r\n l -5 5`;\r\n\r\n if (\r\n this.to_task.$bar.getX() <\r\n this.from_task.$bar.getX() + this.gantt.options.padding\r\n ) {\r\n const down_1 = this.gantt.options.padding / 2 - curve;\r\n const down_2 =\r\n this.to_task.$bar.getY() +\r\n this.to_task.$bar.getHeight() / 2 -\r\n curve_y;\r\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\r\n\r\n this.path = `\r\n M ${start_x} ${start_y}\r\n v ${down_1}\r\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\r\n H ${left}\r\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\r\n V ${down_2}\r\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\r\n L ${end_x} ${end_y}\r\n m -5 -5\r\n l 5 5\r\n l -5 5`;\r\n }\r\n }\r\n\r\n draw() {\r\n this.element = createSVG('path', {\r\n d: this.path,\r\n 'data-from': this.from_task.task.id,\r\n 'data-to': this.to_task.task.id,\r\n });\r\n }\r\n\r\n update() {\r\n this.calculate_path();\r\n this.element.setAttribute('d', this.path);\r\n }\r\n}\r\n","export default class Popup {\r\n constructor(parent, custom_html) {\r\n this.parent = parent;\r\n this.custom_html = custom_html;\r\n this.make();\r\n }\r\n\r\n make() {\r\n this.parent.innerHTML = `\r\n
\r\n
\r\n
\r\n `;\r\n\r\n this.hide();\r\n\r\n this.title = this.parent.querySelector('.title');\r\n this.subtitle = this.parent.querySelector('.subtitle');\r\n this.pointer = this.parent.querySelector('.pointer');\r\n }\r\n\r\n show(options) {\r\n if (!options.target_element) {\r\n throw new Error('target_element is required to show popup');\r\n }\r\n if (!options.position) {\r\n options.position = 'left';\r\n }\r\n const target_element = options.target_element;\r\n\r\n if (this.custom_html) {\r\n let html = this.custom_html(options.task);\r\n html += '
';\r\n this.parent.innerHTML = html;\r\n this.pointer = this.parent.querySelector('.pointer');\r\n } else {\r\n // set data\r\n this.title.innerHTML = options.title;\r\n this.subtitle.innerHTML = options.subtitle;\r\n this.parent.style.width = this.parent.clientWidth + 'px';\r\n }\r\n\r\n // set position\r\n let position_meta;\r\n if (target_element instanceof HTMLElement) {\r\n position_meta = target_element.getBoundingClientRect();\r\n } else if (target_element instanceof SVGElement) {\r\n position_meta = options.target_element.getBBox();\r\n }\r\n\r\n if (options.position === 'left') {\r\n this.parent.style.left =\r\n position_meta.x + (position_meta.width + 10) + 'px';\r\n this.parent.style.top = position_meta.y + 'px';\r\n\r\n this.pointer.style.transform = 'rotateZ(90deg)';\r\n this.pointer.style.left = '-7px';\r\n this.pointer.style.top = '2px';\r\n }\r\n\r\n // show\r\n this.parent.style.opacity = 1;\r\n }\r\n\r\n hide() {\r\n this.parent.style.opacity = 0;\r\n this.parent.style.left = 0;\r\n }\r\n}\r\n","import date_utils from './date_utils';\r\nimport { $, createSVG } from './svg_utils';\r\nimport Bar from './bar';\r\nimport Arrow from './arrow';\r\nimport Popup from './popup';\r\n\r\nimport './gantt.scss';\r\n\r\nconst VIEW_MODE = {\r\n QUARTER_DAY: 'Quarter Day',\r\n HALF_DAY: 'Half Day',\r\n DAY: 'Day',\r\n WEEK: 'Week',\r\n MONTH: 'Month',\r\n YEAR: 'Year',\r\n};\r\n\r\nexport default class Gantt {\r\n constructor(wrapper, tasks, options) {\r\n this.setup_wrapper(wrapper);\r\n this.setup_options(options);\r\n this.setup_tasks(tasks);\r\n // initialize with default view mode\r\n this.change_view_mode();\r\n this.bind_events();\r\n }\r\n\r\n setup_wrapper(element) {\r\n let svg_element, wrapper_element;\r\n\r\n // CSS Selector is passed\r\n if (typeof element === 'string') {\r\n element = document.querySelector(element);\r\n }\r\n\r\n // get the SVGElement\r\n if (element instanceof HTMLElement) {\r\n wrapper_element = element;\r\n svg_element = element.querySelector('svg');\r\n } else if (element instanceof SVGElement) {\r\n svg_element = element;\r\n } else {\r\n throw new TypeError(\r\n 'Frappé Gantt only supports usage of a string CSS selector,' +\r\n \" HTML DOM element or SVG DOM element for the 'element' parameter\"\r\n );\r\n }\r\n\r\n // svg element\r\n if (!svg_element) {\r\n // create it\r\n this.$svg = createSVG('svg', {\r\n append_to: wrapper_element,\r\n class: 'gantt',\r\n });\r\n } else {\r\n this.$svg = svg_element;\r\n this.$svg.classList.add('gantt');\r\n }\r\n\r\n // wrapper element\r\n this.$container = document.createElement('div');\r\n this.$container.classList.add('gantt-container');\r\n\r\n const parent_element = this.$svg.parentElement;\r\n parent_element.appendChild(this.$container);\r\n this.$container.appendChild(this.$svg);\r\n\r\n // popup wrapper\r\n this.popup_wrapper = document.createElement('div');\r\n this.popup_wrapper.classList.add('popup-wrapper');\r\n this.$container.appendChild(this.popup_wrapper);\r\n }\r\n\r\n setup_options(options) {\r\n const default_options = {\r\n header_height: 50,\r\n column_width: 30,\r\n step: 24,\r\n view_modes: [...Object.values(VIEW_MODE)],\r\n bar_height: 20,\r\n bar_corner_radius: 3,\r\n arrow_curve: 5,\r\n padding: 18,\r\n view_mode: 'Day',\r\n date_format: 'YYYY-MM-DD',\r\n popup_trigger: 'click',\r\n custom_popup_html: null,\r\n language: 'en',\r\n };\r\n this.options = Object.assign({}, default_options, options);\r\n }\r\n\r\n setup_tasks(tasks) {\r\n // prepare tasks\r\n this.tasks = tasks.map((task, i) => {\r\n // convert to Date objects\r\n task._start = date_utils.parse(task.start);\r\n task._end = date_utils.parse(task.end);\r\n\r\n // make task invalid if duration too large\r\n if (date_utils.diff(task._end, task._start, 'year') > 10) {\r\n task.end = null;\r\n }\r\n\r\n // cache index\r\n task._index = i;\r\n\r\n // invalid dates\r\n if (!task.start && !task.end) {\r\n const today = date_utils.today();\r\n task._start = today;\r\n task._end = date_utils.add(today, 2, 'day');\r\n }\r\n\r\n if (!task.start && task.end) {\r\n task._start = date_utils.add(task._end, -2, 'day');\r\n }\r\n\r\n if (task.start && !task.end) {\r\n task._end = date_utils.add(task._start, 2, 'day');\r\n }\r\n\r\n // if hours is not set, assume the last day is full day\r\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\r\n const task_end_values = date_utils.get_date_values(task._end);\r\n if (task_end_values.slice(3).every((d) => d === 0)) {\r\n task._end = date_utils.add(task._end, 24, 'hour');\r\n }\r\n\r\n // invalid flag\r\n if (!task.start || !task.end) {\r\n task.invalid = true;\r\n }\r\n\r\n // dependencies\r\n if (typeof task.dependencies === 'string' || !task.dependencies) {\r\n let deps = [];\r\n if (task.dependencies) {\r\n deps = task.dependencies\r\n .split(',')\r\n .map((d) => d.trim())\r\n .filter((d) => d);\r\n }\r\n task.dependencies = deps;\r\n }\r\n\r\n // uids\r\n if (!task.id) {\r\n task.id = generate_id(task);\r\n }\r\n\r\n return task;\r\n });\r\n\r\n this.setup_dependencies();\r\n }\r\n\r\n setup_dependencies() {\r\n this.dependency_map = {};\r\n for (let t of this.tasks) {\r\n for (let d of t.dependencies) {\r\n this.dependency_map[d] = this.dependency_map[d] || [];\r\n this.dependency_map[d].push(t.id);\r\n }\r\n }\r\n }\r\n\r\n refresh(tasks) {\r\n this.setup_tasks(tasks);\r\n this.change_view_mode();\r\n }\r\n\r\n change_view_mode(mode = this.options.view_mode) {\r\n this.update_view_scale(mode);\r\n this.setup_dates();\r\n this.render();\r\n // fire viewmode_change event\r\n this.trigger_event('view_change', [mode]);\r\n }\r\n\r\n update_view_scale(view_mode) {\r\n this.options.view_mode = view_mode;\r\n\r\n if (view_mode === VIEW_MODE.DAY) {\r\n this.options.step = 24;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\r\n this.options.step = 24 / 2;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\r\n this.options.step = 24 / 4;\r\n this.options.column_width = 38;\r\n } else if (view_mode === VIEW_MODE.WEEK) {\r\n this.options.step = 24 * 7;\r\n this.options.column_width = 140;\r\n } else if (view_mode === VIEW_MODE.MONTH) {\r\n this.options.step = 24 * 30;\r\n this.options.column_width = 120;\r\n } else if (view_mode === VIEW_MODE.YEAR) {\r\n this.options.step = 24 * 365;\r\n this.options.column_width = 120;\r\n }\r\n }\r\n\r\n setup_dates() {\r\n this.setup_gantt_dates();\r\n this.setup_date_values();\r\n }\r\n\r\n setup_gantt_dates() {\r\n this.gantt_start = this.gantt_end = null;\r\n\r\n for (let task of this.tasks) {\r\n // set global start and end date\r\n if (!this.gantt_start || task._start < this.gantt_start) {\r\n this.gantt_start = task._start;\r\n }\r\n if (!this.gantt_end || task._end > this.gantt_end) {\r\n this.gantt_end = task._end;\r\n }\r\n }\r\n\r\n this.gantt_start = date_utils.start_of(this.gantt_start, 'day');\r\n this.gantt_end = date_utils.start_of(this.gantt_end, 'day');\r\n\r\n // add date padding on both sides\r\n if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) {\r\n this.gantt_start = date_utils.add(this.gantt_start, -7, 'day');\r\n this.gantt_end = date_utils.add(this.gantt_end, 7, 'day');\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n this.gantt_start = date_utils.start_of(this.gantt_start, 'year');\r\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'year');\r\n } else if (this.view_is(VIEW_MODE.YEAR)) {\r\n this.gantt_start = date_utils.add(this.gantt_start, -2, 'year');\r\n this.gantt_end = date_utils.add(this.gantt_end, 2, 'year');\r\n } else {\r\n this.gantt_start = date_utils.add(this.gantt_start, -1, 'month');\r\n this.gantt_end = date_utils.add(this.gantt_end, 1, 'month');\r\n }\r\n }\r\n\r\n setup_date_values() {\r\n this.dates = [];\r\n let cur_date = null;\r\n\r\n while (cur_date === null || cur_date < this.gantt_end) {\r\n if (!cur_date) {\r\n cur_date = date_utils.clone(this.gantt_start);\r\n } else {\r\n if (this.view_is(VIEW_MODE.YEAR)) {\r\n cur_date = date_utils.add(cur_date, 1, 'year');\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n cur_date = date_utils.add(cur_date, 1, 'month');\r\n } else {\r\n cur_date = date_utils.add(\r\n cur_date,\r\n this.options.step,\r\n 'hour'\r\n );\r\n }\r\n }\r\n this.dates.push(cur_date);\r\n }\r\n }\r\n\r\n bind_events() {\r\n this.bind_grid_click();\r\n this.bind_bar_events();\r\n }\r\n\r\n render() {\r\n this.clear();\r\n this.setup_layers();\r\n this.make_grid();\r\n this.make_dates();\r\n this.make_bars();\r\n this.make_arrows();\r\n this.map_arrows_on_bars();\r\n this.set_width();\r\n this.set_scroll_position();\r\n }\r\n\r\n setup_layers() {\r\n this.layers = {};\r\n const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details'];\r\n // make group layers\r\n for (let layer of layers) {\r\n this.layers[layer] = createSVG('g', {\r\n class: layer,\r\n append_to: this.$svg,\r\n });\r\n }\r\n }\r\n\r\n make_grid() {\r\n this.make_grid_background();\r\n this.make_grid_rows();\r\n this.make_grid_header();\r\n this.make_grid_ticks();\r\n this.make_grid_highlights();\r\n }\r\n\r\n make_grid_background() {\r\n const grid_width = this.dates.length * this.options.column_width;\r\n const grid_height =\r\n this.options.header_height +\r\n this.options.padding +\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length;\r\n\r\n createSVG('rect', {\r\n x: 0,\r\n y: 0,\r\n width: grid_width,\r\n height: grid_height,\r\n class: 'grid-background',\r\n append_to: this.layers.grid,\r\n });\r\n\r\n $.attr(this.$svg, {\r\n height: grid_height + this.options.padding + 100,\r\n width: '100%',\r\n });\r\n }\r\n\r\n make_grid_rows() {\r\n const rows_layer = createSVG('g', { append_to: this.layers.grid });\r\n const lines_layer = createSVG('g', { append_to: this.layers.grid });\r\n\r\n const row_width = this.dates.length * this.options.column_width;\r\n const row_height = this.options.bar_height + this.options.padding;\r\n\r\n let row_y = this.options.header_height + this.options.padding / 2;\r\n\r\n for (let task of this.tasks) {\r\n createSVG('rect', {\r\n x: 0,\r\n y: row_y,\r\n width: row_width,\r\n height: row_height,\r\n class: 'grid-row',\r\n append_to: rows_layer,\r\n });\r\n\r\n createSVG('line', {\r\n x1: 0,\r\n y1: row_y + row_height,\r\n x2: row_width,\r\n y2: row_y + row_height,\r\n class: 'row-line',\r\n append_to: lines_layer,\r\n });\r\n\r\n row_y += this.options.bar_height + this.options.padding;\r\n }\r\n }\r\n\r\n make_grid_header() {\r\n const header_width = this.dates.length * this.options.column_width;\r\n const header_height = this.options.header_height + 10;\r\n createSVG('rect', {\r\n x: 0,\r\n y: 0,\r\n width: header_width,\r\n height: header_height,\r\n class: 'grid-header',\r\n append_to: this.layers.grid,\r\n });\r\n }\r\n\r\n make_grid_ticks() {\r\n let tick_x = 0;\r\n let tick_y = this.options.header_height + this.options.padding / 2;\r\n let tick_height =\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length;\r\n\r\n for (let date of this.dates) {\r\n let tick_class = 'tick';\r\n // thick tick for monday\r\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\r\n tick_class += ' thick';\r\n }\r\n // thick tick for first week\r\n if (\r\n this.view_is(VIEW_MODE.WEEK) &&\r\n date.getDate() >= 1 &&\r\n date.getDate() < 8\r\n ) {\r\n tick_class += ' thick';\r\n }\r\n // thick ticks for quarters\r\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\r\n tick_class += ' thick';\r\n }\r\n\r\n createSVG('path', {\r\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\r\n class: tick_class,\r\n append_to: this.layers.grid,\r\n });\r\n\r\n if (this.view_is(VIEW_MODE.MONTH)) {\r\n tick_x +=\r\n (date_utils.get_days_in_month(date) *\r\n this.options.column_width) /\r\n 30;\r\n } else {\r\n tick_x += this.options.column_width;\r\n }\r\n }\r\n }\r\n\r\n make_grid_highlights() {\r\n // highlight today's date\r\n if (this.view_is(VIEW_MODE.DAY)) {\r\n const x =\r\n (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') /\r\n this.options.step) *\r\n this.options.column_width;\r\n const y = 0;\r\n\r\n const width = this.options.column_width;\r\n const height =\r\n (this.options.bar_height + this.options.padding) *\r\n this.tasks.length +\r\n this.options.header_height +\r\n this.options.padding / 2;\r\n\r\n createSVG('rect', {\r\n x,\r\n y,\r\n width,\r\n height,\r\n class: 'today-highlight',\r\n append_to: this.layers.grid,\r\n });\r\n }\r\n }\r\n\r\n make_dates() {\r\n for (let date of this.get_dates_to_draw()) {\r\n createSVG('text', {\r\n x: date.lower_x,\r\n y: date.lower_y,\r\n innerHTML: date.lower_text,\r\n class: 'lower-text',\r\n append_to: this.layers.date,\r\n });\r\n\r\n if (date.upper_text) {\r\n const $upper_text = createSVG('text', {\r\n x: date.upper_x,\r\n y: date.upper_y,\r\n innerHTML: date.upper_text,\r\n class: 'upper-text',\r\n append_to: this.layers.date,\r\n });\r\n\r\n // remove out-of-bound dates\r\n if (\r\n $upper_text.getBBox().x2 > this.layers.grid.getBBox().width\r\n ) {\r\n $upper_text.remove();\r\n }\r\n }\r\n }\r\n }\r\n\r\n get_dates_to_draw() {\r\n let last_date = null;\r\n const dates = this.dates.map((date, i) => {\r\n const d = this.get_date_info(date, last_date, i);\r\n last_date = date;\r\n return d;\r\n });\r\n return dates;\r\n }\r\n\r\n get_date_info(date, last_date, i) {\r\n if (!last_date) {\r\n last_date = date_utils.add(date, 1, 'year');\r\n }\r\n const date_text = {\r\n 'Quarter Day_lower': date_utils.format(\r\n date,\r\n 'HH',\r\n this.options.language\r\n ),\r\n 'Half Day_lower': date_utils.format(\r\n date,\r\n 'HH',\r\n this.options.language\r\n ),\r\n Day_lower:\r\n date.getDate() !== last_date.getDate()\r\n ? date_utils.format(date, 'D', this.options.language)\r\n : '',\r\n Week_lower:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'D MMM', this.options.language)\r\n : date_utils.format(date, 'D', this.options.language),\r\n Month_lower: date_utils.format(date, 'MMMM', this.options.language),\r\n Year_lower: date_utils.format(date, 'YYYY', this.options.language),\r\n 'Quarter Day_upper':\r\n date.getDate() !== last_date.getDate()\r\n ? date_utils.format(date, 'D MMM', this.options.language)\r\n : '',\r\n 'Half Day_upper':\r\n date.getDate() !== last_date.getDate()\r\n ? date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(\r\n date,\r\n 'D MMM',\r\n this.options.language\r\n )\r\n : date_utils.format(date, 'D', this.options.language)\r\n : '',\r\n Day_upper:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'MMMM', this.options.language)\r\n : '',\r\n Week_upper:\r\n date.getMonth() !== last_date.getMonth()\r\n ? date_utils.format(date, 'MMMM', this.options.language)\r\n : '',\r\n Month_upper:\r\n date.getFullYear() !== last_date.getFullYear()\r\n ? date_utils.format(date, 'YYYY', this.options.language)\r\n : '',\r\n Year_upper:\r\n date.getFullYear() !== last_date.getFullYear()\r\n ? date_utils.format(date, 'YYYY', this.options.language)\r\n : '',\r\n };\r\n\r\n const base_pos = {\r\n x: i * this.options.column_width,\r\n lower_y: this.options.header_height,\r\n upper_y: this.options.header_height - 25,\r\n };\r\n\r\n const x_pos = {\r\n 'Quarter Day_lower': (this.options.column_width * 4) / 2,\r\n 'Quarter Day_upper': 0,\r\n 'Half Day_lower': (this.options.column_width * 2) / 2,\r\n 'Half Day_upper': 0,\r\n Day_lower: this.options.column_width / 2,\r\n Day_upper: (this.options.column_width * 30) / 2,\r\n Week_lower: 0,\r\n Week_upper: (this.options.column_width * 4) / 2,\r\n Month_lower: this.options.column_width / 2,\r\n Month_upper: (this.options.column_width * 12) / 2,\r\n Year_lower: this.options.column_width / 2,\r\n Year_upper: (this.options.column_width * 30) / 2,\r\n };\r\n\r\n return {\r\n upper_text: date_text[`${this.options.view_mode}_upper`],\r\n lower_text: date_text[`${this.options.view_mode}_lower`],\r\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\r\n upper_y: base_pos.upper_y,\r\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\r\n lower_y: base_pos.lower_y,\r\n };\r\n }\r\n\r\n make_bars() {\r\n this.bars = this.tasks.map((task) => {\r\n const bar = new Bar(this, task);\r\n this.layers.bar.appendChild(bar.group);\r\n return bar;\r\n });\r\n }\r\n\r\n make_arrows() {\r\n this.arrows = [];\r\n for (let task of this.tasks) {\r\n let arrows = [];\r\n arrows = task.dependencies\r\n .map((task_id) => {\r\n const dependency = this.get_task(task_id);\r\n if (!dependency) return;\r\n const arrow = new Arrow(\r\n this,\r\n this.bars[dependency._index], // from_task\r\n this.bars[task._index] // to_task\r\n );\r\n this.layers.arrow.appendChild(arrow.element);\r\n return arrow;\r\n })\r\n .filter(Boolean); // filter falsy values\r\n this.arrows = this.arrows.concat(arrows);\r\n }\r\n }\r\n\r\n map_arrows_on_bars() {\r\n for (let bar of this.bars) {\r\n bar.arrows = this.arrows.filter((arrow) => {\r\n return (\r\n arrow.from_task.task.id === bar.task.id ||\r\n arrow.to_task.task.id === bar.task.id\r\n );\r\n });\r\n }\r\n }\r\n\r\n set_width() {\r\n const cur_width = this.$svg.getBoundingClientRect().width;\r\n const actual_width = this.$svg\r\n .querySelector('.grid .grid-row')\r\n .getAttribute('width');\r\n if (cur_width < actual_width) {\r\n this.$svg.setAttribute('width', actual_width);\r\n }\r\n }\r\n\r\n set_scroll_position() {\r\n const parent_element = this.$svg.parentElement;\r\n if (!parent_element) return;\r\n\r\n const hours_before_first_task = date_utils.diff(\r\n this.get_oldest_starting_date(),\r\n this.gantt_start,\r\n 'hour'\r\n );\r\n\r\n const scroll_pos =\r\n (hours_before_first_task / this.options.step) *\r\n this.options.column_width -\r\n this.options.column_width;\r\n\r\n parent_element.scrollLeft = scroll_pos;\r\n }\r\n\r\n bind_grid_click() {\r\n $.on(\r\n this.$svg,\r\n this.options.popup_trigger,\r\n '.grid-row, .grid-header',\r\n () => {\r\n this.unselect_all();\r\n this.hide_popup();\r\n }\r\n );\r\n }\r\n\r\n bind_bar_events() {\r\n let is_dragging = false;\r\n let x_on_start = 0;\r\n let y_on_start = 0;\r\n let is_resizing_left = false;\r\n let is_resizing_right = false;\r\n let parent_bar_id = null;\r\n let bars = []; // instanceof Bar\r\n this.bar_being_dragged = null;\r\n\r\n function action_in_progress() {\r\n return is_dragging || is_resizing_left || is_resizing_right;\r\n }\r\n\r\n $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {\r\n const bar_wrapper = $.closest('.bar-wrapper', element);\r\n\r\n if (element.classList.contains('left')) {\r\n is_resizing_left = true;\r\n } else if (element.classList.contains('right')) {\r\n is_resizing_right = true;\r\n } else if (element.classList.contains('bar-wrapper')) {\r\n is_dragging = true;\r\n }\r\n\r\n bar_wrapper.classList.add('active');\r\n\r\n x_on_start = e.offsetX;\r\n y_on_start = e.offsetY;\r\n\r\n parent_bar_id = bar_wrapper.getAttribute('data-id');\r\n const ids = [\r\n parent_bar_id,\r\n ...this.get_all_dependent_tasks(parent_bar_id),\r\n ];\r\n bars = ids.map((id) => this.get_bar(id));\r\n\r\n this.bar_being_dragged = parent_bar_id;\r\n\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n $bar.ox = $bar.getX();\r\n $bar.oy = $bar.getY();\r\n $bar.owidth = $bar.getWidth();\r\n $bar.finaldx = 0;\r\n });\r\n });\r\n\r\n $.on(this.$svg, 'mousemove', (e) => {\r\n if (!action_in_progress()) return;\r\n const dx = e.offsetX - x_on_start;\r\n const dy = e.offsetY - y_on_start;\r\n\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n $bar.finaldx = this.get_snap_position(dx);\r\n this.hide_popup();\r\n if (is_resizing_left) {\r\n if (parent_bar_id === bar.task.id) {\r\n bar.update_bar_position({\r\n x: $bar.ox + $bar.finaldx,\r\n width: $bar.owidth - $bar.finaldx,\r\n });\r\n } else {\r\n bar.update_bar_position({\r\n x: $bar.ox + $bar.finaldx,\r\n });\r\n }\r\n } else if (is_resizing_right) {\r\n if (parent_bar_id === bar.task.id) {\r\n bar.update_bar_position({\r\n width: $bar.owidth + $bar.finaldx,\r\n });\r\n }\r\n } else if (is_dragging) {\r\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\r\n }\r\n });\r\n });\r\n\r\n document.addEventListener('mouseup', (e) => {\r\n if (is_dragging || is_resizing_left || is_resizing_right) {\r\n bars.forEach((bar) => bar.group.classList.remove('active'));\r\n }\r\n\r\n is_dragging = false;\r\n is_resizing_left = false;\r\n is_resizing_right = false;\r\n });\r\n\r\n $.on(this.$svg, 'mouseup', (e) => {\r\n this.bar_being_dragged = null;\r\n bars.forEach((bar) => {\r\n const $bar = bar.$bar;\r\n if (!$bar.finaldx) return;\r\n bar.date_changed();\r\n bar.set_action_completed();\r\n });\r\n });\r\n\r\n this.bind_bar_progress();\r\n }\r\n\r\n bind_bar_progress() {\r\n let x_on_start = 0;\r\n let y_on_start = 0;\r\n let is_resizing = null;\r\n let bar = null;\r\n let $bar_progress = null;\r\n let $bar = null;\r\n\r\n $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => {\r\n is_resizing = true;\r\n x_on_start = e.offsetX;\r\n y_on_start = e.offsetY;\r\n\r\n const $bar_wrapper = $.closest('.bar-wrapper', handle);\r\n const id = $bar_wrapper.getAttribute('data-id');\r\n bar = this.get_bar(id);\r\n\r\n $bar_progress = bar.$bar_progress;\r\n $bar = bar.$bar;\r\n\r\n $bar_progress.finaldx = 0;\r\n $bar_progress.owidth = $bar_progress.getWidth();\r\n $bar_progress.min_dx = -$bar_progress.getWidth();\r\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\r\n });\r\n\r\n $.on(this.$svg, 'mousemove', (e) => {\r\n if (!is_resizing) return;\r\n let dx = e.offsetX - x_on_start;\r\n let dy = e.offsetY - y_on_start;\r\n\r\n if (dx > $bar_progress.max_dx) {\r\n dx = $bar_progress.max_dx;\r\n }\r\n if (dx < $bar_progress.min_dx) {\r\n dx = $bar_progress.min_dx;\r\n }\r\n\r\n const $handle = bar.$handle_progress;\r\n $.attr($bar_progress, 'width', $bar_progress.owidth + dx);\r\n $.attr($handle, 'points', bar.get_progress_polygon_points());\r\n $bar_progress.finaldx = dx;\r\n });\r\n\r\n $.on(this.$svg, 'mouseup', () => {\r\n is_resizing = false;\r\n if (!($bar_progress && $bar_progress.finaldx)) return;\r\n bar.progress_changed();\r\n bar.set_action_completed();\r\n });\r\n }\r\n\r\n get_all_dependent_tasks(task_id) {\r\n let out = [];\r\n let to_process = [task_id];\r\n while (to_process.length) {\r\n const deps = to_process.reduce((acc, curr) => {\r\n acc = acc.concat(this.dependency_map[curr]);\r\n return acc;\r\n }, []);\r\n\r\n out = out.concat(deps);\r\n to_process = deps.filter((d) => !to_process.includes(d));\r\n }\r\n\r\n return out.filter(Boolean);\r\n }\r\n\r\n get_snap_position(dx) {\r\n let odx = dx,\r\n rem,\r\n position;\r\n\r\n if (this.view_is(VIEW_MODE.WEEK)) {\r\n rem = dx % (this.options.column_width / 7);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 14\r\n ? 0\r\n : this.options.column_width / 7);\r\n } else if (this.view_is(VIEW_MODE.MONTH)) {\r\n rem = dx % (this.options.column_width / 30);\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 60\r\n ? 0\r\n : this.options.column_width / 30);\r\n } else {\r\n rem = dx % this.options.column_width;\r\n position =\r\n odx -\r\n rem +\r\n (rem < this.options.column_width / 2\r\n ? 0\r\n : this.options.column_width);\r\n }\r\n return position;\r\n }\r\n\r\n unselect_all() {\r\n [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => {\r\n el.classList.remove('active');\r\n });\r\n }\r\n\r\n view_is(modes) {\r\n if (typeof modes === 'string') {\r\n return this.options.view_mode === modes;\r\n }\r\n\r\n if (Array.isArray(modes)) {\r\n return modes.some((mode) => this.options.view_mode === mode);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n get_task(id) {\r\n return this.tasks.find((task) => {\r\n return task.id === id;\r\n });\r\n }\r\n\r\n get_bar(id) {\r\n return this.bars.find((bar) => {\r\n return bar.task.id === id;\r\n });\r\n }\r\n\r\n show_popup(options) {\r\n if (!this.popup) {\r\n this.popup = new Popup(\r\n this.popup_wrapper,\r\n this.options.custom_popup_html\r\n );\r\n }\r\n this.popup.show(options);\r\n }\r\n\r\n hide_popup() {\r\n this.popup && this.popup.hide();\r\n }\r\n\r\n trigger_event(event, args) {\r\n if (this.options['on_' + event]) {\r\n this.options['on_' + event].apply(null, args);\r\n }\r\n }\r\n\r\n /**\r\n * Gets the oldest starting date from the list of tasks\r\n *\r\n * @returns Date\r\n * @memberof Gantt\r\n */\r\n get_oldest_starting_date() {\r\n return this.tasks\r\n .map((task) => task._start)\r\n .reduce((prev_date, cur_date) =>\r\n cur_date <= prev_date ? cur_date : prev_date\r\n );\r\n }\r\n\r\n /**\r\n * Clear all elements from the parent svg element\r\n *\r\n * @memberof Gantt\r\n */\r\n clear() {\r\n this.$svg.innerHTML = '';\r\n }\r\n}\r\n\r\nGantt.VIEW_MODE = VIEW_MODE;\r\n\r\nfunction generate_id(task) {\r\n return task.name + '_' + Math.random().toString(36).slice(2, 12);\r\n}\r\n"],"names":["YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","date_utils","parse","date","date_separator","time_separator","Date","date_parts","time_parts","parts","split","map","val","parseInt","vals","length","parseFloat","concat","to_string","with_time","TypeError","this","get_date_values","i","padStart","date_string","time_string","format","format_string","lang","month_name","Intl","DateTimeFormat","month","month_name_capitalized","charAt","toUpperCase","slice","values","d","format_map","YYYY","MM","DD","HH","mm","ss","SSS","D","MMMM","MMM","str","formatted_values","Object","keys","sort","a","b","forEach","key","includes","replace","push","value","diff","date_a","date_b","scale","milliseconds","seconds","hours","minutes","days","months","years","endsWith","Math","floor","today","now","add","qty","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","start_of","scores","should_reset","_scale","clone","get_days_in_month","no_of_days","year","targetLength","padString","String","repeat","$","expr","con","document","querySelector","createSVG","tag","attrs","elem","createElementNS","attr","append_to","appendChild","innerHTML","setAttribute","animateSVG","svgElement","from","to","animatedSvgElement","dur","begin","animEl","attributeName","animateElement","calcMode","keyTimes","keySplines","cubic_bezier","getAnimationElement","event","createEvent","initEvent","eventName","dispatchEvent","name","ease","linear","on","element","selector","callback","delegate","bind","off","handler","removeEventListener","addEventListener","e","delegatedTarget","target","closest","call","matches","parentNode","getAttribute","Bar","constructor","gantt","task","set_defaults","prepare","draw","action_completed","prepare_values","prepare_helpers","invalid","height","options","bar_height","x","compute_x","y","compute_y","corner_radius","bar_corner_radius","duration","_end","_start","step","width","column_width","progress_width","progress","group","class","custom_class","id","bar_group","handle_group","SVGElement","prototype","getX","getY","getWidth","getHeight","getEndX","draw_bar","draw_progress_bar","draw_label","draw_resize_handles","$bar","rx","ry","classList","$bar_progress","requestAnimationFrame","update_label_position","bar","$handle_progress","points","get_progress_polygon_points","join","bar_progress","setup_click_event","popup_trigger","show_popup","unselect_all","trigger_event","bar_being_dragged","subtitle","language","target_element","title","update_bar_position","dependencies","dep","get_bar","reduce","prev","curr","update_attr","update_handle_position","update_progressbar_position","update_arrow_position","date_changed","changed","new_start_date","new_end_date","compute_start_end_date","Number","progress_changed","new_progress","compute_progress","set_action_completed","setTimeout","x_in_units","gantt_start","width_in_units","task_start","view_is","header_height","padding","_index","get_snap_position","dx","rem","position","odx","isNaN","label","getBBox","remove","handle","arrows","arrow","update","Arrow","from_task","to_task","calculate_path","start_x","condition","start_y","end_x","end_y","from_is_below_to","curve","arrow_curve","clockwise","curve_y","offset","path","down_1","down_2","left","Popup","parent","custom_html","make","hide","pointer","show","Error","html","style","clientWidth","position_meta","HTMLElement","getBoundingClientRect","top","transform","opacity","VIEW_MODE","QUARTER_DAY","HALF_DAY","WEEK","Gantt","wrapper","tasks","setup_wrapper","setup_options","setup_tasks","change_view_mode","bind_events","svg_element","wrapper_element","$svg","$container","createElement","parentElement","popup_wrapper","default_options","view_modes","view_mode","date_format","custom_popup_html","assign","start","end","every","deps","trim","filter","random","toString","generate_id","setup_dependencies","dependency_map","t","refresh","mode","update_view_scale","setup_dates","render","setup_gantt_dates","setup_date_values","gantt_end","dates","cur_date","bind_grid_click","bind_bar_events","clear","setup_layers","make_grid","make_dates","make_bars","make_arrows","map_arrows_on_bars","set_width","set_scroll_position","layers","layer","make_grid_background","make_grid_rows","make_grid_header","make_grid_ticks","make_grid_highlights","grid_width","grid_height","grid","rows_layer","lines_layer","row_width","row_height","row_y","x1","y1","x2","y2","tick_x","tick_y","tick_height","tick_class","get_dates_to_draw","lower_x","lower_y","lower_text","upper_text","$upper_text","upper_x","upper_y","last_date","get_date_info","date_text","Day_lower","Week_lower","Month_lower","Year_lower","Day_upper","Week_upper","Month_upper","Year_upper","base_pos","x_pos","bars","task_id","dependency","get_task","Boolean","cur_width","actual_width","parent_element","scroll_pos","get_oldest_starting_date","scrollLeft","hide_popup","is_dragging","x_on_start","y_on_start","is_resizing_left","is_resizing_right","parent_bar_id","bar_wrapper","contains","offsetX","offsetY","ids","get_all_dependent_tasks","ox","oy","owidth","finaldx","bind_bar_progress","is_resizing","min_dx","max_dx","$handle","out","to_process","acc","querySelectorAll","el","modes","Array","isArray","some","find","popup","args","apply","prev_date"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"frappe-gantt.min.js","sources":["../src/date_utils.js","../src/svg_utils.js","../src/bar.js","../src/arrow.js","../src/popup.js","../src/index.js"],"sourcesContent":["const YEAR = \"year\";\nconst MONTH = \"month\";\nconst DAY = \"day\";\nconst HOUR = \"hour\";\nconst MINUTE = \"minute\";\nconst SECOND = \"second\";\nconst MILLISECOND = \"millisecond\";\n\nexport default {\n parse_duration(duration) {\n const regex = /([0-9])+(y|m|d|h|min|s|ms)/gm;\n const matches = regex.exec(duration);\n\n if (matches !== null) {\n if (matches[2] === \"y\") {\n return { duration: parseInt(matches[1]), scale: `year` };\n } else if (matches[2] === \"m\") {\n return { duration: parseInt(matches[1]), scale: `month` };\n } else if (matches[2] === \"d\") {\n return { duration: parseInt(matches[1]), scale: `day` };\n } else if (matches[2] === \"h\") {\n return { duration: parseInt(matches[1]), scale: `hour` };\n } else if (matches[2] === \"min\") {\n return { duration: parseInt(matches[1]), scale: `minute` };\n } else if (matches[2] === \"s\") {\n return { duration: parseInt(matches[1]), scale: `second` };\n } else if (matches[2] === \"ms\") {\n return { duration: parseInt(matches[1]), scale: `millisecond` };\n }\n }\n },\n parse(date, date_separator = \"-\", time_separator = /[.:]/) {\n if (date instanceof Date) {\n return date;\n }\n if (typeof date === \"string\") {\n let date_parts, time_parts;\n const parts = date.split(\" \");\n\n date_parts = parts[0]\n .split(date_separator)\n .map((val) => parseInt(val, 10));\n time_parts = parts[1] && parts[1].split(time_separator);\n\n // month is 0 indexed\n date_parts[1] = date_parts[1] - 1;\n\n let vals = date_parts;\n\n if (time_parts && time_parts.length) {\n if (time_parts.length == 4) {\n time_parts[3] = \"0.\" + time_parts[3];\n time_parts[3] = parseFloat(time_parts[3]) * 1000;\n }\n vals = vals.concat(time_parts);\n }\n\n return new Date(...vals);\n }\n },\n\n to_string(date, with_time = false) {\n if (!(date instanceof Date)) {\n throw new TypeError(\"Invalid argument type\");\n }\n const vals = this.get_date_values(date).map((val, i) => {\n if (i === 1) {\n // add 1 for month\n val = val + 1;\n }\n\n if (i === 6) {\n return padStart(val + \"\", 3, \"0\");\n }\n\n return padStart(val + \"\", 2, \"0\");\n });\n const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`;\n const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`;\n\n return date_string + (with_time ? \" \" + time_string : \"\");\n },\n\n format(date, format_string = \"YYYY-MM-DD HH:mm:ss.SSS\", lang = \"en\") {\n const dateTimeFormat = new Intl.DateTimeFormat(lang, {\n month: \"long\",\n });\n const month_name = dateTimeFormat.format(date);\n const month_name_capitalized =\n month_name.charAt(0).toUpperCase() + month_name.slice(1);\n\n const values = this.get_date_values(date).map((d) => padStart(d, 2, 0));\n const format_map = {\n YYYY: values[0],\n MM: padStart(+values[1] + 1, 2, 0),\n DD: values[2],\n HH: values[3],\n mm: values[4],\n ss: values[5],\n SSS: values[6],\n D: values[2],\n MMMM: month_name_capitalized,\n MMM: month_name_capitalized,\n };\n\n let str = format_string;\n const formatted_values = [];\n\n Object.keys(format_map)\n .sort((a, b) => b.length - a.length) // big string first\n .forEach((key) => {\n if (str.includes(key)) {\n str = str.replace(key, `$${formatted_values.length}`);\n formatted_values.push(format_map[key]);\n }\n });\n\n formatted_values.forEach((value, i) => {\n str = str.replace(`$${i}`, value);\n });\n\n return str;\n },\n\n diff(date_a, date_b, scale = DAY) {\n let milliseconds, seconds, hours, minutes, days, months, years;\n\n milliseconds = date_a - date_b;\n seconds = milliseconds / 1000;\n minutes = seconds / 60;\n hours = minutes / 60;\n days = hours / 24;\n months = days / 30;\n years = months / 12;\n\n if (!scale.endsWith(\"s\")) {\n scale += \"s\";\n }\n\n return Math.floor(\n {\n milliseconds,\n seconds,\n minutes,\n hours,\n days,\n months,\n years,\n }[scale],\n );\n },\n\n today() {\n const vals = this.get_date_values(new Date()).slice(0, 3);\n return new Date(...vals);\n },\n\n now() {\n return new Date();\n },\n\n add(date, qty, scale) {\n qty = parseInt(qty, 10);\n const vals = [\n date.getFullYear() + (scale === YEAR ? qty : 0),\n date.getMonth() + (scale === MONTH ? qty : 0),\n date.getDate() + (scale === DAY ? qty : 0),\n date.getHours() + (scale === HOUR ? qty : 0),\n date.getMinutes() + (scale === MINUTE ? qty : 0),\n date.getSeconds() + (scale === SECOND ? qty : 0),\n date.getMilliseconds() + (scale === MILLISECOND ? qty : 0),\n ];\n return new Date(...vals);\n },\n\n start_of(date, scale) {\n const scores = {\n [YEAR]: 6,\n [MONTH]: 5,\n [DAY]: 4,\n [HOUR]: 3,\n [MINUTE]: 2,\n [SECOND]: 1,\n [MILLISECOND]: 0,\n };\n\n function should_reset(_scale) {\n const max_score = scores[scale];\n return scores[_scale] <= max_score;\n }\n\n const vals = [\n date.getFullYear(),\n should_reset(YEAR) ? 0 : date.getMonth(),\n should_reset(MONTH) ? 1 : date.getDate(),\n should_reset(DAY) ? 0 : date.getHours(),\n should_reset(HOUR) ? 0 : date.getMinutes(),\n should_reset(MINUTE) ? 0 : date.getSeconds(),\n should_reset(SECOND) ? 0 : date.getMilliseconds(),\n ];\n\n return new Date(...vals);\n },\n\n clone(date) {\n return new Date(...this.get_date_values(date));\n },\n\n get_date_values(date) {\n return [\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n ];\n },\n\n get_days_in_month(date) {\n const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n const month = date.getMonth();\n\n if (month !== 1) {\n return no_of_days[month];\n }\n\n // Feb\n const year = date.getFullYear();\n if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {\n return 29;\n }\n return 28;\n },\n};\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart\nfunction padStart(str, targetLength, padString) {\n str = str + \"\";\n targetLength = targetLength >> 0;\n padString = String(typeof padString !== \"undefined\" ? padString : \" \");\n if (str.length > targetLength) {\n return String(str);\n } else {\n targetLength = targetLength - str.length;\n if (targetLength > padString.length) {\n padString += padString.repeat(targetLength / padString.length);\n }\n return padString.slice(0, targetLength) + String(str);\n }\n}\n","export function $(expr, con) {\n return typeof expr === \"string\"\n ? (con || document).querySelector(expr)\n : expr || null;\n}\n\nexport function createSVG(tag, attrs) {\n const elem = document.createElementNS(\"http://www.w3.org/2000/svg\", tag);\n for (let attr in attrs) {\n if (attr === \"append_to\") {\n const parent = attrs.append_to;\n parent.appendChild(elem);\n } else if (attr === \"innerHTML\") {\n elem.innerHTML = attrs.innerHTML;\n } else {\n elem.setAttribute(attr, attrs[attr]);\n }\n }\n return elem;\n}\n\nexport function animateSVG(svgElement, attr, from, to) {\n const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);\n\n if (animatedSvgElement === svgElement) {\n // triggered 2nd time programmatically\n // trigger artificial click event\n const event = document.createEvent(\"HTMLEvents\");\n event.initEvent(\"click\", true, true);\n event.eventName = \"click\";\n animatedSvgElement.dispatchEvent(event);\n }\n}\n\nfunction getAnimationElement(\n svgElement,\n attr,\n from,\n to,\n dur = \"0.4s\",\n begin = \"0.1s\",\n) {\n const animEl = svgElement.querySelector(\"animate\");\n if (animEl) {\n $.attr(animEl, {\n attributeName: attr,\n from,\n to,\n dur,\n begin: \"click + \" + begin, // artificial click\n });\n return svgElement;\n }\n\n const animateElement = createSVG(\"animate\", {\n attributeName: attr,\n from,\n to,\n dur,\n begin,\n calcMode: \"spline\",\n values: from + \";\" + to,\n keyTimes: \"0; 1\",\n keySplines: cubic_bezier(\"ease-out\"),\n });\n svgElement.appendChild(animateElement);\n\n return svgElement;\n}\n\nfunction cubic_bezier(name) {\n return {\n ease: \".25 .1 .25 1\",\n linear: \"0 0 1 1\",\n \"ease-in\": \".42 0 1 1\",\n \"ease-out\": \"0 0 .58 1\",\n \"ease-in-out\": \".42 0 .58 1\",\n }[name];\n}\n\n$.on = (element, event, selector, callback) => {\n if (!callback) {\n callback = selector;\n $.bind(element, event, callback);\n } else {\n $.delegate(element, event, selector, callback);\n }\n};\n\n$.off = (element, event, handler) => {\n element.removeEventListener(event, handler);\n};\n\n$.bind = (element, event, callback) => {\n event.split(/\\s+/).forEach(function (event) {\n element.addEventListener(event, callback);\n });\n};\n\n$.delegate = (element, event, selector, callback) => {\n element.addEventListener(event, function (e) {\n const delegatedTarget = e.target.closest(selector);\n if (delegatedTarget) {\n e.delegatedTarget = delegatedTarget;\n callback.call(this, e, delegatedTarget);\n }\n });\n};\n\n$.closest = (selector, element) => {\n if (!element) return null;\n\n if (element.matches(selector)) {\n return element;\n }\n\n return $.closest(selector, element.parentNode);\n};\n\n$.attr = (element, attr, value) => {\n if (!value && typeof attr === \"string\") {\n return element.getAttribute(attr);\n }\n\n if (typeof attr === \"object\") {\n for (let key in attr) {\n $.attr(element, key, attr[key]);\n }\n return;\n }\n\n element.setAttribute(attr, value);\n};\n","import date_utils from \"./date_utils\";\nimport { $, createSVG, animateSVG } from \"./svg_utils\";\n\nexport default class Bar {\n constructor(gantt, task) {\n this.set_defaults(gantt, task);\n this.prepare();\n this.draw();\n this.bind();\n }\n\n set_defaults(gantt, task) {\n this.action_completed = false;\n this.gantt = gantt;\n this.task = task;\n }\n\n prepare() {\n this.prepare_values();\n this.prepare_helpers();\n }\n\n prepare_values() {\n this.invalid = this.task.invalid;\n this.height = this.gantt.options.bar_height;\n this.compute_x();\n this.compute_y();\n this.compute_duration();\n this.corner_radius = this.gantt.options.bar_corner_radius;\n this.width = this.gantt.options.column_width * this.duration;\n this.progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.task.progress / 100) || 0;\n this.group = createSVG(\"g\", {\n class: \"bar-wrapper \" + (this.task.custom_class || \"\"),\n \"data-id\": this.task.id,\n });\n this.bar_group = createSVG(\"g\", {\n class: \"bar-group\",\n append_to: this.group,\n });\n this.handle_group = createSVG(\"g\", {\n class: \"handle-group\",\n append_to: this.group,\n });\n }\n\n prepare_helpers() {\n SVGElement.prototype.getX = function () {\n return +this.getAttribute(\"x\");\n };\n SVGElement.prototype.getY = function () {\n return +this.getAttribute(\"y\");\n };\n SVGElement.prototype.getWidth = function () {\n return +this.getAttribute(\"width\");\n };\n SVGElement.prototype.getHeight = function () {\n return +this.getAttribute(\"height\");\n };\n SVGElement.prototype.getEndX = function () {\n return this.getX() + this.getWidth();\n };\n }\n\n prepare_expected_progress_values() {\n this.compute_expected_progress();\n this.expected_progress_width =\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0;\n }\n\n draw() {\n this.draw_bar();\n if (this.gantt.options.show_expected_progress) {\n this.prepare_expected_progress_values();\n this.draw_expected_progress_bar();\n }\n this.draw_progress_bar();\n this.draw_label();\n this.draw_resize_handles();\n }\n\n draw_bar() {\n this.$bar = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar\",\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar, \"width\", 0, this.width);\n\n if (this.invalid) {\n this.$bar.classList.add(\"bar-invalid\");\n }\n }\n\n draw_expected_progress_bar() {\n if (this.invalid) return;\n this.$expected_bar_progress = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.expected_progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar-expected-progress\",\n append_to: this.bar_group,\n });\n\n animateSVG(\n this.$expected_bar_progress,\n \"width\",\n 0,\n this.expected_progress_width,\n );\n }\n\n draw_progress_bar() {\n if (this.invalid) return;\n this.$bar_progress = createSVG(\"rect\", {\n x: this.x,\n y: this.y,\n width: this.progress_width,\n height: this.height,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"bar-progress\",\n append_to: this.bar_group,\n });\n\n animateSVG(this.$bar_progress, \"width\", 0, this.progress_width);\n }\n\n draw_label() {\n createSVG(\"text\", {\n x: this.x + this.width / 2,\n y: this.y + this.height / 2,\n innerHTML: this.task.name,\n class: \"bar-label\",\n append_to: this.bar_group,\n });\n // labels get BBox in the next tick\n requestAnimationFrame(() => this.update_label_position());\n }\n\n draw_resize_handles() {\n if (this.invalid) return;\n\n const bar = this.$bar;\n const handle_width = 8;\n\n createSVG(\"rect\", {\n x: bar.getX() + bar.getWidth() - 9,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"handle right\",\n append_to: this.handle_group,\n });\n\n createSVG(\"rect\", {\n x: bar.getX() + 1,\n y: bar.getY() + 1,\n width: handle_width,\n height: this.height - 2,\n rx: this.corner_radius,\n ry: this.corner_radius,\n class: \"handle left\",\n append_to: this.handle_group,\n });\n\n this.$handle_progress = createSVG(\"polygon\", {\n points: this.get_progress_polygon_points().join(\",\"),\n class: \"handle progress\",\n append_to: this.handle_group,\n });\n }\n\n get_progress_polygon_points() {\n const bar_progress = this.$bar_progress;\n return [\n bar_progress.getEndX() - 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX() + 5,\n bar_progress.getY() + bar_progress.getHeight(),\n bar_progress.getEndX(),\n bar_progress.getY() + bar_progress.getHeight() - 8.66,\n ];\n }\n\n bind() {\n if (this.invalid) return;\n this.setup_click_event();\n }\n\n setup_click_event() {\n $.on(this.group, \"focus \" + this.gantt.options.popup_trigger, (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.show_popup();\n this.gantt.unselect_all();\n this.group.classList.add(\"active\");\n });\n\n $.on(this.group, \"dblclick\", (e) => {\n if (this.action_completed) {\n // just finished a move action, wait for a few seconds\n return;\n }\n\n this.gantt.trigger_event(\"click\", [this.task]);\n });\n }\n\n show_popup() {\n if (this.gantt.bar_being_dragged) return;\n\n const start_date = date_utils.format(\n this.task._start,\n \"MMM D\",\n this.gantt.options.language,\n );\n const end_date = date_utils.format(\n date_utils.add(this.task._end, -1, \"second\"),\n \"MMM D\",\n this.gantt.options.language,\n );\n const subtitle = start_date + \" - \" + end_date;\n\n this.gantt.show_popup({\n target_element: this.$bar,\n title: this.task.name,\n subtitle: subtitle,\n task: this.task,\n });\n }\n\n update_bar_position({ x = null, width = null }) {\n const bar = this.$bar;\n if (x) {\n // get all x values of parent task\n const xs = this.task.dependencies.map((dep) => {\n return this.gantt.get_bar(dep).$bar.getX();\n });\n // child task must not go before parent\n const valid_x = xs.reduce((prev, curr) => {\n return x >= curr;\n }, x);\n if (!valid_x) {\n width = null;\n return;\n }\n this.update_attr(bar, \"x\", x);\n }\n if (width) {\n this.update_attr(bar, \"width\", width);\n }\n this.update_label_position();\n this.update_handle_position();\n if (this.gantt.options.show_expected_progress) {\n this.date_changed();\n this.compute_duration();\n this.update_expected_progressbar_position();\n }\n this.update_progressbar_position();\n this.update_arrow_position();\n }\n\n date_changed() {\n let changed = false;\n const { new_start_date, new_end_date } = this.compute_start_end_date();\n\n if (Number(this.task._start) !== Number(new_start_date)) {\n changed = true;\n this.task._start = new_start_date;\n }\n\n if (Number(this.task._end) !== Number(new_end_date)) {\n changed = true;\n this.task._end = new_end_date;\n }\n\n if (!changed) return;\n\n this.gantt.trigger_event(\"date_change\", [\n this.task,\n new_start_date,\n date_utils.add(new_end_date, -1, \"second\"),\n ]);\n }\n\n progress_changed() {\n const new_progress = this.compute_progress();\n this.task.progress = new_progress;\n this.gantt.trigger_event(\"progress_change\", [this.task, new_progress]);\n }\n\n set_action_completed() {\n this.action_completed = true;\n setTimeout(() => (this.action_completed = false), 1000);\n }\n\n compute_start_end_date() {\n const bar = this.$bar;\n const x_in_units = bar.getX() / this.gantt.options.column_width;\n const new_start_date = date_utils.add(\n this.gantt.gantt_start,\n x_in_units * this.gantt.options.step,\n \"hour\",\n );\n const width_in_units = bar.getWidth() / this.gantt.options.column_width;\n const new_end_date = date_utils.add(\n new_start_date,\n width_in_units * this.gantt.options.step,\n \"hour\",\n );\n\n return { new_start_date, new_end_date };\n }\n\n compute_progress() {\n const progress =\n (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100;\n return parseInt(progress, 10);\n }\n\n compute_expected_progress() {\n this.expected_progress =\n date_utils.diff(date_utils.today(), this.task._start, \"hour\") /\n this.gantt.options.step;\n this.expected_progress =\n ((this.expected_progress < this.duration\n ? this.expected_progress\n : this.duration) *\n 100) /\n this.duration;\n }\n\n compute_x() {\n const { step, column_width } = this.gantt.options;\n const task_start = this.task._start;\n const gantt_start = this.gantt.gantt_start;\n\n const diff = date_utils.diff(task_start, gantt_start, \"hour\");\n let x = (diff / step) * column_width;\n\n if (this.gantt.view_is(\"Month\")) {\n const diff = date_utils.diff(task_start, gantt_start, \"day\");\n x = (diff * column_width) / 30;\n }\n this.x = x;\n }\n\n compute_y() {\n this.y =\n this.gantt.options.header_height +\n this.gantt.options.padding +\n this.task._index * (this.height + this.gantt.options.padding);\n }\n\n compute_duration() {\n this.duration =\n date_utils.diff(this.task._end, this.task._start, \"hour\") /\n this.gantt.options.step;\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.gantt.view_is(\"Week\")) {\n rem = dx % (this.gantt.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 14\n ? 0\n : this.gantt.options.column_width / 7);\n } else if (this.gantt.view_is(\"Month\")) {\n rem = dx % (this.gantt.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 60\n ? 0\n : this.gantt.options.column_width / 30);\n } else {\n rem = dx % this.gantt.options.column_width;\n position =\n odx -\n rem +\n (rem < this.gantt.options.column_width / 2\n ? 0\n : this.gantt.options.column_width);\n }\n return position;\n }\n\n update_attr(element, attr, value) {\n value = +value;\n if (!isNaN(value)) {\n element.setAttribute(attr, value);\n }\n return element;\n }\n\n update_expected_progressbar_position() {\n if (this.invalid) return;\n this.$expected_bar_progress.setAttribute(\"x\", this.$bar.getX());\n this.compute_expected_progress();\n this.$expected_bar_progress.setAttribute(\n \"width\",\n this.gantt.options.column_width *\n this.duration *\n (this.expected_progress / 100) || 0,\n );\n }\n\n update_progressbar_position() {\n if (this.invalid) return;\n this.$bar_progress.setAttribute(\"x\", this.$bar.getX());\n this.$bar_progress.setAttribute(\n \"width\",\n this.$bar.getWidth() * (this.task.progress / 100),\n );\n }\n\n update_label_position() {\n const bar = this.$bar,\n label = this.group.querySelector(\".bar-label\");\n\n if (label.getBBox().width > bar.getWidth()) {\n label.classList.add(\"big\");\n label.setAttribute(\"x\", bar.getX() + bar.getWidth() + 5);\n } else {\n label.classList.remove(\"big\");\n label.setAttribute(\"x\", bar.getX() + bar.getWidth() / 2);\n }\n }\n\n update_handle_position() {\n if (this.invalid) return;\n const bar = this.$bar;\n this.handle_group\n .querySelector(\".handle.left\")\n .setAttribute(\"x\", bar.getX() + 1);\n this.handle_group\n .querySelector(\".handle.right\")\n .setAttribute(\"x\", bar.getEndX() - 9);\n const handle = this.group.querySelector(\".handle.progress\");\n handle && handle.setAttribute(\"points\", this.get_progress_polygon_points());\n }\n\n update_arrow_position() {\n this.arrows = this.arrows || [];\n for (let arrow of this.arrows) {\n arrow.update();\n }\n }\n}\n\nfunction isFunction(functionToCheck) {\n var getType = {};\n return (\n functionToCheck &&\n getType.toString.call(functionToCheck) === \"[object Function]\"\n );\n}\n","import { createSVG } from \"./svg_utils\";\n\nexport default class Arrow {\n constructor(gantt, from_task, to_task) {\n this.gantt = gantt;\n this.from_task = from_task;\n this.to_task = to_task;\n\n this.calculate_path();\n this.draw();\n }\n\n calculate_path() {\n let start_x =\n this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2;\n\n const condition = () =>\n this.to_task.$bar.getX() < start_x + this.gantt.options.padding &&\n start_x > this.from_task.$bar.getX() + this.gantt.options.padding;\n\n while (condition()) {\n start_x -= 10;\n }\n\n const start_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.from_task.task._index +\n this.gantt.options.padding;\n\n const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2;\n const end_y =\n this.gantt.options.header_height +\n this.gantt.options.bar_height / 2 +\n (this.gantt.options.padding + this.gantt.options.bar_height) *\n this.to_task.task._index +\n this.gantt.options.padding;\n\n const from_is_below_to =\n this.from_task.task._index > this.to_task.task._index;\n const curve = this.gantt.options.arrow_curve;\n const clockwise = from_is_below_to ? 1 : 0;\n const curve_y = from_is_below_to ? -curve : curve;\n const offset = from_is_below_to\n ? end_y + this.gantt.options.arrow_curve\n : end_y - this.gantt.options.arrow_curve;\n\n this.path = `\n M ${start_x} ${start_y}\n V ${offset}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n\n if (\n this.to_task.$bar.getX() <\n this.from_task.$bar.getX() + this.gantt.options.padding\n ) {\n const down_1 = this.gantt.options.padding / 2 - curve;\n const down_2 =\n this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - curve_y;\n const left = this.to_task.$bar.getX() - this.gantt.options.padding;\n\n this.path = `\n M ${start_x} ${start_y}\n v ${down_1}\n a ${curve} ${curve} 0 0 1 -${curve} ${curve}\n H ${left}\n a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curve_y}\n V ${down_2}\n a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y}\n L ${end_x} ${end_y}\n m -5 -5\n l 5 5\n l -5 5`;\n }\n }\n\n draw() {\n this.element = createSVG(\"path\", {\n d: this.path,\n \"data-from\": this.from_task.task.id,\n \"data-to\": this.to_task.task.id,\n });\n }\n\n update() {\n this.calculate_path();\n this.element.setAttribute(\"d\", this.path);\n }\n}\n","export default class Popup {\n constructor(parent, custom_html) {\n this.parent = parent;\n this.custom_html = custom_html;\n this.make();\n }\n\n make() {\n this.parent.innerHTML = `\n
\n
\n
\n `;\n\n this.hide();\n\n this.title = this.parent.querySelector(\".title\");\n this.subtitle = this.parent.querySelector(\".subtitle\");\n this.pointer = this.parent.querySelector(\".pointer\");\n }\n\n show(options) {\n if (!options.target_element) {\n throw new Error(\"target_element is required to show popup\");\n }\n if (!options.position) {\n options.position = \"left\";\n }\n const target_element = options.target_element;\n\n if (this.custom_html) {\n let html = this.custom_html(options.task);\n html += '
';\n this.parent.innerHTML = html;\n this.pointer = this.parent.querySelector(\".pointer\");\n } else {\n // set data\n this.title.innerHTML = options.title;\n this.subtitle.innerHTML = options.subtitle;\n this.parent.style.width = this.parent.clientWidth + \"px\";\n }\n\n // set position\n let position_meta;\n if (target_element instanceof HTMLElement) {\n position_meta = target_element.getBoundingClientRect();\n } else if (target_element instanceof SVGElement) {\n position_meta = options.target_element.getBBox();\n }\n\n if (options.position === \"left\") {\n this.parent.style.left =\n position_meta.x + (position_meta.width + 10) + \"px\";\n this.parent.style.top = position_meta.y + \"px\";\n\n this.pointer.style.transform = \"rotateZ(90deg)\";\n this.pointer.style.left = \"-7px\";\n this.pointer.style.top = \"2px\";\n }\n\n // show\n this.parent.style.opacity = 1;\n }\n\n hide() {\n this.parent.style.opacity = 0;\n this.parent.style.left = 0;\n }\n}\n","import date_utils from \"./date_utils\";\nimport { $, createSVG } from \"./svg_utils\";\nimport Bar from \"./bar\";\nimport Arrow from \"./arrow\";\nimport Popup from \"./popup\";\n\nimport \"./gantt.scss\";\n\nconst VIEW_MODE = {\n HOUR: \"Hour\",\n QUARTER_DAY: \"Quarter Day\",\n HALF_DAY: \"Half Day\",\n DAY: \"Day\",\n WEEK: \"Week\",\n MONTH: \"Month\",\n YEAR: \"Year\",\n};\n\nconst VIEW_MODE_PADDING = {\n HOUR: [\"7d\", \"7d\"],\n QUARTER_DAY: [\"7d\", \"7d\"],\n HALF_DAY: [\"7d\", \"7d\"],\n DAY: [\"1m\", \"1m\"],\n WEEK: [\"1m\", \"1m\"],\n MONTH: [\"1m\", \"1m\"],\n YEAR: [\"2y\", \"2y\"],\n};\n\nexport default class Gantt {\n constructor(wrapper, tasks, options) {\n this.setup_wrapper(wrapper);\n this.setup_options(options);\n this.setup_tasks(tasks);\n // initialize with default view mode\n this.change_view_mode();\n this.bind_events();\n }\n\n setup_wrapper(element) {\n let svg_element, wrapper_element;\n\n // CSS Selector is passed\n if (typeof element === \"string\") {\n element = document.querySelector(element);\n }\n\n // get the SVGElement\n if (element instanceof HTMLElement) {\n wrapper_element = element;\n svg_element = element.querySelector(\"svg\");\n } else if (element instanceof SVGElement) {\n svg_element = element;\n } else {\n throw new TypeError(\n \"Frappé Gantt only supports usage of a string CSS selector,\" +\n \" HTML DOM element or SVG DOM element for the 'element' parameter\",\n );\n }\n\n // svg element\n if (!svg_element) {\n // create it\n this.$svg = createSVG(\"svg\", {\n append_to: wrapper_element,\n class: \"gantt\",\n });\n } else {\n this.$svg = svg_element;\n this.$svg.classList.add(\"gantt\");\n }\n\n // wrapper element\n this.$container = document.createElement(\"div\");\n this.$container.classList.add(\"gantt-container\");\n\n const parent_element = this.$svg.parentElement;\n parent_element.appendChild(this.$container);\n this.$container.appendChild(this.$svg);\n\n // popup wrapper\n this.popup_wrapper = document.createElement(\"div\");\n this.popup_wrapper.classList.add(\"popup-wrapper\");\n this.$container.appendChild(this.popup_wrapper);\n }\n\n setup_options(options) {\n const default_options = {\n header_height: 50,\n column_width: 30,\n step: 24,\n view_modes: [...Object.values(VIEW_MODE)],\n bar_height: 20,\n bar_corner_radius: 3,\n arrow_curve: 5,\n padding: 18,\n view_mode: \"Day\",\n date_format: \"YYYY-MM-DD\",\n popup_trigger: \"click\",\n custom_popup_html: null,\n language: \"en\",\n };\n this.options = Object.assign({}, default_options, options);\n for (let [key, value] of Object.entries(options.view_mode_padding)) {\n if (typeof value === \"string\") {\n // Configure for single value given\n options.view_mode_padding[key] = [value, value];\n }\n }\n\n console.log(options.view_mode_padding);\n this.options.view_mode_padding = {\n ...VIEW_MODE_PADDING,\n ...options.view_mode_padding,\n };\n }\n\n setup_tasks(tasks) {\n // prepare tasks\n this.tasks = tasks.map((task, i) => {\n // convert to Date objects\n task._start = date_utils.parse(task.start);\n if (task.end === undefined && task.duration !== undefined) {\n task.end = task._start;\n let durations = task.duration.split(\" \");\n\n durations.forEach((tmpDuration) => {\n let { duration, scale } = date_utils.parse_duration(tmpDuration);\n task.end = date_utils.add(task.end, duration, scale);\n });\n }\n task._end = date_utils.parse(task.end);\n\n // make task invalid if duration too large\n if (date_utils.diff(task._end, task._start, \"year\") > 10) {\n task.end = null;\n }\n\n // cache index\n task._index = i;\n\n // invalid dates\n if (!task.start && !task.end) {\n const today = date_utils.today();\n task._start = today;\n task._end = date_utils.add(today, 2, \"day\");\n }\n\n if (!task.start && task.end) {\n task._start = date_utils.add(task._end, -2, \"day\");\n }\n\n if (task.start && !task.end) {\n task._end = date_utils.add(task._start, 2, \"day\");\n }\n\n // if hours is not set, assume the last day is full day\n // e.g: 2018-09-09 becomes 2018-09-09 23:59:59\n const task_end_values = date_utils.get_date_values(task._end);\n if (task_end_values.slice(3).every((d) => d === 0)) {\n task._end = date_utils.add(task._end, 24, \"hour\");\n }\n\n // invalid flag\n if (!task.start || !task.end) {\n task.invalid = true;\n }\n\n // dependencies\n if (typeof task.dependencies === \"string\" || !task.dependencies) {\n let deps = [];\n if (task.dependencies) {\n deps = task.dependencies\n .split(\",\")\n .map((d) => d.trim())\n .filter((d) => d);\n }\n task.dependencies = deps;\n }\n\n // uids\n if (!task.id) {\n task.id = generate_id(task);\n }\n\n return task;\n });\n\n this.setup_dependencies();\n }\n\n setup_dependencies() {\n this.dependency_map = {};\n for (let t of this.tasks) {\n for (let d of t.dependencies) {\n this.dependency_map[d] = this.dependency_map[d] || [];\n this.dependency_map[d].push(t.id);\n }\n }\n }\n\n refresh(tasks) {\n this.setup_tasks(tasks);\n this.change_view_mode();\n }\n\n change_view_mode(mode = this.options.view_mode) {\n this.update_view_scale(mode);\n this.setup_dates();\n this.render();\n // fire viewmode_change event\n this.trigger_event(\"view_change\", [mode]);\n }\n\n update_view_scale(view_mode) {\n this.options.view_mode = view_mode;\n if (view_mode === VIEW_MODE.HOUR) {\n this.options.step = 24 / 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.DAY) {\n this.options.step = 24;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.HALF_DAY) {\n this.options.step = 24 / 2;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.QUARTER_DAY) {\n this.options.step = 24 / 4;\n this.options.column_width = 38;\n } else if (view_mode === VIEW_MODE.WEEK) {\n this.options.step = 24 * 7;\n this.options.column_width = 140;\n } else if (view_mode === VIEW_MODE.MONTH) {\n this.options.step = 24 * 30;\n this.options.column_width = 120;\n } else if (view_mode === VIEW_MODE.YEAR) {\n this.options.step = 24 * 365;\n this.options.column_width = 120;\n }\n }\n\n setup_dates() {\n this.setup_gantt_dates();\n this.setup_date_values();\n }\n\n setup_gantt_dates() {\n this.gantt_start = this.gantt_end = null;\n\n for (let task of this.tasks) {\n // set global start and end date\n if (!this.gantt_start || task._start < this.gantt_start) {\n this.gantt_start = task._start;\n }\n if (!this.gantt_end || task._end > this.gantt_end) {\n this.gantt_end = task._end;\n }\n }\n\n let gantt_start = date_utils.start_of(this.gantt_start, \"day\");\n let gantt_end = date_utils.start_of(this.gantt_end, \"day\");\n // add date padding on both sides\n let viewKey;\n for (let [key, value] of Object.entries(VIEW_MODE)) {\n if (value === this.options.view_mode) {\n viewKey = key;\n }\n }\n const [padding_start, padding_end] = this.options.view_mode_padding[\n viewKey\n ].map(date_utils.parse_duration);\n this.gantt_start = date_utils.add(\n gantt_start,\n -padding_start.duration,\n padding_start.scale,\n );\n this.gantt_end = date_utils.add(\n gantt_end,\n padding_end.duration,\n padding_end.scale,\n );\n }\n\n setup_date_values() {\n this.dates = [];\n let cur_date = null;\n\n while (cur_date === null || cur_date < this.gantt_end) {\n if (!cur_date) {\n cur_date = date_utils.clone(this.gantt_start);\n } else {\n if (this.view_is(VIEW_MODE.YEAR)) {\n cur_date = date_utils.add(cur_date, 1, \"year\");\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n cur_date = date_utils.add(cur_date, 1, \"month\");\n } else {\n cur_date = date_utils.add(cur_date, this.options.step, \"hour\");\n }\n }\n this.dates.push(cur_date);\n }\n }\n\n bind_events() {\n this.bind_grid_click();\n this.bind_bar_events();\n }\n\n render() {\n this.clear();\n this.setup_layers();\n this.make_grid();\n this.make_dates();\n this.make_bars();\n this.make_arrows();\n this.map_arrows_on_bars();\n this.set_width();\n this.set_scroll_position();\n }\n\n setup_layers() {\n this.layers = {};\n const layers = [\"grid\", \"date\", \"arrow\", \"progress\", \"bar\", \"details\"];\n // make group layers\n for (let layer of layers) {\n this.layers[layer] = createSVG(\"g\", {\n class: layer,\n append_to: this.$svg,\n });\n }\n }\n\n make_grid() {\n this.make_grid_background();\n this.make_grid_rows();\n this.make_grid_header();\n this.make_grid_ticks();\n this.make_grid_highlights();\n }\n\n make_grid_background() {\n const grid_width = this.dates.length * this.options.column_width;\n const grid_height =\n this.options.header_height +\n this.options.padding +\n (this.options.bar_height + this.options.padding) * this.tasks.length;\n\n createSVG(\"rect\", {\n x: 0,\n y: 0,\n width: grid_width,\n height: grid_height,\n class: \"grid-background\",\n append_to: this.layers.grid,\n });\n\n $.attr(this.$svg, {\n height: grid_height + this.options.padding + 100,\n width: \"100%\",\n });\n }\n\n make_grid_rows() {\n const rows_layer = createSVG(\"g\", { append_to: this.layers.grid });\n const lines_layer = createSVG(\"g\", { append_to: this.layers.grid });\n\n const row_width = this.dates.length * this.options.column_width;\n const row_height = this.options.bar_height + this.options.padding;\n\n let row_y = this.options.header_height + this.options.padding / 2;\n\n for (let task of this.tasks) {\n createSVG(\"rect\", {\n x: 0,\n y: row_y,\n width: row_width,\n height: row_height,\n class: \"grid-row\",\n append_to: rows_layer,\n });\n\n createSVG(\"line\", {\n x1: 0,\n y1: row_y + row_height,\n x2: row_width,\n y2: row_y + row_height,\n class: \"row-line\",\n append_to: lines_layer,\n });\n\n row_y += this.options.bar_height + this.options.padding;\n }\n }\n\n make_grid_header() {\n const header_width = this.dates.length * this.options.column_width;\n const header_height = this.options.header_height + 10;\n createSVG(\"rect\", {\n x: 0,\n y: 0,\n width: header_width,\n height: header_height,\n class: \"grid-header\",\n append_to: this.layers.grid,\n });\n }\n\n make_grid_ticks() {\n let tick_x = 0;\n let tick_y = this.options.header_height + this.options.padding / 2;\n let tick_height =\n (this.options.bar_height + this.options.padding) * this.tasks.length;\n\n for (let date of this.dates) {\n let tick_class = \"tick\";\n // thick tick for monday\n if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) {\n tick_class += \" thick\";\n }\n // thick tick for first week\n if (\n this.view_is(VIEW_MODE.WEEK) &&\n date.getDate() >= 1 &&\n date.getDate() < 8\n ) {\n tick_class += \" thick\";\n }\n // thick ticks for quarters\n if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) {\n tick_class += \" thick\";\n }\n\n createSVG(\"path\", {\n d: `M ${tick_x} ${tick_y} v ${tick_height}`,\n class: tick_class,\n append_to: this.layers.grid,\n });\n\n if (this.view_is(VIEW_MODE.MONTH)) {\n tick_x +=\n (date_utils.get_days_in_month(date) * this.options.column_width) / 30;\n } else {\n tick_x += this.options.column_width;\n }\n }\n }\n\n //compute the horizontal x distance\n computeGridHighlightDimensions(view_mode) {\n let xDist = 0;\n\n if (this.view_is(VIEW_MODE.DAY)) {\n return (\n (date_utils.diff(date_utils.today(), this.gantt_start, \"hour\") /\n this.options.step) *\n this.options.column_width\n );\n }\n\n for (let date of this.dates) {\n const todayDate = new Date();\n const startDate = new Date(date);\n const endDate = new Date(date);\n switch (view_mode) {\n case VIEW_MODE.WEEK:\n endDate.setDate(date.getDate() + 7);\n break;\n case VIEW_MODE.MONTH:\n endDate.setMonth(date.getMonth() + 1);\n break;\n case VIEW_MODE.YEAR:\n endDate.setFullYear(date.getFullYear() + 1);\n break;\n }\n if (todayDate >= startDate && todayDate <= endDate) {\n break;\n } else {\n xDist += this.options.column_width;\n }\n }\n return xDist;\n }\n\n make_grid_highlights() {\n // highlight today's | week's | month's | year's\n if (\n this.view_is(VIEW_MODE.DAY) ||\n this.view_is(VIEW_MODE.WEEK) ||\n this.view_is(VIEW_MODE.MONTH) ||\n this.view_is(VIEW_MODE.YEAR)\n ) {\n const x = this.computeGridHighlightDimensions(this.options.view_mode);\n const y = 0;\n const width = this.options.column_width;\n const height =\n (this.options.bar_height + this.options.padding) * this.tasks.length +\n this.options.header_height +\n this.options.padding / 2;\n\n let className = \"\";\n switch (this.options.view_mode) {\n case VIEW_MODE.DAY:\n className = \"today-highlight\";\n break;\n case VIEW_MODE.WEEK:\n className = \"week-highlight\";\n break;\n case VIEW_MODE.MONTH:\n className = \"month-highlight\";\n break;\n case VIEW_MODE.YEAR:\n className = \"year-highlight\";\n break;\n }\n createSVG(\"rect\", {\n x,\n y,\n width,\n height,\n class: className,\n append_to: this.layers.grid,\n });\n }\n }\n\n make_dates() {\n for (let date of this.get_dates_to_draw()) {\n createSVG(\"text\", {\n x: date.lower_x,\n y: date.lower_y,\n innerHTML: date.lower_text,\n class: \"lower-text\",\n append_to: this.layers.date,\n });\n\n if (date.upper_text) {\n const $upper_text = createSVG(\"text\", {\n x: date.upper_x,\n y: date.upper_y,\n innerHTML: date.upper_text,\n class: \"upper-text\",\n append_to: this.layers.date,\n });\n\n // remove out-of-bound dates\n if ($upper_text.getBBox().x2 > this.layers.grid.getBBox().width) {\n $upper_text.remove();\n }\n }\n }\n }\n\n get_dates_to_draw() {\n let last_date = null;\n const dates = this.dates.map((date, i) => {\n const d = this.get_date_info(date, last_date, i);\n last_date = date;\n return d;\n });\n return dates;\n }\n\n get_date_info(date, last_date, i) {\n if (!last_date) {\n last_date = date_utils.add(date, 1, \"day\");\n }\n const date_text = {\n Hour_lower: date_utils.format(date, \"HH\", this.options.language),\n \"Quarter Day_lower\": date_utils.format(date, \"HH\", this.options.language),\n \"Half Day_lower\": date_utils.format(date, \"HH\", this.options.language),\n Day_lower:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D\", this.options.language)\n : \"\",\n Week_lower:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : date_utils.format(date, \"D\", this.options.language),\n Month_lower: date_utils.format(date, \"MMMM\", this.options.language),\n Year_lower: date_utils.format(date, \"YYYY\", this.options.language),\n Hour_upper:\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D MMMM\", this.options.language)\n : \"\",\n \"Quarter Day_upper\":\n date.getDate() !== last_date.getDate()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : \"\",\n \"Half Day_upper\":\n date.getDate() !== last_date.getDate()\n ? date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"D MMM\", this.options.language)\n : date_utils.format(date, \"D\", this.options.language)\n : \"\",\n Day_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"MMMM\", this.options.language)\n : \"\",\n Week_upper:\n date.getMonth() !== last_date.getMonth()\n ? date_utils.format(date, \"MMMM\", this.options.language)\n : \"\",\n Month_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, \"YYYY\", this.options.language)\n : \"\",\n Year_upper:\n date.getFullYear() !== last_date.getFullYear()\n ? date_utils.format(date, \"YYYY\", this.options.language)\n : \"\",\n };\n\n const base_pos = {\n x: i * this.options.column_width,\n lower_y: this.options.header_height,\n upper_y: this.options.header_height - 25,\n };\n\n const x_pos = {\n Hour_lower: this.options.column_width / 2,\n Hour_upper: this.options.column_width * 12,\n \"Quarter Day_lower\": this.options.column_width / 2,\n \"Quarter Day_upper\": this.options.column_width * 2,\n \"Half Day_lower\": this.options.column_width / 2,\n \"Half Day_upper\": this.options.column_width,\n Day_lower: this.options.column_width / 2,\n Day_upper: (this.options.column_width * 30) / 2,\n Week_lower: 0,\n Week_upper: (this.options.column_width * 4) / 2,\n Month_lower: this.options.column_width / 2,\n Month_upper: (this.options.column_width * 12) / 2,\n Year_lower: this.options.column_width / 2,\n Year_upper: (this.options.column_width * 30) / 2,\n };\n\n return {\n upper_text: date_text[`${this.options.view_mode}_upper`],\n lower_text: date_text[`${this.options.view_mode}_lower`],\n upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`],\n upper_y: base_pos.upper_y,\n lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`],\n lower_y: base_pos.lower_y,\n };\n }\n\n make_bars() {\n this.bars = this.tasks.map((task) => {\n const bar = new Bar(this, task);\n this.layers.bar.appendChild(bar.group);\n return bar;\n });\n }\n\n make_arrows() {\n this.arrows = [];\n for (let task of this.tasks) {\n let arrows = [];\n arrows = task.dependencies\n .map((task_id) => {\n const dependency = this.get_task(task_id);\n if (!dependency) return;\n const arrow = new Arrow(\n this,\n this.bars[dependency._index], // from_task\n this.bars[task._index], // to_task\n );\n this.layers.arrow.appendChild(arrow.element);\n return arrow;\n })\n .filter(Boolean); // filter falsy values\n this.arrows = this.arrows.concat(arrows);\n }\n }\n\n map_arrows_on_bars() {\n for (let bar of this.bars) {\n bar.arrows = this.arrows.filter((arrow) => {\n return (\n arrow.from_task.task.id === bar.task.id ||\n arrow.to_task.task.id === bar.task.id\n );\n });\n }\n }\n\n set_width() {\n const cur_width = this.$svg.getBoundingClientRect().width;\n const actual_width = this.$svg\n .querySelector(\".grid .grid-row\")\n .getAttribute(\"width\");\n if (cur_width < actual_width) {\n this.$svg.setAttribute(\"width\", actual_width);\n }\n }\n\n set_scroll_position() {\n const parent_element = this.$svg.parentElement;\n if (!parent_element) return;\n\n const hours_before_first_task = date_utils.diff(\n this.get_oldest_starting_date(),\n this.gantt_start,\n \"hour\",\n );\n\n const scroll_pos =\n (hours_before_first_task / this.options.step) *\n this.options.column_width -\n this.options.column_width;\n\n parent_element.scrollLeft = scroll_pos;\n }\n\n bind_grid_click() {\n $.on(\n this.$svg,\n this.options.popup_trigger,\n \".grid-row, .grid-header\",\n () => {\n this.unselect_all();\n this.hide_popup();\n },\n );\n }\n\n bind_bar_events() {\n let is_dragging = false;\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing_left = false;\n let is_resizing_right = false;\n let parent_bar_id = null;\n let bars = []; // instanceof Bar\n this.bar_being_dragged = null;\n\n function action_in_progress() {\n return is_dragging || is_resizing_left || is_resizing_right;\n }\n\n $.on(this.$svg, \"mousedown\", \".bar-wrapper, .handle\", (e, element) => {\n const bar_wrapper = $.closest(\".bar-wrapper\", element);\n\n if (element.classList.contains(\"left\")) {\n is_resizing_left = true;\n } else if (element.classList.contains(\"right\")) {\n is_resizing_right = true;\n } else if (element.classList.contains(\"bar-wrapper\")) {\n is_dragging = true;\n }\n\n bar_wrapper.classList.add(\"active\");\n\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n parent_bar_id = bar_wrapper.getAttribute(\"data-id\");\n const ids = [\n parent_bar_id,\n ...this.get_all_dependent_tasks(parent_bar_id),\n ];\n bars = ids.map((id) => this.get_bar(id));\n\n this.bar_being_dragged = parent_bar_id;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.ox = $bar.getX();\n $bar.oy = $bar.getY();\n $bar.owidth = $bar.getWidth();\n $bar.finaldx = 0;\n });\n });\n\n $.on(this.$svg, \"mousemove\", (e) => {\n if (!action_in_progress()) return;\n const dx = e.offsetX - x_on_start;\n const dy = e.offsetY - y_on_start;\n\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n $bar.finaldx = this.get_snap_position(dx);\n this.hide_popup();\n if (is_resizing_left) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n width: $bar.owidth - $bar.finaldx,\n });\n } else {\n bar.update_bar_position({\n x: $bar.ox + $bar.finaldx,\n });\n }\n } else if (is_resizing_right) {\n if (parent_bar_id === bar.task.id) {\n bar.update_bar_position({\n width: $bar.owidth + $bar.finaldx,\n });\n }\n } else if (is_dragging) {\n bar.update_bar_position({ x: $bar.ox + $bar.finaldx });\n }\n });\n });\n\n document.addEventListener(\"mouseup\", (e) => {\n if (is_dragging || is_resizing_left || is_resizing_right) {\n bars.forEach((bar) => bar.group.classList.remove(\"active\"));\n }\n\n is_dragging = false;\n is_resizing_left = false;\n is_resizing_right = false;\n });\n\n $.on(this.$svg, \"mouseup\", (e) => {\n this.bar_being_dragged = null;\n bars.forEach((bar) => {\n const $bar = bar.$bar;\n if (!$bar.finaldx) return;\n bar.date_changed();\n bar.set_action_completed();\n });\n });\n\n this.bind_bar_progress();\n }\n\n bind_bar_progress() {\n let x_on_start = 0;\n let y_on_start = 0;\n let is_resizing = null;\n let bar = null;\n let $bar_progress = null;\n let $bar = null;\n\n $.on(this.$svg, \"mousedown\", \".handle.progress\", (e, handle) => {\n is_resizing = true;\n x_on_start = e.offsetX;\n y_on_start = e.offsetY;\n\n const $bar_wrapper = $.closest(\".bar-wrapper\", handle);\n const id = $bar_wrapper.getAttribute(\"data-id\");\n bar = this.get_bar(id);\n\n $bar_progress = bar.$bar_progress;\n $bar = bar.$bar;\n\n $bar_progress.finaldx = 0;\n $bar_progress.owidth = $bar_progress.getWidth();\n $bar_progress.min_dx = -$bar_progress.getWidth();\n $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth();\n });\n\n $.on(this.$svg, \"mousemove\", (e) => {\n if (!is_resizing) return;\n let dx = e.offsetX - x_on_start;\n let dy = e.offsetY - y_on_start;\n\n if (dx > $bar_progress.max_dx) {\n dx = $bar_progress.max_dx;\n }\n if (dx < $bar_progress.min_dx) {\n dx = $bar_progress.min_dx;\n }\n\n const $handle = bar.$handle_progress;\n $.attr($bar_progress, \"width\", $bar_progress.owidth + dx);\n $.attr($handle, \"points\", bar.get_progress_polygon_points());\n $bar_progress.finaldx = dx;\n });\n\n $.on(this.$svg, \"mouseup\", () => {\n is_resizing = false;\n if (!($bar_progress && $bar_progress.finaldx)) return;\n bar.progress_changed();\n bar.set_action_completed();\n });\n }\n\n get_all_dependent_tasks(task_id) {\n let out = [];\n let to_process = [task_id];\n while (to_process.length) {\n const deps = to_process.reduce((acc, curr) => {\n acc = acc.concat(this.dependency_map[curr]);\n return acc;\n }, []);\n\n out = out.concat(deps);\n to_process = deps.filter((d) => !to_process.includes(d));\n }\n\n return out.filter(Boolean);\n }\n\n get_snap_position(dx) {\n let odx = dx,\n rem,\n position;\n\n if (this.view_is(VIEW_MODE.WEEK)) {\n rem = dx % (this.options.column_width / 7);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 14\n ? 0\n : this.options.column_width / 7);\n } else if (this.view_is(VIEW_MODE.MONTH)) {\n rem = dx % (this.options.column_width / 30);\n position =\n odx -\n rem +\n (rem < this.options.column_width / 60\n ? 0\n : this.options.column_width / 30);\n } else {\n rem = dx % this.options.column_width;\n position =\n odx -\n rem +\n (rem < this.options.column_width / 2 ? 0 : this.options.column_width);\n }\n return position;\n }\n\n unselect_all() {\n [...this.$svg.querySelectorAll(\".bar-wrapper\")].forEach((el) => {\n el.classList.remove(\"active\");\n });\n }\n\n view_is(modes) {\n if (typeof modes === \"string\") {\n return this.options.view_mode === modes;\n }\n\n if (Array.isArray(modes)) {\n return modes.some((mode) => this.options.view_mode === mode);\n }\n\n return false;\n }\n\n get_task(id) {\n return this.tasks.find((task) => {\n return task.id === id;\n });\n }\n\n get_bar(id) {\n return this.bars.find((bar) => {\n return bar.task.id === id;\n });\n }\n\n show_popup(options) {\n if (!this.popup) {\n this.popup = new Popup(\n this.popup_wrapper,\n this.options.custom_popup_html,\n );\n }\n this.popup.show(options);\n }\n\n hide_popup() {\n this.popup && this.popup.hide();\n }\n\n trigger_event(event, args) {\n if (this.options[\"on_\" + event]) {\n this.options[\"on_\" + event].apply(null, args);\n }\n }\n\n /**\n * Gets the oldest starting date from the list of tasks\n *\n * @returns Date\n * @memberof Gantt\n */\n get_oldest_starting_date() {\n return this.tasks\n .map((task) => task._start)\n .reduce((prev_date, cur_date) =>\n cur_date <= prev_date ? cur_date : prev_date,\n );\n }\n\n /**\n * Clear all elements from the parent svg element\n *\n * @memberof Gantt\n */\n clear() {\n this.$svg.innerHTML = \"\";\n }\n}\n\nGantt.VIEW_MODE = VIEW_MODE;\n\nfunction generate_id(task) {\n return task.name + \"_\" + Math.random().toString(36).slice(2, 12);\n}\n"],"names":["YEAR","MONTH","DAY","HOUR","MINUTE","SECOND","MILLISECOND","date_utils","parse_duration","duration","matches","exec","parseInt","scale","parse","date","date_separator","time_separator","Date","date_parts","time_parts","parts","split","map","val","vals","length","parseFloat","concat","to_string","with_time","TypeError","this","get_date_values","i","padStart","date_string","time_string","format","format_string","lang","month_name","Intl","DateTimeFormat","month","month_name_capitalized","charAt","toUpperCase","slice","values","d","format_map","YYYY","MM","DD","HH","mm","ss","SSS","D","MMMM","MMM","str","formatted_values","Object","keys","sort","a","b","forEach","key","includes","replace","push","value","diff","date_a","date_b","milliseconds","seconds","hours","minutes","days","months","years","endsWith","Math","floor","today","now","add","qty","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getMilliseconds","start_of","scores","should_reset","_scale","clone","get_days_in_month","no_of_days","year","targetLength","padString","String","repeat","$","expr","con","document","querySelector","createSVG","tag","attrs","elem","createElementNS","attr","append_to","appendChild","innerHTML","setAttribute","animateSVG","svgElement","from","to","animatedSvgElement","dur","begin","animEl","attributeName","animateElement","calcMode","keyTimes","keySplines","cubic_bezier","getAnimationElement","event","createEvent","initEvent","eventName","dispatchEvent","name","ease","linear","on","element","selector","callback","delegate","bind","off","handler","removeEventListener","addEventListener","e","delegatedTarget","target","closest","call","parentNode","getAttribute","Bar","constructor","gantt","task","set_defaults","prepare","draw","action_completed","prepare_values","prepare_helpers","invalid","height","options","bar_height","compute_x","compute_y","compute_duration","corner_radius","bar_corner_radius","width","column_width","progress_width","progress","group","class","custom_class","id","bar_group","handle_group","SVGElement","prototype","getX","getY","getWidth","getHeight","getEndX","prepare_expected_progress_values","compute_expected_progress","expected_progress_width","expected_progress","draw_bar","show_expected_progress","draw_expected_progress_bar","draw_progress_bar","draw_label","draw_resize_handles","$bar","x","y","rx","ry","classList","$expected_bar_progress","$bar_progress","requestAnimationFrame","update_label_position","bar","$handle_progress","points","get_progress_polygon_points","join","bar_progress","setup_click_event","popup_trigger","show_popup","unselect_all","trigger_event","bar_being_dragged","subtitle","_start","language","_end","target_element","title","update_bar_position","dependencies","dep","get_bar","reduce","prev","curr","update_attr","update_handle_position","date_changed","update_expected_progressbar_position","update_progressbar_position","update_arrow_position","changed","new_start_date","new_end_date","compute_start_end_date","Number","progress_changed","new_progress","compute_progress","set_action_completed","setTimeout","x_in_units","gantt_start","step","width_in_units","task_start","view_is","header_height","padding","_index","get_snap_position","dx","rem","position","odx","isNaN","label","getBBox","remove","handle","arrows","arrow","update","Arrow","from_task","to_task","calculate_path","start_x","condition","start_y","end_x","end_y","from_is_below_to","curve","arrow_curve","clockwise","curve_y","offset","path","down_1","down_2","left","Popup","parent","custom_html","make","hide","pointer","show","Error","html","style","clientWidth","position_meta","HTMLElement","getBoundingClientRect","top","transform","opacity","VIEW_MODE","QUARTER_DAY","HALF_DAY","WEEK","VIEW_MODE_PADDING","Gantt","wrapper","tasks","setup_wrapper","setup_options","setup_tasks","change_view_mode","bind_events","svg_element","wrapper_element","$svg","$container","createElement","parentElement","popup_wrapper","default_options","view_modes","view_mode","date_format","custom_popup_html","assign","entries","view_mode_padding","console","log","start","undefined","end","tmpDuration","every","deps","trim","filter","random","toString","generate_id","setup_dependencies","dependency_map","t","refresh","mode","update_view_scale","setup_dates","render","setup_gantt_dates","setup_date_values","gantt_end","viewKey","padding_start","padding_end","dates","cur_date","bind_grid_click","bind_bar_events","clear","setup_layers","make_grid","make_dates","make_bars","make_arrows","map_arrows_on_bars","set_width","set_scroll_position","layers","layer","make_grid_background","make_grid_rows","make_grid_header","make_grid_ticks","make_grid_highlights","grid_width","grid_height","grid","rows_layer","lines_layer","row_width","row_height","row_y","x1","y1","x2","y2","tick_x","tick_y","tick_height","tick_class","computeGridHighlightDimensions","xDist","todayDate","startDate","endDate","setDate","setMonth","setFullYear","className","get_dates_to_draw","lower_x","lower_y","lower_text","upper_text","$upper_text","upper_x","upper_y","last_date","get_date_info","date_text","Hour_lower","Day_lower","Week_lower","Month_lower","Year_lower","Hour_upper","Day_upper","Week_upper","Month_upper","Year_upper","base_pos","x_pos","bars","task_id","dependency","get_task","Boolean","cur_width","actual_width","parent_element","scroll_pos","get_oldest_starting_date","scrollLeft","hide_popup","is_dragging","x_on_start","y_on_start","is_resizing_left","is_resizing_right","parent_bar_id","bar_wrapper","contains","offsetX","offsetY","ids","get_all_dependent_tasks","ox","oy","owidth","finaldx","bind_bar_progress","is_resizing","min_dx","max_dx","$handle","out","to_process","acc","querySelectorAll","el","modes","Array","isArray","some","find","popup","args","apply","prev_date"],"mappings":"kCAAA,MAAMA,EAAO,OACPC,EAAQ,QACRC,EAAM,MACNC,EAAO,OACPC,EAAS,SACTC,EAAS,SACTC,EAAc,cAEL,IAAAC,EAAA,CACbC,eAAeC,GACb,MACMC,EADQ,+BACQC,KAAKF,GAE3B,GAAgB,OAAZC,EAAkB,CACpB,GAAmB,MAAfA,EAAQ,GACV,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,QAC3C,GAAmB,MAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,SAC3C,GAAmB,MAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,OAC3C,GAAmB,MAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,QAC3C,GAAmB,QAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,UAC3C,GAAmB,MAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,UAC3C,GAAmB,OAAfH,EAAQ,GACjB,MAAO,CAAED,SAAUG,SAASF,EAAQ,IAAKG,MAAO,iBAItDC,MAAMC,EAAMC,EAAiB,IAAKC,EAAiB,QACjD,GAAIF,aAAgBG,KAClB,OAAOH,EAET,GAAoB,iBAATA,EAAmB,CAC5B,IAAII,EAAYC,EAChB,MAAMC,EAAQN,EAAKO,MAAM,KAEzBH,EAAaE,EAAM,GAChBC,MAAMN,GACNO,KAAKC,GAAQZ,SAASY,EAAK,MAC9BJ,EAAaC,EAAM,IAAMA,EAAM,GAAGC,MAAML,GAGxCE,EAAW,GAAKA,EAAW,GAAK,EAEhC,IAAIM,EAAON,EAUX,OARIC,GAAcA,EAAWM,SACF,GAArBN,EAAWM,SACbN,EAAW,GAAK,KAAOA,EAAW,GAClCA,EAAW,GAAiC,IAA5BO,WAAWP,EAAW,KAExCK,EAAOA,EAAKG,OAAOR,IAGd,IAAIF,QAAQO,KAIvBI,UAAUd,EAAMe,GAAY,GAC1B,KAAMf,aAAgBG,MACpB,MAAM,IAAIa,UAAU,yBAEtB,MAAMN,EAAOO,KAAKC,gBAAgBlB,GAAMQ,KAAI,CAACC,EAAKU,KACtC,IAANA,IAEFV,GAAY,GAILW,EAASX,EAAM,GADd,IAANU,EACwB,EAGF,EAHK,QAK3BE,EAAc,GAAGX,EAAK,MAAMA,EAAK,MAAMA,EAAK,KAC5CY,EAAc,GAAGZ,EAAK,MAAMA,EAAK,MAAMA,EAAK,MAAMA,EAAK,KAE7D,OAAOW,GAAeN,EAAY,IAAMO,EAAc,KAGxDC,OAAOvB,EAAMwB,EAAgB,0BAA2BC,EAAO,MAC7D,MAGMC,EAHiB,IAAIC,KAAKC,eAAeH,EAAM,CACnDI,MAAO,SAEyBN,OAAOvB,GACnC8B,EACJJ,EAAWK,OAAO,GAAGC,cAAgBN,EAAWO,MAAM,GAElDC,EAASjB,KAAKC,gBAAgBlB,GAAMQ,KAAK2B,GAAMf,EAASe,EAAG,EAAG,KAC9DC,EAAa,CACjBC,KAAMH,EAAO,GACbI,GAAIlB,GAAUc,EAAO,GAAK,EAAG,EAAG,GAChCK,GAAIL,EAAO,GACXM,GAAIN,EAAO,GACXO,GAAIP,EAAO,GACXQ,GAAIR,EAAO,GACXS,IAAKT,EAAO,GACZU,EAAGV,EAAO,GACVW,KAAMf,EACNgB,IAAKhB,GAGP,IAAIiB,EAAMvB,EACV,MAAMwB,EAAmB,GAezB,OAbAC,OAAOC,KAAKd,GACTe,MAAK,CAACC,EAAGC,IAAMA,EAAE1C,OAASyC,EAAEzC,SAC5B2C,SAASC,IACJR,EAAIS,SAASD,KACfR,EAAMA,EAAIU,QAAQF,EAAK,IAAIP,EAAiBrC,UAC5CqC,EAAiBU,KAAKtB,EAAWmB,QAIvCP,EAAiBM,SAAQ,CAACK,EAAOxC,KAC/B4B,EAAMA,EAAIU,QAAQ,IAAItC,IAAKwC,MAGtBZ,GAGTa,KAAKC,EAAQC,EAAQhE,EAAQX,GAC3B,IAAI4E,EAAcC,EAASC,EAAOC,EAASC,EAAMC,EAAQC,EAczD,OAZAN,EAAeF,EAASC,EACxBE,EAAUD,EAAe,IACzBG,EAAUF,EAAU,GACpBC,EAAQC,EAAU,GAClBC,EAAOF,EAAQ,GACfG,EAASD,EAAO,GAChBE,EAAQD,EAAS,GAEZtE,EAAMwE,SAAS,OAClBxE,GAAS,KAGJyE,KAAKC,MACV,CACET,aAAAA,EACAC,QAAAA,EACAE,QAAAA,EACAD,MAAAA,EACAE,KAAAA,EACAC,OAAAA,EACAC,MAAAA,GACAvE,KAIN2E,QACE,MAAM/D,EAAOO,KAAKC,gBAAgB,IAAIf,MAAQ8B,MAAM,EAAG,GACvD,OAAO,IAAI9B,QAAQO,IAGrBgE,IAAG,IACM,IAAIvE,KAGbwE,IAAI3E,EAAM4E,EAAK9E,GACb8E,EAAM/E,SAAS+E,EAAK,IACpB,MAAMlE,EAAO,CACXV,EAAK6E,eAAiB/E,IAAUb,EAAO2F,EAAM,GAC7C5E,EAAK8E,YAAchF,IAAUZ,EAAQ0F,EAAM,GAC3C5E,EAAK+E,WAAajF,IAAUX,EAAMyF,EAAM,GACxC5E,EAAKgF,YAAclF,IAAUV,EAAOwF,EAAM,GAC1C5E,EAAKiF,cAAgBnF,IAAUT,EAASuF,EAAM,GAC9C5E,EAAKkF,cAAgBpF,IAAUR,EAASsF,EAAM,GAC9C5E,EAAKmF,mBAAqBrF,IAAUP,EAAcqF,EAAM,IAE1D,OAAO,IAAIzE,QAAQO,IAGrB0E,SAASpF,EAAMF,GACb,MAAMuF,EAAS,CACbpG,CAACA,GAAO,EACRC,CAACA,GAAQ,EACTC,CAACA,GAAM,EACPC,CAACA,GAAO,EACRC,CAACA,GAAS,EACVC,CAACA,GAAS,EACVC,CAACA,GAAc,GAGjB,SAAS+F,EAAaC,GAEpB,OAAOF,EAAOE,IADIF,EAAOvF,GAI3B,MAAMY,EAAO,CACXV,EAAK6E,cACLS,EAAarG,GAAQ,EAAIe,EAAK8E,WAC9BQ,EAAapG,GAAS,EAAIc,EAAK+E,UAC/BO,EAAanG,GAAO,EAAIa,EAAKgF,WAC7BM,EAAalG,GAAQ,EAAIY,EAAKiF,aAC9BK,EAAajG,GAAU,EAAIW,EAAKkF,aAChCI,EAAahG,GAAU,EAAIU,EAAKmF,mBAGlC,OAAO,IAAIhF,QAAQO,IAGrB8E,MAAMxF,GACJ,OAAO,IAAIG,QAAQc,KAAKC,gBAAgBlB,KAG1CkB,gBAAgBlB,GACP,CACLA,EAAK6E,cACL7E,EAAK8E,WACL9E,EAAK+E,UACL/E,EAAKgF,WACLhF,EAAKiF,aACLjF,EAAKkF,aACLlF,EAAKmF,mBAITM,kBAAkBzF,GAChB,MAAM0F,EAAa,CAAC,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,IAE1D7D,EAAQ7B,EAAK8E,WAEnB,GAAc,IAAVjD,EACF,OAAO6D,EAAW7D,GAIpB,MAAM8D,EAAO3F,EAAK6E,cAClB,OAAKc,EAAO,GAAK,GAAKA,EAAO,KAAO,GAAMA,EAAO,KAAO,EAC/C,GAEF,KAKX,SAASvE,EAAS2B,EAAK6C,EAAcC,GAInC,OAHA9C,GAAY,GACZ6C,IAA+B,EAC/BC,EAAYC,YAA4B,IAAdD,EAA4BA,EAAY,KAC9D9C,EAAIpC,OAASiF,EACRE,OAAO/C,KAEd6C,GAA8B7C,EAAIpC,QACfkF,EAAUlF,SAC3BkF,GAAaA,EAAUE,OAAOH,EAAeC,EAAUlF,SAElDkF,EAAU5D,MAAM,EAAG2D,GAAgBE,OAAO/C,IC1P9C,SAASiD,EAAEC,EAAMC,GACtB,MAAuB,iBAATD,GACTC,GAAOC,UAAUC,cAAcH,GAChCA,GAAQ,KAGP,SAASI,EAAUC,EAAKC,GAC7B,MAAMC,EAAOL,SAASM,gBAAgB,6BAA8BH,GACpE,IAAK,IAAII,KAAQH,EACf,GAAa,cAATG,EAAsB,CACTH,EAAMI,UACdC,YAAYJ,OACD,cAATE,EACTF,EAAKK,UAAYN,EAAMM,UAEvBL,EAAKM,aAAaJ,EAAMH,EAAMG,IAGlC,OAAOF,EAGF,SAASO,EAAWC,EAAYN,EAAMO,EAAMC,GACjD,MAAMC,EAYR,SACEH,EACAN,EACAO,EACAC,EACAE,EAAM,OACNC,EAAQ,QAER,MAAMC,EAASN,EAAWZ,cAAc,WACxC,GAAIkB,EAQF,OAPAtB,EAAEU,KAAKY,EAAQ,CACbC,cAAeb,EACfO,KAAAA,EACAC,GAAAA,EACAE,IAAAA,EACAC,MAAO,WAAaA,IAEfL,EAGT,MAAMQ,EAAiBnB,EAAU,UAAW,CAC1CkB,cAAeb,EACfO,KAAAA,EACAC,GAAAA,EACAE,IAAAA,EACAC,MAAAA,EACAI,SAAU,SACVvF,OAAQ+E,EAAO,IAAMC,EACrBQ,SAAU,OACVC,WAAYC,EAAa,cAI3B,OAFAZ,EAAWJ,YAAYY,GAEhBR,EA7CoBa,CAAoBb,EAAYN,EAAMO,EAAMC,GAEvE,GAAIC,IAAuBH,EAAY,CAGrC,MAAMc,EAAQ3B,SAAS4B,YAAY,cACnCD,EAAME,UAAU,SAAS,GAAM,GAC/BF,EAAMG,UAAY,QAClBd,EAAmBe,cAAcJ,IAwCrC,SAASF,EAAaO,GACpB,MAAO,CACLC,KAAM,eACNC,OAAQ,UACR,UAAW,YACX,WAAY,YACZ,cAAe,eACfF,GAGJnC,EAAEsC,GAAK,CAACC,EAAST,EAAOU,EAAUC,KAC3BA,EAIHzC,EAAE0C,SAASH,EAAST,EAAOU,EAAUC,IAHrCA,EAAWD,EACXxC,EAAE2C,KAAKJ,EAAST,EAAOW,KAM3BzC,EAAE4C,IAAM,CAACL,EAAST,EAAOe,KACvBN,EAAQO,oBAAoBhB,EAAOe,IAGrC7C,EAAE2C,KAAO,CAACJ,EAAST,EAAOW,KACxBX,EAAMvH,MAAM,OAAO+C,SAAQ,SAAUwE,GACnCS,EAAQQ,iBAAiBjB,EAAOW,OAIpCzC,EAAE0C,SAAW,CAACH,EAAST,EAAOU,EAAUC,KACtCF,EAAQQ,iBAAiBjB,GAAO,SAAUkB,GACxC,MAAMC,EAAkBD,EAAEE,OAAOC,QAAQX,GACrCS,IACFD,EAAEC,gBAAkBA,EACpBR,EAASW,KAAKnI,KAAM+H,EAAGC,QAK7BjD,EAAEmD,QAAU,CAACX,EAAUD,IAChBA,EAEDA,EAAQ5I,QAAQ6I,GACXD,EAGFvC,EAAEmD,QAAQX,EAAUD,EAAQc,YANd,KASvBrD,EAAEU,KAAO,CAAC6B,EAAS7B,EAAM/C,KACvB,IAAKA,GAAyB,iBAAT+C,EACnB,OAAO6B,EAAQe,aAAa5C,GAG9B,GAAoB,iBAATA,EAOX6B,EAAQzB,aAAaJ,EAAM/C,QANzB,IAAK,IAAIJ,KAAOmD,EACdV,EAAEU,KAAK6B,EAAShF,EAAKmD,EAAKnD,KC3HjB,MAAMgG,EACnBC,YAAYC,EAAOC,GACjBzI,KAAK0I,aAAaF,EAAOC,GACzBzI,KAAK2I,UACL3I,KAAK4I,OACL5I,KAAK0H,OAGPgB,aAAaF,EAAOC,GAClBzI,KAAK6I,kBAAmB,EACxB7I,KAAKwI,MAAQA,EACbxI,KAAKyI,KAAOA,EAGdE,UACE3I,KAAK8I,iBACL9I,KAAK+I,kBAGPD,iBACE9I,KAAKgJ,QAAUhJ,KAAKyI,KAAKO,QACzBhJ,KAAKiJ,OAASjJ,KAAKwI,MAAMU,QAAQC,WACjCnJ,KAAKoJ,YACLpJ,KAAKqJ,YACLrJ,KAAKsJ,mBACLtJ,KAAKuJ,cAAgBvJ,KAAKwI,MAAMU,QAAQM,kBACxCxJ,KAAKyJ,MAAQzJ,KAAKwI,MAAMU,QAAQQ,aAAe1J,KAAKvB,SACpDuB,KAAK2J,eACH3J,KAAKwI,MAAMU,QAAQQ,aACnB1J,KAAKvB,UACJuB,KAAKyI,KAAKmB,SAAW,MAAQ,EAChC5J,KAAK6J,MAAQzE,EAAU,IAAK,CAC1B0E,MAAO,gBAAkB9J,KAAKyI,KAAKsB,cAAgB,IACnD,UAAW/J,KAAKyI,KAAKuB,KAEvBhK,KAAKiK,UAAY7E,EAAU,IAAK,CAC9B0E,MAAO,YACPpE,UAAW1F,KAAK6J,QAElB7J,KAAKkK,aAAe9E,EAAU,IAAK,CACjC0E,MAAO,eACPpE,UAAW1F,KAAK6J,QAIpBd,kBACEoB,WAAWC,UAAUC,KAAO,WAC1B,OAAQrK,KAAKqI,aAAa,MAE5B8B,WAAWC,UAAUE,KAAO,WAC1B,OAAQtK,KAAKqI,aAAa,MAE5B8B,WAAWC,UAAUG,SAAW,WAC9B,OAAQvK,KAAKqI,aAAa,UAE5B8B,WAAWC,UAAUI,UAAY,WAC/B,OAAQxK,KAAKqI,aAAa,WAE5B8B,WAAWC,UAAUK,QAAU,WAC7B,OAAOzK,KAAKqK,OAASrK,KAAKuK,YAI9BG,mCACE1K,KAAK2K,4BACL3K,KAAK4K,wBACH5K,KAAKwI,MAAMU,QAAQQ,aACnB1J,KAAKvB,UACJuB,KAAK6K,kBAAoB,MAAQ,EAGtCjC,OACE5I,KAAK8K,WACD9K,KAAKwI,MAAMU,QAAQ6B,yBACrB/K,KAAK0K,mCACL1K,KAAKgL,8BAEPhL,KAAKiL,oBACLjL,KAAKkL,aACLlL,KAAKmL,sBAGPL,WACE9K,KAAKoL,KAAOhG,EAAU,OAAQ,CAC5BiG,EAAGrL,KAAKqL,EACRC,EAAGtL,KAAKsL,EACR7B,MAAOzJ,KAAKyJ,MACZR,OAAQjJ,KAAKiJ,OACbsC,GAAIvL,KAAKuJ,cACTiC,GAAIxL,KAAKuJ,cACTO,MAAO,MACPpE,UAAW1F,KAAKiK,YAGlBnE,EAAW9F,KAAKoL,KAAM,QAAS,EAAGpL,KAAKyJ,OAEnCzJ,KAAKgJ,SACPhJ,KAAKoL,KAAKK,UAAU/H,IAAI,eAI5BsH,6BACMhL,KAAKgJ,UACThJ,KAAK0L,uBAAyBtG,EAAU,OAAQ,CAC9CiG,EAAGrL,KAAKqL,EACRC,EAAGtL,KAAKsL,EACR7B,MAAOzJ,KAAK4K,wBACZ3B,OAAQjJ,KAAKiJ,OACbsC,GAAIvL,KAAKuJ,cACTiC,GAAIxL,KAAKuJ,cACTO,MAAO,wBACPpE,UAAW1F,KAAKiK,YAGlBnE,EACE9F,KAAK0L,uBACL,QACA,EACA1L,KAAK4K,0BAITK,oBACMjL,KAAKgJ,UACThJ,KAAK2L,cAAgBvG,EAAU,OAAQ,CACrCiG,EAAGrL,KAAKqL,EACRC,EAAGtL,KAAKsL,EACR7B,MAAOzJ,KAAK2J,eACZV,OAAQjJ,KAAKiJ,OACbsC,GAAIvL,KAAKuJ,cACTiC,GAAIxL,KAAKuJ,cACTO,MAAO,eACPpE,UAAW1F,KAAKiK,YAGlBnE,EAAW9F,KAAK2L,cAAe,QAAS,EAAG3L,KAAK2J,iBAGlDuB,aACE9F,EAAU,OAAQ,CAChBiG,EAAGrL,KAAKqL,EAAIrL,KAAKyJ,MAAQ,EACzB6B,EAAGtL,KAAKsL,EAAItL,KAAKiJ,OAAS,EAC1BrD,UAAW5F,KAAKyI,KAAKvB,KACrB4C,MAAO,YACPpE,UAAW1F,KAAKiK,YAGlB2B,uBAAsB,IAAM5L,KAAK6L,0BAGnCV,sBACE,GAAInL,KAAKgJ,QAAS,OAElB,MAAM8C,EAAM9L,KAAKoL,KAGjBhG,EAAU,OAAQ,CAChBiG,EAAGS,EAAIzB,OAASyB,EAAIvB,WAAa,EACjCe,EAAGQ,EAAIxB,OAAS,EAChBb,MALmB,EAMnBR,OAAQjJ,KAAKiJ,OAAS,EACtBsC,GAAIvL,KAAKuJ,cACTiC,GAAIxL,KAAKuJ,cACTO,MAAO,eACPpE,UAAW1F,KAAKkK,eAGlB9E,EAAU,OAAQ,CAChBiG,EAAGS,EAAIzB,OAAS,EAChBiB,EAAGQ,EAAIxB,OAAS,EAChBb,MAhBmB,EAiBnBR,OAAQjJ,KAAKiJ,OAAS,EACtBsC,GAAIvL,KAAKuJ,cACTiC,GAAIxL,KAAKuJ,cACTO,MAAO,cACPpE,UAAW1F,KAAKkK,eAGlBlK,KAAK+L,iBAAmB3G,EAAU,UAAW,CAC3C4G,OAAQhM,KAAKiM,8BAA8BC,KAAK,KAChDpC,MAAO,kBACPpE,UAAW1F,KAAKkK,eAIpB+B,8BACE,MAAME,EAAenM,KAAK2L,cAC1B,MAAO,CACLQ,EAAa1B,UAAY,EACzB0B,EAAa7B,OAAS6B,EAAa3B,YACnC2B,EAAa1B,UAAY,EACzB0B,EAAa7B,OAAS6B,EAAa3B,YACnC2B,EAAa1B,UACb0B,EAAa7B,OAAS6B,EAAa3B,YAAc,MAIrD9C,OACM1H,KAAKgJ,SACThJ,KAAKoM,oBAGPA,oBACErH,EAAEsC,GAAGrH,KAAK6J,MAAO,SAAW7J,KAAKwI,MAAMU,QAAQmD,eAAgBtE,IACzD/H,KAAK6I,mBAKT7I,KAAKsM,aACLtM,KAAKwI,MAAM+D,eACXvM,KAAK6J,MAAM4B,UAAU/H,IAAI,cAG3BqB,EAAEsC,GAAGrH,KAAK6J,MAAO,YAAa9B,IACxB/H,KAAK6I,kBAKT7I,KAAKwI,MAAMgE,cAAc,QAAS,CAACxM,KAAKyI,UAI5C6D,aACE,GAAItM,KAAKwI,MAAMiE,kBAAmB,OAElC,MAUMC,EAVanO,EAAW+B,OAC5BN,KAAKyI,KAAKkE,OACV,QACA3M,KAAKwI,MAAMU,QAAQ0D,UAOS,MALbrO,EAAW+B,OAC1B/B,EAAWmF,IAAI1D,KAAKyI,KAAKoE,MAAO,EAAG,UACnC,QACA7M,KAAKwI,MAAMU,QAAQ0D,UAIrB5M,KAAKwI,MAAM8D,WAAW,CACpBQ,eAAgB9M,KAAKoL,KACrB2B,MAAO/M,KAAKyI,KAAKvB,KACjBwF,SAAUA,EACVjE,KAAMzI,KAAKyI,OAIfuE,qBAAoB3B,EAAEA,EAAI,KAAI5B,MAAEA,EAAQ,OACtC,MAAMqC,EAAM9L,KAAKoL,KACjB,GAAIC,EAAG,CASL,IAPWrL,KAAKyI,KAAKwE,aAAa1N,KAAK2N,GAC9BlN,KAAKwI,MAAM2E,QAAQD,GAAK9B,KAAKf,SAGnB+C,QAAO,CAACC,EAAMC,IACxBjC,GAAKiC,GACXjC,GAGD,YADA5B,EAAQ,MAGVzJ,KAAKuN,YAAYzB,EAAK,IAAKT,GAEzB5B,GACFzJ,KAAKuN,YAAYzB,EAAK,QAASrC,GAEjCzJ,KAAK6L,wBACL7L,KAAKwN,yBACDxN,KAAKwI,MAAMU,QAAQ6B,yBACrB/K,KAAKyN,eACLzN,KAAKsJ,mBACLtJ,KAAK0N,wCAEP1N,KAAK2N,8BACL3N,KAAK4N,wBAGPH,eACE,IAAII,GAAU,EACd,MAAMC,eAAEA,EAAcC,aAAEA,GAAiB/N,KAAKgO,yBAE1CC,OAAOjO,KAAKyI,KAAKkE,UAAYsB,OAAOH,KACtCD,GAAU,EACV7N,KAAKyI,KAAKkE,OAASmB,GAGjBG,OAAOjO,KAAKyI,KAAKoE,QAAUoB,OAAOF,KACpCF,GAAU,EACV7N,KAAKyI,KAAKoE,KAAOkB,GAGdF,GAEL7N,KAAKwI,MAAMgE,cAAc,cAAe,CACtCxM,KAAKyI,KACLqF,EACAvP,EAAWmF,IAAIqK,GAAe,EAAG,YAIrCG,mBACE,MAAMC,EAAenO,KAAKoO,mBAC1BpO,KAAKyI,KAAKmB,SAAWuE,EACrBnO,KAAKwI,MAAMgE,cAAc,kBAAmB,CAACxM,KAAKyI,KAAM0F,IAG1DE,uBACErO,KAAK6I,kBAAmB,EACxByF,YAAW,IAAOtO,KAAK6I,kBAAmB,GAAQ,KAGpDmF,yBACE,MAAMlC,EAAM9L,KAAKoL,KACXmD,EAAazC,EAAIzB,OAASrK,KAAKwI,MAAMU,QAAQQ,aAC7CoE,EAAiBvP,EAAWmF,IAChC1D,KAAKwI,MAAMgG,YACXD,EAAavO,KAAKwI,MAAMU,QAAQuF,KAChC,QAEIC,EAAiB5C,EAAIvB,WAAavK,KAAKwI,MAAMU,QAAQQ,aAO3D,MAAO,CAAEoE,eAAAA,EAAgBC,aANJxP,EAAWmF,IAC9BoK,EACAY,EAAiB1O,KAAKwI,MAAMU,QAAQuF,KACpC,SAMJL,mBACE,MAAMxE,EACH5J,KAAK2L,cAAcpB,WAAavK,KAAKoL,KAAKb,WAAc,IAC3D,OAAO3L,SAASgL,EAAU,IAG5Be,4BACE3K,KAAK6K,kBACHtM,EAAWoE,KAAKpE,EAAWiF,QAASxD,KAAKyI,KAAKkE,OAAQ,QACtD3M,KAAKwI,MAAMU,QAAQuF,KACrBzO,KAAK6K,kBAID,KAHA7K,KAAK6K,kBAAoB7K,KAAKvB,SAC5BuB,KAAK6K,kBACL7K,KAAKvB,UAETuB,KAAKvB,SAGT2K,YACE,MAAMqF,KAAEA,EAAI/E,aAAEA,GAAiB1J,KAAKwI,MAAMU,QACpCyF,EAAa3O,KAAKyI,KAAKkE,OACvB6B,EAAcxO,KAAKwI,MAAMgG,YAG/B,IAAInD,EADS9M,EAAWoE,KAAKgM,EAAYH,EAAa,QACtCC,EAAQ/E,EAExB,GAAI1J,KAAKwI,MAAMoG,QAAQ,SAAU,CAE/BvD,EADa9M,EAAWoE,KAAKgM,EAAYH,EAAa,OAC1C9E,EAAgB,GAE9B1J,KAAKqL,EAAIA,EAGXhC,YACErJ,KAAKsL,EACHtL,KAAKwI,MAAMU,QAAQ2F,cACnB7O,KAAKwI,MAAMU,QAAQ4F,QACnB9O,KAAKyI,KAAKsG,QAAU/O,KAAKiJ,OAASjJ,KAAKwI,MAAMU,QAAQ4F,SAGzDxF,mBACEtJ,KAAKvB,SACHF,EAAWoE,KAAK3C,KAAKyI,KAAKoE,KAAM7M,KAAKyI,KAAKkE,OAAQ,QAClD3M,KAAKwI,MAAMU,QAAQuF,KAGvBO,kBAAkBC,GAChB,IACEC,EACAC,EAFEC,EAAMH,EA6BV,OAzBIjP,KAAKwI,MAAMoG,QAAQ,SACrBM,EAAMD,GAAMjP,KAAKwI,MAAMU,QAAQQ,aAAe,GAC9CyF,EACEC,EACAF,GACCA,EAAMlP,KAAKwI,MAAMU,QAAQQ,aAAe,GACrC,EACA1J,KAAKwI,MAAMU,QAAQQ,aAAe,IAC/B1J,KAAKwI,MAAMoG,QAAQ,UAC5BM,EAAMD,GAAMjP,KAAKwI,MAAMU,QAAQQ,aAAe,IAC9CyF,EACEC,EACAF,GACCA,EAAMlP,KAAKwI,MAAMU,QAAQQ,aAAe,GACrC,EACA1J,KAAKwI,MAAMU,QAAQQ,aAAe,MAExCwF,EAAMD,EAAKjP,KAAKwI,MAAMU,QAAQQ,aAC9ByF,EACEC,EACAF,GACCA,EAAMlP,KAAKwI,MAAMU,QAAQQ,aAAe,EACrC,EACA1J,KAAKwI,MAAMU,QAAQQ,eAEpByF,EAGT5B,YAAYjG,EAAS7B,EAAM/C,GAKzB,OAJAA,GAASA,EACJ2M,MAAM3M,IACT4E,EAAQzB,aAAaJ,EAAM/C,GAEtB4E,EAGToG,uCACM1N,KAAKgJ,UACThJ,KAAK0L,uBAAuB7F,aAAa,IAAK7F,KAAKoL,KAAKf,QACxDrK,KAAK2K,4BACL3K,KAAK0L,uBAAuB7F,aAC1B,QACA7F,KAAKwI,MAAMU,QAAQQ,aACnB1J,KAAKvB,UACJuB,KAAK6K,kBAAoB,MAAQ,IAItC8C,8BACM3N,KAAKgJ,UACThJ,KAAK2L,cAAc9F,aAAa,IAAK7F,KAAKoL,KAAKf,QAC/CrK,KAAK2L,cAAc9F,aACjB,QACA7F,KAAKoL,KAAKb,YAAcvK,KAAKyI,KAAKmB,SAAW,OAIjDiC,wBACE,MAAMC,EAAM9L,KAAKoL,KACfkE,EAAQtP,KAAK6J,MAAM1E,cAAc,cAE/BmK,EAAMC,UAAU9F,MAAQqC,EAAIvB,YAC9B+E,EAAM7D,UAAU/H,IAAI,OACpB4L,EAAMzJ,aAAa,IAAKiG,EAAIzB,OAASyB,EAAIvB,WAAa,KAEtD+E,EAAM7D,UAAU+D,OAAO,OACvBF,EAAMzJ,aAAa,IAAKiG,EAAIzB,OAASyB,EAAIvB,WAAa,IAI1DiD,yBACE,GAAIxN,KAAKgJ,QAAS,OAClB,MAAM8C,EAAM9L,KAAKoL,KACjBpL,KAAKkK,aACF/E,cAAc,gBACdU,aAAa,IAAKiG,EAAIzB,OAAS,GAClCrK,KAAKkK,aACF/E,cAAc,iBACdU,aAAa,IAAKiG,EAAIrB,UAAY,GACrC,MAAMgF,EAASzP,KAAK6J,MAAM1E,cAAc,oBACxCsK,GAAUA,EAAO5J,aAAa,SAAU7F,KAAKiM,+BAG/C2B,wBACE5N,KAAK0P,OAAS1P,KAAK0P,QAAU,GAC7B,IAAK,IAAIC,KAAS3P,KAAK0P,OACrBC,EAAMC,UCpdG,MAAMC,EACnBtH,YAAYC,EAAOsH,EAAWC,GAC5B/P,KAAKwI,MAAQA,EACbxI,KAAK8P,UAAYA,EACjB9P,KAAK+P,QAAUA,EAEf/P,KAAKgQ,iBACLhQ,KAAK4I,OAGPoH,iBACE,IAAIC,EACFjQ,KAAK8P,UAAU1E,KAAKf,OAASrK,KAAK8P,UAAU1E,KAAKb,WAAa,EAEhE,MAAM2F,EAAY,IAChBlQ,KAAK+P,QAAQ3E,KAAKf,OAAS4F,EAAUjQ,KAAKwI,MAAMU,QAAQ4F,SACxDmB,EAAUjQ,KAAK8P,UAAU1E,KAAKf,OAASrK,KAAKwI,MAAMU,QAAQ4F,QAE5D,KAAOoB,KACLD,GAAW,GAGb,MAAME,EACJnQ,KAAKwI,MAAMU,QAAQ2F,cACnB7O,KAAKwI,MAAMU,QAAQC,YAClBnJ,KAAKwI,MAAMU,QAAQ4F,QAAU9O,KAAKwI,MAAMU,QAAQC,YAC/CnJ,KAAK8P,UAAUrH,KAAKsG,OACtB/O,KAAKwI,MAAMU,QAAQ4F,QAEfsB,EAAQpQ,KAAK+P,QAAQ3E,KAAKf,OAASrK,KAAKwI,MAAMU,QAAQ4F,QAAU,EAChEuB,EACJrQ,KAAKwI,MAAMU,QAAQ2F,cACnB7O,KAAKwI,MAAMU,QAAQC,WAAa,GAC/BnJ,KAAKwI,MAAMU,QAAQ4F,QAAU9O,KAAKwI,MAAMU,QAAQC,YAC/CnJ,KAAK+P,QAAQtH,KAAKsG,OACpB/O,KAAKwI,MAAMU,QAAQ4F,QAEfwB,EACJtQ,KAAK8P,UAAUrH,KAAKsG,OAAS/O,KAAK+P,QAAQtH,KAAKsG,OAC3CwB,EAAQvQ,KAAKwI,MAAMU,QAAQsH,YAC3BC,EAAYH,EAAmB,EAAI,EACnCI,EAAUJ,GAAoBC,EAAQA,EACtCI,EAASL,EACXD,EAAQrQ,KAAKwI,MAAMU,QAAQsH,YAC3BH,EAAQrQ,KAAKwI,MAAMU,QAAQsH,YAW/B,GATAxQ,KAAK4Q,KAAO,mBACAX,KAAWE,oBACXQ,oBACAJ,KAASA,SAAaE,KAAaF,KAASG,oBAC5CN,KAASC,gEAMnBrQ,KAAK+P,QAAQ3E,KAAKf,OAClBrK,KAAK8P,UAAU1E,KAAKf,OAASrK,KAAKwI,MAAMU,QAAQ4F,QAChD,CACA,MAAM+B,EAAS7Q,KAAKwI,MAAMU,QAAQ4F,QAAU,EAAIyB,EAC1CO,EACJ9Q,KAAK+P,QAAQ3E,KAAKd,OAAStK,KAAK+P,QAAQ3E,KAAKZ,YAAc,EAAIkG,EAC3DK,EAAO/Q,KAAK+P,QAAQ3E,KAAKf,OAASrK,KAAKwI,MAAMU,QAAQ4F,QAE3D9O,KAAK4Q,KAAO,uBACEX,KAAWE,wBACXU,wBACAN,KAASA,YAAgBA,KAASA,wBAClCQ,wBACAR,KAASA,SAAaE,MAAcF,KAASG,wBAC7CI,wBACAP,KAASA,SAAaE,KAAaF,KAASG,wBAC5CN,KAASC,6EAO3BzH,OACE5I,KAAKsH,QAAUlC,EAAU,OAAQ,CAC/BlE,EAAGlB,KAAK4Q,KACR,YAAa5Q,KAAK8P,UAAUrH,KAAKuB,GACjC,UAAWhK,KAAK+P,QAAQtH,KAAKuB,KAIjC4F,SACE5P,KAAKgQ,iBACLhQ,KAAKsH,QAAQzB,aAAa,IAAK7F,KAAK4Q,OC3FzB,MAAMI,EACnBzI,YAAY0I,EAAQC,GAClBlR,KAAKiR,OAASA,EACdjR,KAAKkR,YAAcA,EACnBlR,KAAKmR,OAGPA,OACEnR,KAAKiR,OAAOrL,UAAY,uIAMxB5F,KAAKoR,OAELpR,KAAK+M,MAAQ/M,KAAKiR,OAAO9L,cAAc,UACvCnF,KAAK0M,SAAW1M,KAAKiR,OAAO9L,cAAc,aAC1CnF,KAAKqR,QAAUrR,KAAKiR,OAAO9L,cAAc,YAG3CmM,KAAKpI,GACH,IAAKA,EAAQ4D,eACX,MAAM,IAAIyE,MAAM,4CAEbrI,EAAQiG,WACXjG,EAAQiG,SAAW,QAErB,MAAMrC,EAAiB5D,EAAQ4D,eAE/B,GAAI9M,KAAKkR,YAAa,CACpB,IAAIM,EAAOxR,KAAKkR,YAAYhI,EAAQT,MACpC+I,GAAQ,8BACRxR,KAAKiR,OAAOrL,UAAY4L,EACxBxR,KAAKqR,QAAUrR,KAAKiR,OAAO9L,cAAc,iBAGzCnF,KAAK+M,MAAMnH,UAAYsD,EAAQ6D,MAC/B/M,KAAK0M,SAAS9G,UAAYsD,EAAQwD,SAClC1M,KAAKiR,OAAOQ,MAAMhI,MAAQzJ,KAAKiR,OAAOS,YAAc,KAItD,IAAIC,EACA7E,aAA0B8E,YAC5BD,EAAgB7E,EAAe+E,wBACtB/E,aAA0B3C,aACnCwH,EAAgBzI,EAAQ4D,eAAeyC,WAGhB,SAArBrG,EAAQiG,WACVnP,KAAKiR,OAAOQ,MAAMV,KAChBY,EAActG,GAAKsG,EAAclI,MAAQ,IAAM,KACjDzJ,KAAKiR,OAAOQ,MAAMK,IAAMH,EAAcrG,EAAI,KAE1CtL,KAAKqR,QAAQI,MAAMM,UAAY,iBAC/B/R,KAAKqR,QAAQI,MAAMV,KAAO,OAC1B/Q,KAAKqR,QAAQI,MAAMK,IAAM,OAI3B9R,KAAKiR,OAAOQ,MAAMO,QAAU,EAG9BZ,OACEpR,KAAKiR,OAAOQ,MAAMO,QAAU,EAC5BhS,KAAKiR,OAAOQ,MAAMV,KAAO,GC1D7B,MAAMkB,EAAY,CAChB9T,KAAM,OACN+T,YAAa,cACbC,SAAU,WACVjU,IAAK,MACLkU,KAAM,OACNnU,MAAO,QACPD,KAAM,QAGFqU,EAAoB,CACxBlU,KAAM,CAAC,KAAM,MACb+T,YAAa,CAAC,KAAM,MACpBC,SAAU,CAAC,KAAM,MACjBjU,IAAK,CAAC,KAAM,MACZkU,KAAM,CAAC,KAAM,MACbnU,MAAO,CAAC,KAAM,MACdD,KAAM,CAAC,KAAM,OAGA,MAAMsU,EACnB/J,YAAYgK,EAASC,EAAOtJ,GAC1BlJ,KAAKyS,cAAcF,GACnBvS,KAAK0S,cAAcxJ,GACnBlJ,KAAK2S,YAAYH,GAEjBxS,KAAK4S,mBACL5S,KAAK6S,cAGPJ,cAAcnL,GACZ,IAAIwL,EAAaC,EAQjB,GALuB,iBAAZzL,IACTA,EAAUpC,SAASC,cAAcmC,IAI/BA,aAAmBsK,YACrBmB,EAAkBzL,EAClBwL,EAAcxL,EAAQnC,cAAc,WAC/B,CAAA,KAAImC,aAAmB6C,YAG5B,MAAM,IAAIpK,UACR,8HAHF+S,EAAcxL,EASXwL,GAOH9S,KAAKgT,KAAOF,EACZ9S,KAAKgT,KAAKvH,UAAU/H,IAAI,UANxB1D,KAAKgT,KAAO5N,EAAU,MAAO,CAC3BM,UAAWqN,EACXjJ,MAAO,UAQX9J,KAAKiT,WAAa/N,SAASgO,cAAc,OACzClT,KAAKiT,WAAWxH,UAAU/H,IAAI,mBAEP1D,KAAKgT,KAAKG,cAClBxN,YAAY3F,KAAKiT,YAChCjT,KAAKiT,WAAWtN,YAAY3F,KAAKgT,MAGjChT,KAAKoT,cAAgBlO,SAASgO,cAAc,OAC5ClT,KAAKoT,cAAc3H,UAAU/H,IAAI,iBACjC1D,KAAKiT,WAAWtN,YAAY3F,KAAKoT,eAGnCV,cAAcxJ,GACZ,MAAMmK,EAAkB,CACtBxE,cAAe,GACfnF,aAAc,GACd+E,KAAM,GACN6E,WAAY,IAAItR,OAAOf,OAAOgR,IAC9B9I,WAAY,GACZK,kBAAmB,EACnBgH,YAAa,EACb1B,QAAS,GACTyE,UAAW,MACXC,YAAa,aACbnH,cAAe,QACfoH,kBAAmB,KACnB7G,SAAU,MAEZ5M,KAAKkJ,QAAUlH,OAAO0R,OAAO,GAAIL,EAAiBnK,GAClD,IAAK,IAAK5G,EAAKI,KAAUV,OAAO2R,QAAQzK,EAAQ0K,mBACzB,iBAAVlR,IAETwG,EAAQ0K,kBAAkBtR,GAAO,CAACI,EAAOA,IAI7CmR,QAAQC,IAAI5K,EAAQ0K,mBACpB5T,KAAKkJ,QAAQ0K,kBAAoB,IAC5BvB,KACAnJ,EAAQ0K,mBAIfjB,YAAYH,GAEVxS,KAAKwS,MAAQA,EAAMjT,KAAI,CAACkJ,EAAMvI,KAG5B,GADAuI,EAAKkE,OAASpO,EAAWO,MAAM2J,EAAKsL,YACnBC,IAAbvL,EAAKwL,UAAuCD,IAAlBvL,EAAKhK,SAAwB,CACzDgK,EAAKwL,IAAMxL,EAAKkE,OACAlE,EAAKhK,SAASa,MAAM,KAE1B+C,SAAS6R,IACjB,IAAIzV,SAAEA,EAAQI,MAAEA,GAAUN,EAAWC,eAAe0V,GACpDzL,EAAKwL,IAAM1V,EAAWmF,IAAI+E,EAAKwL,IAAKxV,EAAUI,MAclD,GAXA4J,EAAKoE,KAAOtO,EAAWO,MAAM2J,EAAKwL,KAG9B1V,EAAWoE,KAAK8F,EAAKoE,KAAMpE,EAAKkE,OAAQ,QAAU,KACpDlE,EAAKwL,IAAM,MAIbxL,EAAKsG,OAAS7O,GAGTuI,EAAKsL,QAAUtL,EAAKwL,IAAK,CAC5B,MAAMzQ,EAAQjF,EAAWiF,QACzBiF,EAAKkE,OAASnJ,EACdiF,EAAKoE,KAAOtO,EAAWmF,IAAIF,EAAO,EAAG,QAGlCiF,EAAKsL,OAAStL,EAAKwL,MACtBxL,EAAKkE,OAASpO,EAAWmF,IAAI+E,EAAKoE,MAAO,EAAG,QAG1CpE,EAAKsL,QAAUtL,EAAKwL,MACtBxL,EAAKoE,KAAOtO,EAAWmF,IAAI+E,EAAKkE,OAAQ,EAAG,QAgB7C,GAXwBpO,EAAW0B,gBAAgBwI,EAAKoE,MACpC7L,MAAM,GAAGmT,OAAOjT,GAAY,IAANA,MACxCuH,EAAKoE,KAAOtO,EAAWmF,IAAI+E,EAAKoE,KAAM,GAAI,SAIvCpE,EAAKsL,OAAUtL,EAAKwL,MACvBxL,EAAKO,SAAU,GAIgB,iBAAtBP,EAAKwE,eAA8BxE,EAAKwE,aAAc,CAC/D,IAAImH,EAAO,GACP3L,EAAKwE,eACPmH,EAAO3L,EAAKwE,aACT3N,MAAM,KACNC,KAAK2B,GAAMA,EAAEmT,SACbC,QAAQpT,GAAMA,KAEnBuH,EAAKwE,aAAemH,EAQtB,OAJK3L,EAAKuB,KACRvB,EAAKuB,GAozBb,SAAqBvB,GACnB,OAAOA,EAAKvB,KAAO,IAAM5D,KAAKiR,SAASC,SAAS,IAAIxT,MAAM,EAAG,IArzB7CyT,CAAYhM,IAGjBA,KAGTzI,KAAK0U,qBAGPA,qBACE1U,KAAK2U,eAAiB,GACtB,IAAK,IAAIC,KAAK5U,KAAKwS,MACjB,IAAK,IAAItR,KAAK0T,EAAE3H,aACdjN,KAAK2U,eAAezT,GAAKlB,KAAK2U,eAAezT,IAAM,GACnDlB,KAAK2U,eAAezT,GAAGuB,KAAKmS,EAAE5K,IAKpC6K,QAAQrC,GACNxS,KAAK2S,YAAYH,GACjBxS,KAAK4S,mBAGPA,iBAAiBkC,EAAO9U,KAAKkJ,QAAQqK,WACnCvT,KAAK+U,kBAAkBD,GACvB9U,KAAKgV,cACLhV,KAAKiV,SAELjV,KAAKwM,cAAc,cAAe,CAACsI,IAGrCC,kBAAkBxB,GAChBvT,KAAKkJ,QAAQqK,UAAYA,EACrBA,IAActB,EAAU9T,MAC1B6B,KAAKkJ,QAAQuF,KAAO,EACpBzO,KAAKkJ,QAAQQ,aAAe,IACnB6J,IAActB,EAAU/T,KACjC8B,KAAKkJ,QAAQuF,KAAO,GACpBzO,KAAKkJ,QAAQQ,aAAe,IACnB6J,IAActB,EAAUE,UACjCnS,KAAKkJ,QAAQuF,KAAO,GACpBzO,KAAKkJ,QAAQQ,aAAe,IACnB6J,IAActB,EAAUC,aACjClS,KAAKkJ,QAAQuF,KAAO,EACpBzO,KAAKkJ,QAAQQ,aAAe,IACnB6J,IAActB,EAAUG,MACjCpS,KAAKkJ,QAAQuF,KAAO,IACpBzO,KAAKkJ,QAAQQ,aAAe,KACnB6J,IAActB,EAAUhU,OACjC+B,KAAKkJ,QAAQuF,KAAO,IACpBzO,KAAKkJ,QAAQQ,aAAe,KACnB6J,IAActB,EAAUjU,OACjCgC,KAAKkJ,QAAQuF,KAAO,KACpBzO,KAAKkJ,QAAQQ,aAAe,KAIhCsL,cACEhV,KAAKkV,oBACLlV,KAAKmV,oBAGPD,oBACElV,KAAKwO,YAAcxO,KAAKoV,UAAY,KAEpC,IAAK,IAAI3M,KAAQzI,KAAKwS,QAEfxS,KAAKwO,aAAe/F,EAAKkE,OAAS3M,KAAKwO,eAC1CxO,KAAKwO,YAAc/F,EAAKkE,UAErB3M,KAAKoV,WAAa3M,EAAKoE,KAAO7M,KAAKoV,aACtCpV,KAAKoV,UAAY3M,EAAKoE,MAI1B,IAGIwI,EAHA7G,EAAcjQ,EAAW4F,SAASnE,KAAKwO,YAAa,OACpD4G,EAAY7W,EAAW4F,SAASnE,KAAKoV,UAAW,OAGpD,IAAK,IAAK9S,EAAKI,KAAUV,OAAO2R,QAAQ1B,GAClCvP,IAAU1C,KAAKkJ,QAAQqK,YACzB8B,EAAU/S,GAGd,MAAOgT,EAAeC,GAAevV,KAAKkJ,QAAQ0K,kBAChDyB,GACA9V,IAAIhB,EAAWC,gBACjBwB,KAAKwO,YAAcjQ,EAAWmF,IAC5B8K,GACC8G,EAAc7W,SACf6W,EAAczW,OAEhBmB,KAAKoV,UAAY7W,EAAWmF,IAC1B0R,EACAG,EAAY9W,SACZ8W,EAAY1W,OAIhBsW,oBACEnV,KAAKwV,MAAQ,GACb,IAAIC,EAAW,KAEf,KAAoB,OAAbA,GAAqBA,EAAWzV,KAAKoV,WAKtCK,EAJCA,EAGCzV,KAAK4O,QAAQqD,EAAUjU,MACdO,EAAWmF,IAAI+R,EAAU,EAAG,QAC9BzV,KAAK4O,QAAQqD,EAAUhU,OACrBM,EAAWmF,IAAI+R,EAAU,EAAG,SAE5BlX,EAAWmF,IAAI+R,EAAUzV,KAAKkJ,QAAQuF,KAAM,QAP9ClQ,EAAWgG,MAAMvE,KAAKwO,aAUnCxO,KAAKwV,MAAM/S,KAAKgT,GAIpB5C,cACE7S,KAAK0V,kBACL1V,KAAK2V,kBAGPV,SACEjV,KAAK4V,QACL5V,KAAK6V,eACL7V,KAAK8V,YACL9V,KAAK+V,aACL/V,KAAKgW,YACLhW,KAAKiW,cACLjW,KAAKkW,qBACLlW,KAAKmW,YACLnW,KAAKoW,sBAGPP,eACE7V,KAAKqW,OAAS,GACd,MAAMA,EAAS,CAAC,OAAQ,OAAQ,QAAS,WAAY,MAAO,WAE5D,IAAK,IAAIC,KAASD,EAChBrW,KAAKqW,OAAOC,GAASlR,EAAU,IAAK,CAClC0E,MAAOwM,EACP5Q,UAAW1F,KAAKgT,OAKtB8C,YACE9V,KAAKuW,uBACLvW,KAAKwW,iBACLxW,KAAKyW,mBACLzW,KAAK0W,kBACL1W,KAAK2W,uBAGPJ,uBACE,MAAMK,EAAa5W,KAAKwV,MAAM9V,OAASM,KAAKkJ,QAAQQ,aAC9CmN,EACJ7W,KAAKkJ,QAAQ2F,cACb7O,KAAKkJ,QAAQ4F,SACZ9O,KAAKkJ,QAAQC,WAAanJ,KAAKkJ,QAAQ4F,SAAW9O,KAAKwS,MAAM9S,OAEhE0F,EAAU,OAAQ,CAChBiG,EAAG,EACHC,EAAG,EACH7B,MAAOmN,EACP3N,OAAQ4N,EACR/M,MAAO,kBACPpE,UAAW1F,KAAKqW,OAAOS,OAGzB/R,EAAEU,KAAKzF,KAAKgT,KAAM,CAChB/J,OAAQ4N,EAAc7W,KAAKkJ,QAAQ4F,QAAU,IAC7CrF,MAAO,SAIX+M,iBACE,MAAMO,EAAa3R,EAAU,IAAK,CAAEM,UAAW1F,KAAKqW,OAAOS,OACrDE,EAAc5R,EAAU,IAAK,CAAEM,UAAW1F,KAAKqW,OAAOS,OAEtDG,EAAYjX,KAAKwV,MAAM9V,OAASM,KAAKkJ,QAAQQ,aAC7CwN,EAAalX,KAAKkJ,QAAQC,WAAanJ,KAAKkJ,QAAQ4F,QAE1D,IAAIqI,EAAQnX,KAAKkJ,QAAQ2F,cAAgB7O,KAAKkJ,QAAQ4F,QAAU,EAEhE,IAAK,IAAIrG,KAAQzI,KAAKwS,MACpBpN,EAAU,OAAQ,CAChBiG,EAAG,EACHC,EAAG6L,EACH1N,MAAOwN,EACPhO,OAAQiO,EACRpN,MAAO,WACPpE,UAAWqR,IAGb3R,EAAU,OAAQ,CAChBgS,GAAI,EACJC,GAAIF,EAAQD,EACZI,GAAIL,EACJM,GAAIJ,EAAQD,EACZpN,MAAO,WACPpE,UAAWsR,IAGbG,GAASnX,KAAKkJ,QAAQC,WAAanJ,KAAKkJ,QAAQ4F,QAIpD2H,mBAGErR,EAAU,OAAQ,CAChBiG,EAAG,EACHC,EAAG,EACH7B,MALmBzJ,KAAKwV,MAAM9V,OAASM,KAAKkJ,QAAQQ,aAMpDT,OALoBjJ,KAAKkJ,QAAQ2F,cAAgB,GAMjD/E,MAAO,cACPpE,UAAW1F,KAAKqW,OAAOS,OAI3BJ,kBACE,IAAIc,EAAS,EACTC,EAASzX,KAAKkJ,QAAQ2F,cAAgB7O,KAAKkJ,QAAQ4F,QAAU,EAC7D4I,GACD1X,KAAKkJ,QAAQC,WAAanJ,KAAKkJ,QAAQ4F,SAAW9O,KAAKwS,MAAM9S,OAEhE,IAAK,IAAIX,KAAQiB,KAAKwV,MAAO,CAC3B,IAAImC,EAAa,OAEb3X,KAAK4O,QAAQqD,EAAU/T,MAA2B,IAAnBa,EAAK+E,YACtC6T,GAAc,UAId3X,KAAK4O,QAAQqD,EAAUG,OACvBrT,EAAK+E,WAAa,GAClB/E,EAAK+E,UAAY,IAEjB6T,GAAc,UAGZ3X,KAAK4O,QAAQqD,EAAUhU,QAAUc,EAAK8E,WAAa,GAAM,IAC3D8T,GAAc,UAGhBvS,EAAU,OAAQ,CAChBlE,EAAG,KAAKsW,KAAUC,OAAYC,IAC9B5N,MAAO6N,EACPjS,UAAW1F,KAAKqW,OAAOS,OAGrB9W,KAAK4O,QAAQqD,EAAUhU,OACzBuZ,GACGjZ,EAAWiG,kBAAkBzF,GAAQiB,KAAKkJ,QAAQQ,aAAgB,GAErE8N,GAAUxX,KAAKkJ,QAAQQ,cAM7BkO,+BAA+BrE,GAC7B,IAAIsE,EAAQ,EAEZ,GAAI7X,KAAK4O,QAAQqD,EAAU/T,KACzB,OACGK,EAAWoE,KAAKpE,EAAWiF,QAASxD,KAAKwO,YAAa,QACrDxO,KAAKkJ,QAAQuF,KACfzO,KAAKkJ,QAAQQ,aAIjB,IAAK,IAAI3K,KAAQiB,KAAKwV,MAAO,CAC3B,MAAMsC,EAAY,IAAI5Y,KAChB6Y,EAAY,IAAI7Y,KAAKH,GACrBiZ,EAAU,IAAI9Y,KAAKH,GACzB,OAAQwU,GACN,KAAKtB,EAAUG,KACb4F,EAAQC,QAAQlZ,EAAK+E,UAAY,GACjC,MACF,KAAKmO,EAAUhU,MACb+Z,EAAQE,SAASnZ,EAAK8E,WAAa,GACnC,MACF,KAAKoO,EAAUjU,KACbga,EAAQG,YAAYpZ,EAAK6E,cAAgB,GAG7C,GAAIkU,GAAaC,GAAaD,GAAaE,EACzC,MAEAH,GAAS7X,KAAKkJ,QAAQQ,aAG1B,OAAOmO,EAGTlB,uBAEE,GACE3W,KAAK4O,QAAQqD,EAAU/T,MACvB8B,KAAK4O,QAAQqD,EAAUG,OACvBpS,KAAK4O,QAAQqD,EAAUhU,QACvB+B,KAAK4O,QAAQqD,EAAUjU,MACvB,CACA,MAAMqN,EAAIrL,KAAK4X,+BAA+B5X,KAAKkJ,QAAQqK,WACrDjI,EAAI,EACJ7B,EAAQzJ,KAAKkJ,QAAQQ,aACrBT,GACHjJ,KAAKkJ,QAAQC,WAAanJ,KAAKkJ,QAAQ4F,SAAW9O,KAAKwS,MAAM9S,OAC9DM,KAAKkJ,QAAQ2F,cACb7O,KAAKkJ,QAAQ4F,QAAU,EAEzB,IAAIsJ,EAAY,GAChB,OAAQpY,KAAKkJ,QAAQqK,WACnB,KAAKtB,EAAU/T,IACbka,EAAY,kBACZ,MACF,KAAKnG,EAAUG,KACbgG,EAAY,iBACZ,MACF,KAAKnG,EAAUhU,MACbma,EAAY,kBACZ,MACF,KAAKnG,EAAUjU,KACboa,EAAY,iBAGhBhT,EAAU,OAAQ,CAChBiG,EAAAA,EACAC,EAAAA,EACA7B,MAAAA,EACAR,OAAAA,EACAa,MAAOsO,EACP1S,UAAW1F,KAAKqW,OAAOS,QAK7Bf,aACE,IAAK,IAAIhX,KAAQiB,KAAKqY,oBASpB,GARAjT,EAAU,OAAQ,CAChBiG,EAAGtM,EAAKuZ,QACRhN,EAAGvM,EAAKwZ,QACR3S,UAAW7G,EAAKyZ,WAChB1O,MAAO,aACPpE,UAAW1F,KAAKqW,OAAOtX,OAGrBA,EAAK0Z,WAAY,CACnB,MAAMC,EAActT,EAAU,OAAQ,CACpCiG,EAAGtM,EAAK4Z,QACRrN,EAAGvM,EAAK6Z,QACRhT,UAAW7G,EAAK0Z,WAChB3O,MAAO,aACPpE,UAAW1F,KAAKqW,OAAOtX,OAIrB2Z,EAAYnJ,UAAU+H,GAAKtX,KAAKqW,OAAOS,KAAKvH,UAAU9F,OACxDiP,EAAYlJ,UAMpB6I,oBACE,IAAIQ,EAAY,KAMhB,OALc7Y,KAAKwV,MAAMjW,KAAI,CAACR,EAAMmB,KAClC,MAAMgB,EAAIlB,KAAK8Y,cAAc/Z,EAAM8Z,EAAW3Y,GAE9C,OADA2Y,EAAY9Z,EACLmC,KAKX4X,cAAc/Z,EAAM8Z,EAAW3Y,GACxB2Y,IACHA,EAAYta,EAAWmF,IAAI3E,EAAM,EAAG,QAEtC,MAAMga,EAAY,CAChBC,WAAYza,EAAW+B,OAAOvB,EAAM,KAAMiB,KAAKkJ,QAAQ0D,UACvD,oBAAqBrO,EAAW+B,OAAOvB,EAAM,KAAMiB,KAAKkJ,QAAQ0D,UAChE,iBAAkBrO,EAAW+B,OAAOvB,EAAM,KAAMiB,KAAKkJ,QAAQ0D,UAC7DqM,UACEla,EAAK+E,YAAc+U,EAAU/U,UACzBvF,EAAW+B,OAAOvB,EAAM,IAAKiB,KAAKkJ,QAAQ0D,UAC1C,GACNsM,WACEna,EAAK8E,aAAegV,EAAUhV,WAC1BtF,EAAW+B,OAAOvB,EAAM,QAASiB,KAAKkJ,QAAQ0D,UAC9CrO,EAAW+B,OAAOvB,EAAM,IAAKiB,KAAKkJ,QAAQ0D,UAChDuM,YAAa5a,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UAC1DwM,WAAY7a,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UACzDyM,WACEta,EAAK+E,YAAc+U,EAAU/U,UACzBvF,EAAW+B,OAAOvB,EAAM,SAAUiB,KAAKkJ,QAAQ0D,UAC/C,GACN,oBACE7N,EAAK+E,YAAc+U,EAAU/U,UACzBvF,EAAW+B,OAAOvB,EAAM,QAASiB,KAAKkJ,QAAQ0D,UAC9C,GACN,iBACE7N,EAAK+E,YAAc+U,EAAU/U,UACzB/E,EAAK8E,aAAegV,EAAUhV,WAC5BtF,EAAW+B,OAAOvB,EAAM,QAASiB,KAAKkJ,QAAQ0D,UAC9CrO,EAAW+B,OAAOvB,EAAM,IAAKiB,KAAKkJ,QAAQ0D,UAC5C,GACN0M,UACEva,EAAK8E,aAAegV,EAAUhV,WAC1BtF,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UAC7C,GACN2M,WACExa,EAAK8E,aAAegV,EAAUhV,WAC1BtF,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UAC7C,GACN4M,YACEza,EAAK6E,gBAAkBiV,EAAUjV,cAC7BrF,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UAC7C,GACN6M,WACE1a,EAAK6E,gBAAkBiV,EAAUjV,cAC7BrF,EAAW+B,OAAOvB,EAAM,OAAQiB,KAAKkJ,QAAQ0D,UAC7C,IAGF8M,EAAW,CACfrO,EAAGnL,EAAIF,KAAKkJ,QAAQQ,aACpB6O,QAASvY,KAAKkJ,QAAQ2F,cACtB+J,QAAS5Y,KAAKkJ,QAAQ2F,cAAgB,IAGlC8K,EAAQ,CACZX,WAAYhZ,KAAKkJ,QAAQQ,aAAe,EACxC2P,WAAwC,GAA5BrZ,KAAKkJ,QAAQQ,aACzB,oBAAqB1J,KAAKkJ,QAAQQ,aAAe,EACjD,oBAAiD,EAA5B1J,KAAKkJ,QAAQQ,aAClC,iBAAkB1J,KAAKkJ,QAAQQ,aAAe,EAC9C,iBAAkB1J,KAAKkJ,QAAQQ,aAC/BuP,UAAWjZ,KAAKkJ,QAAQQ,aAAe,EACvC4P,UAAwC,GAA5BtZ,KAAKkJ,QAAQQ,aAAqB,EAC9CwP,WAAY,EACZK,WAAyC,EAA5BvZ,KAAKkJ,QAAQQ,aAAoB,EAC9CyP,YAAanZ,KAAKkJ,QAAQQ,aAAe,EACzC8P,YAA0C,GAA5BxZ,KAAKkJ,QAAQQ,aAAqB,EAChD0P,WAAYpZ,KAAKkJ,QAAQQ,aAAe,EACxC+P,WAAyC,GAA5BzZ,KAAKkJ,QAAQQ,aAAqB,GAGjD,MAAO,CACL+O,WAAYM,EAAU,GAAG/Y,KAAKkJ,QAAQqK,mBACtCiF,WAAYO,EAAU,GAAG/Y,KAAKkJ,QAAQqK,mBACtCoF,QAASe,EAASrO,EAAIsO,EAAM,GAAG3Z,KAAKkJ,QAAQqK,mBAC5CqF,QAASc,EAASd,QAClBN,QAASoB,EAASrO,EAAIsO,EAAM,GAAG3Z,KAAKkJ,QAAQqK,mBAC5CgF,QAASmB,EAASnB,SAItBvC,YACEhW,KAAK4Z,KAAO5Z,KAAKwS,MAAMjT,KAAKkJ,IAC1B,MAAMqD,EAAM,IAAIxD,EAAItI,KAAMyI,GAE1B,OADAzI,KAAKqW,OAAOvK,IAAInG,YAAYmG,EAAIjC,OACzBiC,KAIXmK,cACEjW,KAAK0P,OAAS,GACd,IAAK,IAAIjH,KAAQzI,KAAKwS,MAAO,CAC3B,IAAI9C,EAAS,GACbA,EAASjH,EAAKwE,aACX1N,KAAKsa,IACJ,MAAMC,EAAa9Z,KAAK+Z,SAASF,GACjC,IAAKC,EAAY,OACjB,MAAMnK,EAAQ,IAAIE,EAChB7P,KACAA,KAAK4Z,KAAKE,EAAW/K,QACrB/O,KAAK4Z,KAAKnR,EAAKsG,SAGjB,OADA/O,KAAKqW,OAAO1G,MAAMhK,YAAYgK,EAAMrI,SAC7BqI,KAER2E,OAAO0F,SACVha,KAAK0P,OAAS1P,KAAK0P,OAAO9P,OAAO8P,IAIrCwG,qBACE,IAAK,IAAIpK,KAAO9L,KAAK4Z,KACnB9N,EAAI4D,OAAS1P,KAAK0P,OAAO4E,QAAQ3E,GAE7BA,EAAMG,UAAUrH,KAAKuB,KAAO8B,EAAIrD,KAAKuB,IACrC2F,EAAMI,QAAQtH,KAAKuB,KAAO8B,EAAIrD,KAAKuB,KAM3CmM,YACE,MAAM8D,EAAYja,KAAKgT,KAAKnB,wBAAwBpI,MAC9CyQ,EAAela,KAAKgT,KACvB7N,cAAc,mBACdkD,aAAa,SACZ4R,EAAYC,GACdla,KAAKgT,KAAKnN,aAAa,QAASqU,GAIpC9D,sBACE,MAAM+D,EAAiBna,KAAKgT,KAAKG,cACjC,IAAKgH,EAAgB,OAErB,MAMMC,EAN0B7b,EAAWoE,KACzC3C,KAAKqa,2BACLra,KAAKwO,YACL,QAI2BxO,KAAKkJ,QAAQuF,KACtCzO,KAAKkJ,QAAQQ,aACf1J,KAAKkJ,QAAQQ,aAEfyQ,EAAeG,WAAaF,EAG9B1E,kBACE3Q,EAAEsC,GACArH,KAAKgT,KACLhT,KAAKkJ,QAAQmD,cACb,2BACA,KACErM,KAAKuM,eACLvM,KAAKua,gBAKX5E,kBACE,IAAI6E,GAAc,EACdC,EAAa,EACbC,EAAa,EACbC,GAAmB,EACnBC,GAAoB,EACpBC,EAAgB,KAChBjB,EAAO,GACX5Z,KAAKyM,kBAAoB,KAMzB1H,EAAEsC,GAAGrH,KAAKgT,KAAM,YAAa,yBAAyB,CAACjL,EAAGT,KACxD,MAAMwT,EAAc/V,EAAEmD,QAAQ,eAAgBZ,GAE1CA,EAAQmE,UAAUsP,SAAS,QAC7BJ,GAAmB,EACVrT,EAAQmE,UAAUsP,SAAS,SACpCH,GAAoB,EACXtT,EAAQmE,UAAUsP,SAAS,iBACpCP,GAAc,GAGhBM,EAAYrP,UAAU/H,IAAI,UAE1B+W,EAAa1S,EAAEiT,QACfN,EAAa3S,EAAEkT,QAEfJ,EAAgBC,EAAYzS,aAAa,WACzC,MAAM6S,EAAM,CACVL,KACG7a,KAAKmb,wBAAwBN,IAElCjB,EAAOsB,EAAI3b,KAAKyK,GAAOhK,KAAKmN,QAAQnD,KAEpChK,KAAKyM,kBAAoBoO,EAEzBjB,EAAKvX,SAASyJ,IACZ,MAAMV,EAAOU,EAAIV,KACjBA,EAAKgQ,GAAKhQ,EAAKf,OACfe,EAAKiQ,GAAKjQ,EAAKd,OACfc,EAAKkQ,OAASlQ,EAAKb,WACnBa,EAAKmQ,QAAU,QAInBxW,EAAEsC,GAAGrH,KAAKgT,KAAM,aAAcjL,IAC5B,KAtCOyS,GAAeG,GAAoBC,GAsCf,OAC3B,MAAM3L,EAAKlH,EAAEiT,QAAUP,EACZ1S,EAAEkT,QAEbrB,EAAKvX,SAASyJ,IACZ,MAAMV,EAAOU,EAAIV,KACjBA,EAAKmQ,QAAUvb,KAAKgP,kBAAkBC,GACtCjP,KAAKua,aACDI,EACEE,IAAkB/O,EAAIrD,KAAKuB,GAC7B8B,EAAIkB,oBAAoB,CACtB3B,EAAGD,EAAKgQ,GAAKhQ,EAAKmQ,QAClB9R,MAAO2B,EAAKkQ,OAASlQ,EAAKmQ,UAG5BzP,EAAIkB,oBAAoB,CACtB3B,EAAGD,EAAKgQ,GAAKhQ,EAAKmQ,UAGbX,EACLC,IAAkB/O,EAAIrD,KAAKuB,IAC7B8B,EAAIkB,oBAAoB,CACtBvD,MAAO2B,EAAKkQ,OAASlQ,EAAKmQ,UAGrBf,GACT1O,EAAIkB,oBAAoB,CAAE3B,EAAGD,EAAKgQ,GAAKhQ,EAAKmQ,gBAKlDrW,SAAS4C,iBAAiB,WAAYC,KAChCyS,GAAeG,GAAoBC,IACrChB,EAAKvX,SAASyJ,GAAQA,EAAIjC,MAAM4B,UAAU+D,OAAO,YAGnDgL,GAAc,EACdG,GAAmB,EACnBC,GAAoB,KAGtB7V,EAAEsC,GAAGrH,KAAKgT,KAAM,WAAYjL,IAC1B/H,KAAKyM,kBAAoB,KACzBmN,EAAKvX,SAASyJ,IACCA,EAAIV,KACPmQ,UACVzP,EAAI2B,eACJ3B,EAAIuC,8BAIRrO,KAAKwb,oBAGPA,oBACE,IAAIf,EAAa,EACbC,EAAa,EACbe,EAAc,KACd3P,EAAM,KACNH,EAAgB,KAChBP,EAAO,KAEXrG,EAAEsC,GAAGrH,KAAKgT,KAAM,YAAa,oBAAoB,CAACjL,EAAG0H,KACnDgM,GAAc,EACdhB,EAAa1S,EAAEiT,QACfN,EAAa3S,EAAEkT,QAEf,MACMjR,EADejF,EAAEmD,QAAQ,eAAgBuH,GACvBpH,aAAa,WACrCyD,EAAM9L,KAAKmN,QAAQnD,GAEnB2B,EAAgBG,EAAIH,cACpBP,EAAOU,EAAIV,KAEXO,EAAc4P,QAAU,EACxB5P,EAAc2P,OAAS3P,EAAcpB,WACrCoB,EAAc+P,QAAU/P,EAAcpB,WACtCoB,EAAcgQ,OAASvQ,EAAKb,WAAaoB,EAAcpB,cAGzDxF,EAAEsC,GAAGrH,KAAKgT,KAAM,aAAcjL,IAC5B,IAAK0T,EAAa,OAClB,IAAIxM,EAAKlH,EAAEiT,QAAUP,EACZ1S,EAAEkT,QAEPhM,EAAKtD,EAAcgQ,SACrB1M,EAAKtD,EAAcgQ,QAEjB1M,EAAKtD,EAAc+P,SACrBzM,EAAKtD,EAAc+P,QAGrB,MAAME,EAAU9P,EAAIC,iBACpBhH,EAAEU,KAAKkG,EAAe,QAASA,EAAc2P,OAASrM,GACtDlK,EAAEU,KAAKmW,EAAS,SAAU9P,EAAIG,+BAC9BN,EAAc4P,QAAUtM,KAG1BlK,EAAEsC,GAAGrH,KAAKgT,KAAM,WAAW,KACzByI,GAAc,EACR9P,GAAiBA,EAAc4P,UACrCzP,EAAIoC,mBACJpC,EAAIuC,2BAIR8M,wBAAwBtB,GACtB,IAAIgC,EAAM,GACNC,EAAa,CAACjC,GAClB,KAAOiC,EAAWpc,QAAQ,CACxB,MAAM0U,EAAO0H,EAAW1O,QAAO,CAAC2O,EAAKzO,IACnCyO,EAAMA,EAAInc,OAAOI,KAAK2U,eAAerH,KAEpC,IAEHuO,EAAMA,EAAIjc,OAAOwU,GACjB0H,EAAa1H,EAAKE,QAAQpT,IAAO4a,EAAWvZ,SAASrB,KAGvD,OAAO2a,EAAIvH,OAAO0F,SAGpBhL,kBAAkBC,GAChB,IACEC,EACAC,EAFEC,EAAMH,EA2BV,OAvBIjP,KAAK4O,QAAQqD,EAAUG,OACzBlD,EAAMD,GAAMjP,KAAKkJ,QAAQQ,aAAe,GACxCyF,EACEC,EACAF,GACCA,EAAMlP,KAAKkJ,QAAQQ,aAAe,GAC/B,EACA1J,KAAKkJ,QAAQQ,aAAe,IACzB1J,KAAK4O,QAAQqD,EAAUhU,QAChCiR,EAAMD,GAAMjP,KAAKkJ,QAAQQ,aAAe,IACxCyF,EACEC,EACAF,GACCA,EAAMlP,KAAKkJ,QAAQQ,aAAe,GAC/B,EACA1J,KAAKkJ,QAAQQ,aAAe,MAElCwF,EAAMD,EAAKjP,KAAKkJ,QAAQQ,aACxByF,EACEC,EACAF,GACCA,EAAMlP,KAAKkJ,QAAQQ,aAAe,EAAI,EAAI1J,KAAKkJ,QAAQQ,eAErDyF,EAGT5C,eACE,IAAIvM,KAAKgT,KAAKgJ,iBAAiB,iBAAiB3Z,SAAS4Z,IACvDA,EAAGxQ,UAAU+D,OAAO,aAIxBZ,QAAQsN,GACN,MAAqB,iBAAVA,EACFlc,KAAKkJ,QAAQqK,YAAc2I,IAGhCC,MAAMC,QAAQF,IACTA,EAAMG,MAAMvH,GAAS9U,KAAKkJ,QAAQqK,YAAcuB,IAM3DiF,SAAS/P,GACP,OAAOhK,KAAKwS,MAAM8J,MAAM7T,GACfA,EAAKuB,KAAOA,IAIvBmD,QAAQnD,GACN,OAAOhK,KAAK4Z,KAAK0C,MAAMxQ,GACdA,EAAIrD,KAAKuB,KAAOA,IAI3BsC,WAAWpD,GACJlJ,KAAKuc,QACRvc,KAAKuc,MAAQ,IAAIvL,EACfhR,KAAKoT,cACLpT,KAAKkJ,QAAQuK,oBAGjBzT,KAAKuc,MAAMjL,KAAKpI,GAGlBqR,aACEva,KAAKuc,OAASvc,KAAKuc,MAAMnL,OAG3B5E,cAAc3F,EAAO2V,GACfxc,KAAKkJ,QAAQ,MAAQrC,IACvB7G,KAAKkJ,QAAQ,MAAQrC,GAAO4V,MAAM,KAAMD,GAU5CnC,2BACE,OAAOra,KAAKwS,MACTjT,KAAKkJ,GAASA,EAAKkE,SACnBS,QAAO,CAACsP,EAAWjH,IAClBA,GAAYiH,EAAYjH,EAAWiH,IASzC9G,QACE5V,KAAKgT,KAAKpN,UAAY,WAI1B0M,EAAML,UAAYA"} \ No newline at end of file diff --git a/index.html b/index.html index 34cb4d2..3ef6df7 100644 --- a/index.html +++ b/index.html @@ -1,111 +1,112 @@ - + - - - Simple Gantt - - - - - -
-

Interactive Gantt Chart entirely made in SVG!

-
-
- - - \ No newline at end of file + + + Simple Gantt + + + + + +
+

Interactive Gantt Chart entirely made in SVG!

+
+
+ + + diff --git a/package.json b/package.json index 2b61aa0..85de70c 100755 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "eslint-config-prettier": "^2.9.0", "eslint-plugin-prettier": "^2.6.0", "jest": "^22.2.1", - "prettier": "^2.6.2", + "prettier": "3.2.5", "rollup": "^2.70.2", "rollup-plugin-sass": "^1.2.12", "rollup-plugin-terser": "^7.0.2" diff --git a/rollup.config.js b/rollup.config.js index 0fb9ec5..ed53480 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,37 +1,37 @@ -import sass from 'rollup-plugin-sass'; -import { terser } from 'rollup-plugin-terser'; +import sass from "rollup-plugin-sass"; +import { terser } from "rollup-plugin-terser"; const dev = { - input: 'src/index.js', - output: { - name: 'Gantt', - file: 'dist/frappe-gantt.js', - sourcemap: true, - format: 'iife', - }, - plugins: [ - sass({ - output: true, - }), - ], + input: "src/index.js", + output: { + name: "Gantt", + file: "dist/frappe-gantt.js", + sourcemap: true, + format: "iife", + }, + plugins: [ + sass({ + output: true, + }), + ], }; const prod = { - input: 'src/index.js', - output: { - name: 'Gantt', - file: 'dist/frappe-gantt.min.js', - sourcemap: true, - format: 'iife', - }, - plugins: [ - sass({ - output: true, - options: { - outputStyle: 'compressed', - }, - }), - terser(), - ], + input: "src/index.js", + output: { + name: "Gantt", + file: "dist/frappe-gantt.min.js", + sourcemap: true, + format: "iife", + }, + plugins: [ + sass({ + output: true, + options: { + outputStyle: "compressed", + }, + }), + terser(), + ], }; export default [dev, prod]; diff --git a/src/arrow.js b/src/arrow.js index f1c6ad6..71647a0 100644 --- a/src/arrow.js +++ b/src/arrow.js @@ -1,52 +1,52 @@ -import { createSVG } from './svg_utils'; +import { createSVG } from "./svg_utils"; export default class Arrow { - constructor(gantt, from_task, to_task) { - this.gantt = gantt; - this.from_task = from_task; - this.to_task = to_task; + constructor(gantt, from_task, to_task) { + this.gantt = gantt; + this.from_task = from_task; + this.to_task = to_task; - this.calculate_path(); - this.draw(); + this.calculate_path(); + this.draw(); + } + + calculate_path() { + let start_x = + this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2; + + const condition = () => + this.to_task.$bar.getX() < start_x + this.gantt.options.padding && + start_x > this.from_task.$bar.getX() + this.gantt.options.padding; + + while (condition()) { + start_x -= 10; } - calculate_path() { - let start_x = - this.from_task.$bar.getX() + this.from_task.$bar.getWidth() / 2; + const start_y = + this.gantt.options.header_height + + this.gantt.options.bar_height + + (this.gantt.options.padding + this.gantt.options.bar_height) * + this.from_task.task._index + + this.gantt.options.padding; - const condition = () => - this.to_task.$bar.getX() < start_x + this.gantt.options.padding && - start_x > this.from_task.$bar.getX() + this.gantt.options.padding; + const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2; + const end_y = + this.gantt.options.header_height + + this.gantt.options.bar_height / 2 + + (this.gantt.options.padding + this.gantt.options.bar_height) * + this.to_task.task._index + + this.gantt.options.padding; - while (condition()) { - start_x -= 10; - } + const from_is_below_to = + this.from_task.task._index > this.to_task.task._index; + const curve = this.gantt.options.arrow_curve; + const clockwise = from_is_below_to ? 1 : 0; + const curve_y = from_is_below_to ? -curve : curve; + const offset = from_is_below_to + ? end_y + this.gantt.options.arrow_curve + : end_y - this.gantt.options.arrow_curve; - const start_y = - this.gantt.options.header_height + - this.gantt.options.bar_height + - (this.gantt.options.padding + this.gantt.options.bar_height) * - this.from_task.task._index + - this.gantt.options.padding; - - const end_x = this.to_task.$bar.getX() - this.gantt.options.padding / 2; - const end_y = - this.gantt.options.header_height + - this.gantt.options.bar_height / 2 + - (this.gantt.options.padding + this.gantt.options.bar_height) * - this.to_task.task._index + - this.gantt.options.padding; - - const from_is_below_to = - this.from_task.task._index > this.to_task.task._index; - const curve = this.gantt.options.arrow_curve; - const clockwise = from_is_below_to ? 1 : 0; - const curve_y = from_is_below_to ? -curve : curve; - const offset = from_is_below_to - ? end_y + this.gantt.options.arrow_curve - : end_y - this.gantt.options.arrow_curve; - - this.path = ` + this.path = ` M ${start_x} ${start_y} V ${offset} a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curve_y} @@ -55,18 +55,16 @@ export default class Arrow { l 5 5 l -5 5`; - if ( - this.to_task.$bar.getX() < - this.from_task.$bar.getX() + this.gantt.options.padding - ) { - const down_1 = this.gantt.options.padding / 2 - curve; - const down_2 = - this.to_task.$bar.getY() + - this.to_task.$bar.getHeight() / 2 - - curve_y; - const left = this.to_task.$bar.getX() - this.gantt.options.padding; + if ( + this.to_task.$bar.getX() < + this.from_task.$bar.getX() + this.gantt.options.padding + ) { + const down_1 = this.gantt.options.padding / 2 - curve; + const down_2 = + this.to_task.$bar.getY() + this.to_task.$bar.getHeight() / 2 - curve_y; + const left = this.to_task.$bar.getX() - this.gantt.options.padding; - this.path = ` + this.path = ` M ${start_x} ${start_y} v ${down_1} a ${curve} ${curve} 0 0 1 -${curve} ${curve} @@ -78,19 +76,19 @@ export default class Arrow { m -5 -5 l 5 5 l -5 5`; - } } + } - draw() { - this.element = createSVG('path', { - d: this.path, - 'data-from': this.from_task.task.id, - 'data-to': this.to_task.task.id, - }); - } + draw() { + this.element = createSVG("path", { + d: this.path, + "data-from": this.from_task.task.id, + "data-to": this.to_task.task.id, + }); + } - update() { - this.calculate_path(); - this.element.setAttribute('d', this.path); - } + update() { + this.calculate_path(); + this.element.setAttribute("d", this.path); + } } diff --git a/src/bar.js b/src/bar.js index 41fbc1f..a6a3be1 100644 --- a/src/bar.js +++ b/src/bar.js @@ -1,471 +1,482 @@ -import date_utils from './date_utils'; -import { $, createSVG, animateSVG } from './svg_utils'; +import date_utils from "./date_utils"; +import { $, createSVG, animateSVG } from "./svg_utils"; export default class Bar { - constructor(gantt, task) { - this.set_defaults(gantt, task); - this.prepare(); - this.draw(); - this.bind(); + constructor(gantt, task) { + this.set_defaults(gantt, task); + this.prepare(); + this.draw(); + this.bind(); + } + + set_defaults(gantt, task) { + this.action_completed = false; + this.gantt = gantt; + this.task = task; + } + + prepare() { + this.prepare_values(); + this.prepare_helpers(); + } + + prepare_values() { + this.invalid = this.task.invalid; + this.height = this.gantt.options.bar_height; + this.compute_x(); + this.compute_y(); + this.compute_duration(); + this.corner_radius = this.gantt.options.bar_corner_radius; + this.width = this.gantt.options.column_width * this.duration; + this.progress_width = + this.gantt.options.column_width * + this.duration * + (this.task.progress / 100) || 0; + this.group = createSVG("g", { + class: "bar-wrapper " + (this.task.custom_class || ""), + "data-id": this.task.id, + }); + this.bar_group = createSVG("g", { + class: "bar-group", + append_to: this.group, + }); + this.handle_group = createSVG("g", { + class: "handle-group", + append_to: this.group, + }); + } + + prepare_helpers() { + SVGElement.prototype.getX = function () { + return +this.getAttribute("x"); + }; + SVGElement.prototype.getY = function () { + return +this.getAttribute("y"); + }; + SVGElement.prototype.getWidth = function () { + return +this.getAttribute("width"); + }; + SVGElement.prototype.getHeight = function () { + return +this.getAttribute("height"); + }; + SVGElement.prototype.getEndX = function () { + return this.getX() + this.getWidth(); + }; + } + + prepare_expected_progress_values() { + this.compute_expected_progress(); + this.expected_progress_width = + this.gantt.options.column_width * + this.duration * + (this.expected_progress / 100) || 0; + } + + draw() { + this.draw_bar(); + if (this.gantt.options.show_expected_progress) { + this.prepare_expected_progress_values(); + this.draw_expected_progress_bar(); + } + this.draw_progress_bar(); + this.draw_label(); + this.draw_resize_handles(); + } + + draw_bar() { + this.$bar = createSVG("rect", { + x: this.x, + y: this.y, + width: this.width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar", + append_to: this.bar_group, + }); + + animateSVG(this.$bar, "width", 0, this.width); + + if (this.invalid) { + this.$bar.classList.add("bar-invalid"); + } + } + + draw_expected_progress_bar() { + if (this.invalid) return; + this.$expected_bar_progress = createSVG("rect", { + x: this.x, + y: this.y, + width: this.expected_progress_width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar-expected-progress", + append_to: this.bar_group, + }); + + animateSVG( + this.$expected_bar_progress, + "width", + 0, + this.expected_progress_width, + ); + } + + draw_progress_bar() { + if (this.invalid) return; + this.$bar_progress = createSVG("rect", { + x: this.x, + y: this.y, + width: this.progress_width, + height: this.height, + rx: this.corner_radius, + ry: this.corner_radius, + class: "bar-progress", + append_to: this.bar_group, + }); + + animateSVG(this.$bar_progress, "width", 0, this.progress_width); + } + + draw_label() { + createSVG("text", { + x: this.x + this.width / 2, + y: this.y + this.height / 2, + innerHTML: this.task.name, + class: "bar-label", + append_to: this.bar_group, + }); + // labels get BBox in the next tick + requestAnimationFrame(() => this.update_label_position()); + } + + draw_resize_handles() { + if (this.invalid) return; + + const bar = this.$bar; + const handle_width = 8; + + createSVG("rect", { + x: bar.getX() + bar.getWidth() - 9, + y: bar.getY() + 1, + width: handle_width, + height: this.height - 2, + rx: this.corner_radius, + ry: this.corner_radius, + class: "handle right", + append_to: this.handle_group, + }); + + createSVG("rect", { + x: bar.getX() + 1, + y: bar.getY() + 1, + width: handle_width, + height: this.height - 2, + rx: this.corner_radius, + ry: this.corner_radius, + class: "handle left", + append_to: this.handle_group, + }); + + this.$handle_progress = createSVG("polygon", { + points: this.get_progress_polygon_points().join(","), + class: "handle progress", + append_to: this.handle_group, + }); + } + + get_progress_polygon_points() { + const bar_progress = this.$bar_progress; + return [ + bar_progress.getEndX() - 5, + bar_progress.getY() + bar_progress.getHeight(), + bar_progress.getEndX() + 5, + bar_progress.getY() + bar_progress.getHeight(), + bar_progress.getEndX(), + bar_progress.getY() + bar_progress.getHeight() - 8.66, + ]; + } + + bind() { + if (this.invalid) return; + this.setup_click_event(); + } + + setup_click_event() { + $.on(this.group, "focus " + this.gantt.options.popup_trigger, (e) => { + if (this.action_completed) { + // just finished a move action, wait for a few seconds + return; + } + + this.show_popup(); + this.gantt.unselect_all(); + this.group.classList.add("active"); + }); + + $.on(this.group, "dblclick", (e) => { + if (this.action_completed) { + // just finished a move action, wait for a few seconds + return; + } + + this.gantt.trigger_event("click", [this.task]); + }); + } + + show_popup() { + if (this.gantt.bar_being_dragged) return; + + const start_date = date_utils.format( + this.task._start, + "MMM D", + this.gantt.options.language, + ); + const end_date = date_utils.format( + date_utils.add(this.task._end, -1, "second"), + "MMM D", + this.gantt.options.language, + ); + const subtitle = start_date + " - " + end_date; + + this.gantt.show_popup({ + target_element: this.$bar, + title: this.task.name, + subtitle: subtitle, + task: this.task, + }); + } + + update_bar_position({ x = null, width = null }) { + const bar = this.$bar; + if (x) { + // get all x values of parent task + const xs = this.task.dependencies.map((dep) => { + return this.gantt.get_bar(dep).$bar.getX(); + }); + // child task must not go before parent + const valid_x = xs.reduce((prev, curr) => { + return x >= curr; + }, x); + if (!valid_x) { + width = null; + return; + } + this.update_attr(bar, "x", x); + } + if (width) { + this.update_attr(bar, "width", width); + } + this.update_label_position(); + this.update_handle_position(); + if (this.gantt.options.show_expected_progress) { + this.date_changed(); + this.compute_duration(); + this.update_expected_progressbar_position(); + } + this.update_progressbar_position(); + this.update_arrow_position(); + } + + date_changed() { + let changed = false; + const { new_start_date, new_end_date } = this.compute_start_end_date(); + + if (Number(this.task._start) !== Number(new_start_date)) { + changed = true; + this.task._start = new_start_date; } - set_defaults(gantt, task) { - this.action_completed = false; - this.gantt = gantt; - this.task = task; + if (Number(this.task._end) !== Number(new_end_date)) { + changed = true; + this.task._end = new_end_date; } - prepare() { - this.prepare_values(); - this.prepare_helpers(); + if (!changed) return; + + this.gantt.trigger_event("date_change", [ + this.task, + new_start_date, + date_utils.add(new_end_date, -1, "second"), + ]); + } + + progress_changed() { + const new_progress = this.compute_progress(); + this.task.progress = new_progress; + this.gantt.trigger_event("progress_change", [this.task, new_progress]); + } + + set_action_completed() { + this.action_completed = true; + setTimeout(() => (this.action_completed = false), 1000); + } + + compute_start_end_date() { + const bar = this.$bar; + const x_in_units = bar.getX() / this.gantt.options.column_width; + const new_start_date = date_utils.add( + this.gantt.gantt_start, + x_in_units * this.gantt.options.step, + "hour", + ); + const width_in_units = bar.getWidth() / this.gantt.options.column_width; + const new_end_date = date_utils.add( + new_start_date, + width_in_units * this.gantt.options.step, + "hour", + ); + + return { new_start_date, new_end_date }; + } + + compute_progress() { + const progress = + (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100; + return parseInt(progress, 10); + } + + compute_expected_progress() { + this.expected_progress = + date_utils.diff(date_utils.today(), this.task._start, "hour") / + this.gantt.options.step; + this.expected_progress = + ((this.expected_progress < this.duration + ? this.expected_progress + : this.duration) * + 100) / + this.duration; + } + + compute_x() { + const { step, column_width } = this.gantt.options; + const task_start = this.task._start; + const gantt_start = this.gantt.gantt_start; + + const diff = date_utils.diff(task_start, gantt_start, "hour"); + let x = (diff / step) * column_width; + + if (this.gantt.view_is("Month")) { + const diff = date_utils.diff(task_start, gantt_start, "day"); + x = (diff * column_width) / 30; } + this.x = x; + } - prepare_values() { - this.invalid = this.task.invalid; - this.height = this.gantt.options.bar_height; - this.compute_x(); - this.compute_y(); - this.compute_duration(); - this.corner_radius = this.gantt.options.bar_corner_radius; - this.width = this.gantt.options.column_width * this.duration; - this.progress_width = - this.gantt.options.column_width * - this.duration * - (this.task.progress / 100) || 0; - this.group = createSVG('g', { - class: 'bar-wrapper ' + (this.task.custom_class || ''), - 'data-id': this.task.id, - }); - this.bar_group = createSVG('g', { - class: 'bar-group', - append_to: this.group, - }); - this.handle_group = createSVG('g', { - class: 'handle-group', - append_to: this.group, - }); + compute_y() { + this.y = + this.gantt.options.header_height + + this.gantt.options.padding + + this.task._index * (this.height + this.gantt.options.padding); + } + + compute_duration() { + this.duration = + date_utils.diff(this.task._end, this.task._start, "hour") / + this.gantt.options.step; + } + + get_snap_position(dx) { + let odx = dx, + rem, + position; + + if (this.gantt.view_is("Week")) { + rem = dx % (this.gantt.options.column_width / 7); + position = + odx - + rem + + (rem < this.gantt.options.column_width / 14 + ? 0 + : this.gantt.options.column_width / 7); + } else if (this.gantt.view_is("Month")) { + rem = dx % (this.gantt.options.column_width / 30); + position = + odx - + rem + + (rem < this.gantt.options.column_width / 60 + ? 0 + : this.gantt.options.column_width / 30); + } else { + rem = dx % this.gantt.options.column_width; + position = + odx - + rem + + (rem < this.gantt.options.column_width / 2 + ? 0 + : this.gantt.options.column_width); } + return position; + } - prepare_helpers() { - SVGElement.prototype.getX = function () { - return +this.getAttribute('x'); - }; - SVGElement.prototype.getY = function () { - return +this.getAttribute('y'); - }; - SVGElement.prototype.getWidth = function () { - return +this.getAttribute('width'); - }; - SVGElement.prototype.getHeight = function () { - return +this.getAttribute('height'); - }; - SVGElement.prototype.getEndX = function () { - return this.getX() + this.getWidth(); - }; + update_attr(element, attr, value) { + value = +value; + if (!isNaN(value)) { + element.setAttribute(attr, value); } + return element; + } - prepare_expected_progress_values() { - this.compute_expected_progress(); - this.expected_progress_width = - this.gantt.options.column_width * - this.duration * - (this.expected_progress / 100) || 0; + update_expected_progressbar_position() { + if (this.invalid) return; + this.$expected_bar_progress.setAttribute("x", this.$bar.getX()); + this.compute_expected_progress(); + this.$expected_bar_progress.setAttribute( + "width", + this.gantt.options.column_width * + this.duration * + (this.expected_progress / 100) || 0, + ); + } + + update_progressbar_position() { + if (this.invalid) return; + this.$bar_progress.setAttribute("x", this.$bar.getX()); + this.$bar_progress.setAttribute( + "width", + this.$bar.getWidth() * (this.task.progress / 100), + ); + } + + update_label_position() { + const bar = this.$bar, + label = this.group.querySelector(".bar-label"); + + if (label.getBBox().width > bar.getWidth()) { + label.classList.add("big"); + label.setAttribute("x", bar.getX() + bar.getWidth() + 5); + } else { + label.classList.remove("big"); + label.setAttribute("x", bar.getX() + bar.getWidth() / 2); } + } - draw() { - this.draw_bar(); - if (this.gantt.options.show_expected_progress) { - this.prepare_expected_progress_values(); - this.draw_expected_progress_bar(); - } - this.draw_progress_bar(); - this.draw_label(); - this.draw_resize_handles(); - } - - draw_bar() { - this.$bar = createSVG('rect', { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar', - append_to: this.bar_group, - }); - - animateSVG(this.$bar, 'width', 0, this.width); - - if (this.invalid) { - this.$bar.classList.add('bar-invalid'); - } - } - - draw_expected_progress_bar() { - if (this.invalid) return; - this.$expected_bar_progress = createSVG('rect', { - x: this.x, - y: this.y, - width: this.expected_progress_width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar-expected-progress', - append_to: this.bar_group, - }); - - animateSVG(this.$expected_bar_progress, 'width', 0, this.expected_progress_width); - } - - draw_progress_bar() { - if (this.invalid) return; - this.$bar_progress = createSVG('rect', { - x: this.x, - y: this.y, - width: this.progress_width, - height: this.height, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'bar-progress', - append_to: this.bar_group, - }); - - animateSVG(this.$bar_progress, 'width', 0, this.progress_width); - } - - draw_label() { - createSVG('text', { - x: this.x + this.width / 2, - y: this.y + this.height / 2, - innerHTML: this.task.name, - class: 'bar-label', - append_to: this.bar_group, - }); - // labels get BBox in the next tick - requestAnimationFrame(() => this.update_label_position()); - } - - draw_resize_handles() { - if (this.invalid) return; - - const bar = this.$bar; - const handle_width = 8; - - createSVG('rect', { - x: bar.getX() + bar.getWidth() - 9, - y: bar.getY() + 1, - width: handle_width, - height: this.height - 2, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'handle right', - append_to: this.handle_group, - }); - - createSVG('rect', { - x: bar.getX() + 1, - y: bar.getY() + 1, - width: handle_width, - height: this.height - 2, - rx: this.corner_radius, - ry: this.corner_radius, - class: 'handle left', - append_to: this.handle_group, - }); - - if (this.task.progress < 100) { - this.$handle_progress = createSVG('polygon', { - points: this.get_progress_polygon_points().join(','), - class: 'handle progress', - append_to: this.handle_group, - }); - } - } - - get_progress_polygon_points() { - const bar_progress = this.$bar_progress; - return [ - bar_progress.getEndX() - 5, - bar_progress.getY() + bar_progress.getHeight(), - bar_progress.getEndX() + 5, - bar_progress.getY() + bar_progress.getHeight(), - bar_progress.getEndX(), - bar_progress.getY() + bar_progress.getHeight() - 8.66, - ]; - } - - bind() { - if (this.invalid) return; - this.setup_click_event(); - } - - setup_click_event() { - $.on(this.group, 'focus ' + this.gantt.options.popup_trigger, (e) => { - if (this.action_completed) { - // just finished a move action, wait for a few seconds - return; - } - - this.show_popup(); - this.gantt.unselect_all(); - this.group.classList.add('active'); - }); - - $.on(this.group, 'dblclick', (e) => { - if (this.action_completed) { - // just finished a move action, wait for a few seconds - return; - } - - this.gantt.trigger_event('click', [this.task]); - }); - } - - show_popup() { - if (this.gantt.bar_being_dragged) return; - - const start_date = date_utils.format( - this.task._start, - 'MMM D', - this.gantt.options.language - ); - const end_date = date_utils.format( - date_utils.add(this.task._end, -1, 'second'), - 'MMM D', - this.gantt.options.language - ); - const subtitle = start_date + ' - ' + end_date; - - this.gantt.show_popup({ - target_element: this.$bar, - title: this.task.name, - subtitle: subtitle, - task: this.task, - }); - } - - update_bar_position({ x = null, width = null }) { - const bar = this.$bar; - if (x) { - // get all x values of parent task - const xs = this.task.dependencies.map((dep) => { - return this.gantt.get_bar(dep).$bar.getX(); - }); - // child task must not go before parent - const valid_x = xs.reduce((prev, curr) => { - return x >= curr; - }, x); - if (!valid_x) { - width = null; - return; - } - this.update_attr(bar, 'x', x); - } - if (width) { - this.update_attr(bar, 'width', width); - } - this.update_label_position(); - this.update_handle_position(); - if (this.gantt.options.show_expected_progress){ - this.date_changed(); - this.compute_duration(); - this.update_expected_progressbar_position(); - } - this.update_progressbar_position(); - this.update_arrow_position(); - } - - date_changed() { - let changed = false; - const { new_start_date, new_end_date } = this.compute_start_end_date(); - - if (Number(this.task._start) !== Number(new_start_date)) { - changed = true; - this.task._start = new_start_date; - } - - if (Number(this.task._end) !== Number(new_end_date)) { - changed = true; - this.task._end = new_end_date; - } - - if (!changed) return; - - this.gantt.trigger_event('date_change', [ - this.task, - new_start_date, - date_utils.add(new_end_date, -1, 'second'), - ]); - } - - progress_changed() { - const new_progress = this.compute_progress(); - this.task.progress = new_progress; - this.gantt.trigger_event('progress_change', [this.task, new_progress]); - } - - set_action_completed() { - this.action_completed = true; - setTimeout(() => (this.action_completed = false), 1000); - } - - compute_start_end_date() { - const bar = this.$bar; - const x_in_units = bar.getX() / this.gantt.options.column_width; - const new_start_date = date_utils.add( - this.gantt.gantt_start, - x_in_units * this.gantt.options.step, - 'hour' - ); - const width_in_units = bar.getWidth() / this.gantt.options.column_width; - const new_end_date = date_utils.add( - new_start_date, - width_in_units * this.gantt.options.step, - 'hour' - ); - - return { new_start_date, new_end_date }; - } - - compute_progress() { - const progress = - (this.$bar_progress.getWidth() / this.$bar.getWidth()) * 100; - return parseInt(progress, 10); - } - - compute_expected_progress() { - this.expected_progress = date_utils.diff(date_utils.today(), this.task._start, 'hour') / this.gantt.options.step; - this.expected_progress = ((this.expected_progress < this.duration) ? this.expected_progress : this.duration) * 100 / this.duration; - } - - compute_x() { - const { step, column_width } = this.gantt.options; - const task_start = this.task._start; - const gantt_start = this.gantt.gantt_start; - - const diff = date_utils.diff(task_start, gantt_start, 'hour'); - let x = (diff / step) * column_width; - - if (this.gantt.view_is('Month')) { - const diff = date_utils.diff(task_start, gantt_start, 'day'); - x = (diff * column_width) / 30; - } - this.x = x; - } - - compute_y() { - this.y = ( - this.gantt.options.header_height + - this.gantt.options.padding + - this.task._index * (this.height + this.gantt.options.padding) - ); - } - - compute_duration() { - this.duration = date_utils.diff(this.task._end, this.task._start, 'hour') / - this.gantt.options.step; - } - - get_snap_position(dx) { - let odx = dx, - rem, - position; - - if (this.gantt.view_is('Week')) { - rem = dx % (this.gantt.options.column_width / 7); - position = - odx - - rem + - (rem < this.gantt.options.column_width / 14 - ? 0 - : this.gantt.options.column_width / 7); - } else if (this.gantt.view_is('Month')) { - rem = dx % (this.gantt.options.column_width / 30); - position = - odx - - rem + - (rem < this.gantt.options.column_width / 60 - ? 0 - : this.gantt.options.column_width / 30); - } else { - rem = dx % this.gantt.options.column_width; - position = - odx - - rem + - (rem < this.gantt.options.column_width / 2 - ? 0 - : this.gantt.options.column_width); - } - return position; - } - - update_attr(element, attr, value) { - value = +value; - if (!isNaN(value)) { - element.setAttribute(attr, value); - } - return element; - } - - update_expected_progressbar_position() { - if (this.invalid) return; - this.$expected_bar_progress.setAttribute('x', this.$bar.getX()); - this.compute_expected_progress(); - this.$expected_bar_progress.setAttribute( - 'width', - this.gantt.options.column_width * this.duration * (this.expected_progress / 100) || 0 - ); - } - - update_progressbar_position() { - if (this.invalid) return; - this.$bar_progress.setAttribute('x', this.$bar.getX()); - this.$bar_progress.setAttribute( - 'width', - this.$bar.getWidth() * (this.task.progress / 100) - ); - } - - update_label_position() { - const bar = this.$bar, - label = this.group.querySelector('.bar-label'); - - if (label.getBBox().width > bar.getWidth()) { - label.classList.add('big'); - label.setAttribute('x', bar.getX() + bar.getWidth() + 5); - } else { - label.classList.remove('big'); - label.setAttribute('x', bar.getX() + bar.getWidth() / 2); - } - } - - update_handle_position() { - if (this.invalid) return; - const bar = this.$bar; - this.handle_group - .querySelector('.handle.left') - .setAttribute('x', bar.getX() + 1); - this.handle_group - .querySelector('.handle.right') - .setAttribute('x', bar.getEndX() - 9); - const handle = this.group.querySelector('.handle.progress'); - handle && - handle.setAttribute('points', this.get_progress_polygon_points()); - } - - update_arrow_position() { - this.arrows = this.arrows || []; - for (let arrow of this.arrows) { - arrow.update(); - } + update_handle_position() { + if (this.invalid) return; + const bar = this.$bar; + this.handle_group + .querySelector(".handle.left") + .setAttribute("x", bar.getX() + 1); + this.handle_group + .querySelector(".handle.right") + .setAttribute("x", bar.getEndX() - 9); + const handle = this.group.querySelector(".handle.progress"); + handle && handle.setAttribute("points", this.get_progress_polygon_points()); + } + + update_arrow_position() { + this.arrows = this.arrows || []; + for (let arrow of this.arrows) { + arrow.update(); } + } } function isFunction(functionToCheck) { - var getType = {}; - return ( - functionToCheck && - getType.toString.call(functionToCheck) === '[object Function]' - ); + var getType = {}; + return ( + functionToCheck && + getType.toString.call(functionToCheck) === "[object Function]" + ); } diff --git a/src/dark.scss b/src/dark.scss index 4edc905..e051f3f 100644 --- a/src/dark.scss +++ b/src/dark.scss @@ -9,89 +9,89 @@ $text-color-dark: #f7f7f7; $blue-dark: #8a8aff; .dark > .gantt-container .gantt { - .grid-header { - fill: #252525; - stroke: $border-color-dark; - } - .grid-row { - fill: #252525; - } - .grid-row:nth-child(even) { - fill: $light-bg-dark; - } - .row-line { - stroke: $light-border-color-dark; - } - .tick { - stroke: $border-color-dark; - } - .today-highlight { - opacity: 0.2; - } + .grid-header { + fill: #252525; + stroke: $border-color-dark; + } + .grid-row { + fill: #252525; + } + .grid-row:nth-child(even) { + fill: $light-bg-dark; + } + .row-line { + stroke: $light-border-color-dark; + } + .tick { + stroke: $border-color-dark; + } + .today-highlight { + opacity: 0.2; + } - .arrow { - stroke: $text-muted-dark; - } + .arrow { + stroke: $text-muted-dark; + } - .bar { - fill: $bar-color-dark; - stroke: none; - } - .bar-progress { - fill: $blue-dark; - } - .bar-invalid { - fill: transparent; - stroke: $bar-stroke-dark; + .bar { + fill: $bar-color-dark; + stroke: none; + } + .bar-progress { + fill: $blue-dark; + } + .bar-invalid { + fill: transparent; + stroke: $bar-stroke-dark; - &~.bar-label { - fill: $text-light-dark; - } - } + & ~ .bar-label { + fill: $text-light-dark; + } + } - .bar-label.big { - fill: $text-light-dark; - } + .bar-label.big { + fill: $text-light-dark; + } - .bar-wrapper { - &:hover { - .bar { - fill: lighten($bar-color-dark, 5); - } + .bar-wrapper { + &:hover { + .bar { + fill: lighten($bar-color-dark, 5); + } - .bar-progress { - fill: lighten($blue-dark, 5); - } - } + .bar-progress { + fill: lighten($blue-dark, 5); + } + } - &.active { - .bar { - fill: lighten($bar-color-dark, 5); - } + &.active { + .bar { + fill: lighten($bar-color-dark, 5); + } - .bar-progress { - fill: lighten($blue-dark, 5); - } - } - } + .bar-progress { + fill: lighten($blue-dark, 5); + } + } + } - .upper-text { - fill: #a2a2a2; - } - .lower-text { - fill: $text-color-dark; - } + .upper-text { + fill: #a2a2a2; + } + .lower-text { + fill: $text-color-dark; + } } .dark > .gantt-container { - .popup-wrapper { - background-color: #333; + .popup-wrapper { + background-color: #333; - .title { - border-color: lighten($blue-dark, 5);; - } - .pointer { - border-top-color: #333; - } - } -} \ No newline at end of file + .title { + border-color: lighten($blue-dark, 5); + } + .pointer { + border-top-color: #333; + } + } +} diff --git a/src/date_utils.js b/src/date_utils.js index 3782cea..550dc94 100644 --- a/src/date_utils.js +++ b/src/date_utils.js @@ -1,231 +1,253 @@ -const YEAR = 'year'; -const MONTH = 'month'; -const DAY = 'day'; -const HOUR = 'hour'; -const MINUTE = 'minute'; -const SECOND = 'second'; -const MILLISECOND = 'millisecond'; +const YEAR = "year"; +const MONTH = "month"; +const DAY = "day"; +const HOUR = "hour"; +const MINUTE = "minute"; +const SECOND = "second"; +const MILLISECOND = "millisecond"; export default { - parse(date, date_separator = '-', time_separator = /[.:]/) { - if (date instanceof Date) { - return date; + parse_duration(duration) { + const regex = /([0-9])+(y|m|d|h|min|s|ms)/gm; + const matches = regex.exec(duration); + + if (matches !== null) { + if (matches[2] === "y") { + return { duration: parseInt(matches[1]), scale: `year` }; + } else if (matches[2] === "m") { + return { duration: parseInt(matches[1]), scale: `month` }; + } else if (matches[2] === "d") { + return { duration: parseInt(matches[1]), scale: `day` }; + } else if (matches[2] === "h") { + return { duration: parseInt(matches[1]), scale: `hour` }; + } else if (matches[2] === "min") { + return { duration: parseInt(matches[1]), scale: `minute` }; + } else if (matches[2] === "s") { + return { duration: parseInt(matches[1]), scale: `second` }; + } else if (matches[2] === "ms") { + return { duration: parseInt(matches[1]), scale: `millisecond` }; + } + } + }, + parse(date, date_separator = "-", time_separator = /[.:]/) { + if (date instanceof Date) { + return date; + } + if (typeof date === "string") { + let date_parts, time_parts; + const parts = date.split(" "); + + date_parts = parts[0] + .split(date_separator) + .map((val) => parseInt(val, 10)); + time_parts = parts[1] && parts[1].split(time_separator); + + // month is 0 indexed + date_parts[1] = date_parts[1] - 1; + + let vals = date_parts; + + if (time_parts && time_parts.length) { + if (time_parts.length == 4) { + time_parts[3] = "0." + time_parts[3]; + time_parts[3] = parseFloat(time_parts[3]) * 1000; } - if (typeof date === 'string') { - let date_parts, time_parts; - const parts = date.split(' '); + vals = vals.concat(time_parts); + } - date_parts = parts[0] - .split(date_separator) - .map((val) => parseInt(val, 10)); - time_parts = parts[1] && parts[1].split(time_separator); + return new Date(...vals); + } + }, - // month is 0 indexed - date_parts[1] = date_parts[1] - 1; + to_string(date, with_time = false) { + if (!(date instanceof Date)) { + throw new TypeError("Invalid argument type"); + } + const vals = this.get_date_values(date).map((val, i) => { + if (i === 1) { + // add 1 for month + val = val + 1; + } - let vals = date_parts; + if (i === 6) { + return padStart(val + "", 3, "0"); + } - if (time_parts && time_parts.length) { - if (time_parts.length == 4) { - time_parts[3] = '0.' + time_parts[3]; - time_parts[3] = parseFloat(time_parts[3]) * 1000; - } - vals = vals.concat(time_parts); - } + return padStart(val + "", 2, "0"); + }); + const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`; + const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`; - return new Date(...vals); + return date_string + (with_time ? " " + time_string : ""); + }, + + format(date, format_string = "YYYY-MM-DD HH:mm:ss.SSS", lang = "en") { + const dateTimeFormat = new Intl.DateTimeFormat(lang, { + month: "long", + }); + const month_name = dateTimeFormat.format(date); + const month_name_capitalized = + month_name.charAt(0).toUpperCase() + month_name.slice(1); + + const values = this.get_date_values(date).map((d) => padStart(d, 2, 0)); + const format_map = { + YYYY: values[0], + MM: padStart(+values[1] + 1, 2, 0), + DD: values[2], + HH: values[3], + mm: values[4], + ss: values[5], + SSS: values[6], + D: values[2], + MMMM: month_name_capitalized, + MMM: month_name_capitalized, + }; + + let str = format_string; + const formatted_values = []; + + Object.keys(format_map) + .sort((a, b) => b.length - a.length) // big string first + .forEach((key) => { + if (str.includes(key)) { + str = str.replace(key, `$${formatted_values.length}`); + formatted_values.push(format_map[key]); } - }, + }); - to_string(date, with_time = false) { - if (!(date instanceof Date)) { - throw new TypeError('Invalid argument type'); - } - const vals = this.get_date_values(date).map((val, i) => { - if (i === 1) { - // add 1 for month - val = val + 1; - } + formatted_values.forEach((value, i) => { + str = str.replace(`$${i}`, value); + }); - if (i === 6) { - return padStart(val + '', 3, '0'); - } + return str; + }, - return padStart(val + '', 2, '0'); - }); - const date_string = `${vals[0]}-${vals[1]}-${vals[2]}`; - const time_string = `${vals[3]}:${vals[4]}:${vals[5]}.${vals[6]}`; + diff(date_a, date_b, scale = DAY) { + let milliseconds, seconds, hours, minutes, days, months, years; - return date_string + (with_time ? ' ' + time_string : ''); - }, + milliseconds = date_a - date_b; + seconds = milliseconds / 1000; + minutes = seconds / 60; + hours = minutes / 60; + days = hours / 24; + months = days / 30; + years = months / 12; - format(date, format_string = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') { - const dateTimeFormat = new Intl.DateTimeFormat(lang, { - month: 'long' - }); - const month_name = dateTimeFormat.format(date); - const month_name_capitalized = - month_name.charAt(0).toUpperCase() + month_name.slice(1); + if (!scale.endsWith("s")) { + scale += "s"; + } - const values = this.get_date_values(date).map(d => padStart(d, 2, 0)); - const format_map = { - YYYY: values[0], - MM: padStart(+values[1] + 1, 2, 0), - DD: values[2], - HH: values[3], - mm: values[4], - ss: values[5], - SSS: values[6], - D: values[2], - MMMM: month_name_capitalized, - MMM: month_name_capitalized, - }; + return Math.floor( + { + milliseconds, + seconds, + minutes, + hours, + days, + months, + years, + }[scale], + ); + }, - let str = format_string; - const formatted_values = []; + today() { + const vals = this.get_date_values(new Date()).slice(0, 3); + return new Date(...vals); + }, - Object.keys(format_map) - .sort((a, b) => b.length - a.length) // big string first - .forEach((key) => { - if (str.includes(key)) { - str = str.replace(key, `$${formatted_values.length}`); - formatted_values.push(format_map[key]); - } - }); + now() { + return new Date(); + }, - formatted_values.forEach((value, i) => { - str = str.replace(`$${i}`, value); - }); + add(date, qty, scale) { + qty = parseInt(qty, 10); + const vals = [ + date.getFullYear() + (scale === YEAR ? qty : 0), + date.getMonth() + (scale === MONTH ? qty : 0), + date.getDate() + (scale === DAY ? qty : 0), + date.getHours() + (scale === HOUR ? qty : 0), + date.getMinutes() + (scale === MINUTE ? qty : 0), + date.getSeconds() + (scale === SECOND ? qty : 0), + date.getMilliseconds() + (scale === MILLISECOND ? qty : 0), + ]; + return new Date(...vals); + }, - return str; - }, + start_of(date, scale) { + const scores = { + [YEAR]: 6, + [MONTH]: 5, + [DAY]: 4, + [HOUR]: 3, + [MINUTE]: 2, + [SECOND]: 1, + [MILLISECOND]: 0, + }; - diff(date_a, date_b, scale = DAY) { - let milliseconds, seconds, hours, minutes, days, months, years; + function should_reset(_scale) { + const max_score = scores[scale]; + return scores[_scale] <= max_score; + } - milliseconds = date_a - date_b; - seconds = milliseconds / 1000; - minutes = seconds / 60; - hours = minutes / 60; - days = hours / 24; - months = days / 30; - years = months / 12; + const vals = [ + date.getFullYear(), + should_reset(YEAR) ? 0 : date.getMonth(), + should_reset(MONTH) ? 1 : date.getDate(), + should_reset(DAY) ? 0 : date.getHours(), + should_reset(HOUR) ? 0 : date.getMinutes(), + should_reset(MINUTE) ? 0 : date.getSeconds(), + should_reset(SECOND) ? 0 : date.getMilliseconds(), + ]; - if (!scale.endsWith('s')) { - scale += 's'; - } + return new Date(...vals); + }, - return Math.floor( - { - milliseconds, - seconds, - minutes, - hours, - days, - months, - years, - }[scale] - ); - }, + clone(date) { + return new Date(...this.get_date_values(date)); + }, - today() { - const vals = this.get_date_values(new Date()).slice(0, 3); - return new Date(...vals); - }, + get_date_values(date) { + return [ + date.getFullYear(), + date.getMonth(), + date.getDate(), + date.getHours(), + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds(), + ]; + }, - now() { - return new Date(); - }, + get_days_in_month(date) { + const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - add(date, qty, scale) { - qty = parseInt(qty, 10); - const vals = [ - date.getFullYear() + (scale === YEAR ? qty : 0), - date.getMonth() + (scale === MONTH ? qty : 0), - date.getDate() + (scale === DAY ? qty : 0), - date.getHours() + (scale === HOUR ? qty : 0), - date.getMinutes() + (scale === MINUTE ? qty : 0), - date.getSeconds() + (scale === SECOND ? qty : 0), - date.getMilliseconds() + (scale === MILLISECOND ? qty : 0), - ]; - return new Date(...vals); - }, + const month = date.getMonth(); - start_of(date, scale) { - const scores = { - [YEAR]: 6, - [MONTH]: 5, - [DAY]: 4, - [HOUR]: 3, - [MINUTE]: 2, - [SECOND]: 1, - [MILLISECOND]: 0, - }; + if (month !== 1) { + return no_of_days[month]; + } - function should_reset(_scale) { - const max_score = scores[scale]; - return scores[_scale] <= max_score; - } - - const vals = [ - date.getFullYear(), - should_reset(YEAR) ? 0 : date.getMonth(), - should_reset(MONTH) ? 1 : date.getDate(), - should_reset(DAY) ? 0 : date.getHours(), - should_reset(HOUR) ? 0 : date.getMinutes(), - should_reset(MINUTE) ? 0 : date.getSeconds(), - should_reset(SECOND) ? 0 : date.getMilliseconds(), - ]; - - return new Date(...vals); - }, - - clone(date) { - return new Date(...this.get_date_values(date)); - }, - - get_date_values(date) { - return [ - date.getFullYear(), - date.getMonth(), - date.getDate(), - date.getHours(), - date.getMinutes(), - date.getSeconds(), - date.getMilliseconds(), - ]; - }, - - get_days_in_month(date) { - const no_of_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; - - const month = date.getMonth(); - - if (month !== 1) { - return no_of_days[month]; - } - - // Feb - const year = date.getFullYear(); - if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { - return 29; - } - return 28; - }, + // Feb + const year = date.getFullYear(); + if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { + return 29; + } + return 28; + }, }; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart function padStart(str, targetLength, padString) { - str = str + ''; - targetLength = targetLength >> 0; - padString = String(typeof padString !== 'undefined' ? padString : ' '); - if (str.length > targetLength) { - return String(str); - } else { - targetLength = targetLength - str.length; - if (targetLength > padString.length) { - padString += padString.repeat(targetLength / padString.length); - } - return padString.slice(0, targetLength) + String(str); + str = str + ""; + targetLength = targetLength >> 0; + padString = String(typeof padString !== "undefined" ? padString : " "); + if (str.length > targetLength) { + return String(str); + } else { + targetLength = targetLength - str.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength / padString.length); } + return padString.slice(0, targetLength) + String(str); + } } diff --git a/src/gantt.scss b/src/gantt.scss index ebb6a90..8ed70aa 100644 --- a/src/gantt.scss +++ b/src/gantt.scss @@ -1,7 +1,7 @@ @import "./dark.scss"; $bar-color: #b8c2cc !default; -$bar-stroke: #8D99A6 !default; +$bar-stroke: #8d99a6 !default; $border-color: #e0e0e0 !default; $light-bg: #f5f5f5 !default; $light-border-color: #ebeff2 !default; @@ -14,178 +14,179 @@ $handle-color: #ddd !default; $light-blue: #c4c4e9 !default; .gantt { - user-select: none; - -webkit-user-select: none; - - .grid-background { - fill: none; - } - .grid-header { - fill: #ffffff; - stroke: $border-color; - stroke-width: 1.4; - } - .grid-row { - fill: #ffffff; - } - .grid-row:nth-child(even) { - fill: $light-bg; - } - .row-line { - stroke: $light-border-color; - } - .tick { - stroke: $border-color; - stroke-width: 0.2; - &.thick { - stroke-width: 0.4; - } - } - .today-highlight { - fill: $light-yellow; - opacity: 0.5; - } + user-select: none; + -webkit-user-select: none; - .week-highlight { - fill: $light-yellow; - opacity: 0.5; - } + .grid-background { + fill: none; + } + .grid-header { + fill: #ffffff; + stroke: $border-color; + stroke-width: 1.4; + } + .grid-row { + fill: #ffffff; + } + .grid-row:nth-child(even) { + fill: $light-bg; + } + .row-line { + stroke: $light-border-color; + } + .tick { + stroke: $border-color; + stroke-width: 0.2; + &.thick { + stroke-width: 0.4; + } + } + .today-highlight { + fill: $light-yellow; + opacity: 0.5; + } - .month-highlight { - fill: $light-yellow; - opacity: 0.5; - } + .week-highlight { + fill: $light-yellow; + opacity: 0.5; + } - .year-highlight { - fill: $light-yellow; - opacity: 0.5; - } + .month-highlight { + fill: $light-yellow; + opacity: 0.5; + } - .arrow { - fill: none; - stroke: $text-muted; - stroke-width: 1.4; - } + .year-highlight { + fill: $light-yellow; + opacity: 0.5; + } - .bar { - fill: $bar-color; - stroke: $bar-stroke; - stroke-width: 0; - transition: stroke-width .3s ease; - } - .bar-progress { - fill: $blue; - } - .bar-expected-progress { - fill: $light-blue; - } - .bar-invalid { - fill: transparent; - stroke: $bar-stroke; - stroke-width: 1; - stroke-dasharray: 5; + .arrow { + fill: none; + stroke: $text-muted; + stroke-width: 1.4; + } - &~.bar-label { - fill: $text-light; - } - } - .bar-label { - fill: #fff; - dominant-baseline: central; - text-anchor: middle; - font-size: 12px; - font-weight: lighter; + .bar { + fill: $bar-color; + stroke: $bar-stroke; + stroke-width: 0; + transition: stroke-width 0.3s ease; + } + .bar-progress { + fill: $blue; + } + .bar-expected-progress { + fill: $light-blue; + } + .bar-invalid { + fill: transparent; + stroke: $bar-stroke; + stroke-width: 1; + stroke-dasharray: 5; - &.big { - fill: $text-light; - text-anchor: start; - } - } + & ~ .bar-label { + fill: $text-light; + } + } + .bar-label { + fill: #fff; + dominant-baseline: central; + text-anchor: middle; + font-size: 12px; + font-weight: lighter; - .handle { - fill: $handle-color; - cursor: ew-resize; - opacity: 0; - visibility: hidden; - transition: opacity .3s ease; - } + &.big { + fill: $text-light; + text-anchor: start; + } + } - .bar-wrapper { - cursor: pointer; - outline: none; + .handle { + fill: $handle-color; + cursor: ew-resize; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease; + } - &:hover { - .bar { - fill: darken($bar-color, 5); - } + .bar-wrapper { + cursor: pointer; + outline: none; - .bar-progress { - fill: darken($blue, 5); - } + &:hover { + .bar { + fill: darken($bar-color, 5); + } - .handle { - visibility: visible; - opacity: 1; - } - } + .bar-progress { + fill: darken($blue, 5); + } - &.active { - .bar { - fill: darken($bar-color, 5); - } + .handle { + visibility: visible; + opacity: 1; + } + } - .bar-progress { - fill: darken($blue, 5); - } - } - } + &.active { + .bar { + fill: darken($bar-color, 5); + } - .lower-text, .upper-text { - font-size: 12px; - text-anchor: middle; - } - .upper-text { - fill: $text-light; - } - .lower-text { - fill: $text-color; - } + .bar-progress { + fill: darken($blue, 5); + } + } + } - .hide { - display: none; - } + .lower-text, + .upper-text { + font-size: 12px; + text-anchor: middle; + } + .upper-text { + fill: $text-light; + } + .lower-text { + fill: $text-color; + } + + .hide { + display: none; + } } .gantt-container { - position: relative; - overflow: auto; - font-size: 12px; + position: relative; + overflow: auto; + font-size: 12px; - .popup-wrapper { - position: absolute; - top: 0; - left: 0; - background: rgba(0, 0, 0, 0.8); - padding: 0; - color: #959da5; - border-radius: 3px; + .popup-wrapper { + position: absolute; + top: 0; + left: 0; + background: rgba(0, 0, 0, 0.8); + padding: 0; + color: #959da5; + border-radius: 3px; - .title { - border-bottom: 3px solid $blue; - padding: 10px; - } + .title { + border-bottom: 3px solid $blue; + padding: 10px; + } - .subtitle { - padding: 10px; - color: #dfe2e5; - } + .subtitle { + padding: 10px; + color: #dfe2e5; + } - .pointer { - position: absolute; - height: 5px; - margin: 0 0 0 -5px; - border: 5px solid transparent; - border-top-color: rgba(0, 0, 0, 0.8); - } - } -} \ No newline at end of file + .pointer { + position: absolute; + height: 5px; + margin: 0 0 0 -5px; + border: 5px solid transparent; + border-top-color: rgba(0, 0, 0, 0.8); + } + } +} diff --git a/src/index.js b/src/index.js index 5039c7c..dbff9e0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,977 +1,1028 @@ -import date_utils from './date_utils'; -import { $, createSVG } from './svg_utils'; -import Bar from './bar'; -import Arrow from './arrow'; -import Popup from './popup'; +import date_utils from "./date_utils"; +import { $, createSVG } from "./svg_utils"; +import Bar from "./bar"; +import Arrow from "./arrow"; +import Popup from "./popup"; -import './gantt.scss'; +import "./gantt.scss"; const VIEW_MODE = { - QUARTER_DAY: 'Quarter Day', - HALF_DAY: 'Half Day', - DAY: 'Day', - WEEK: 'Week', - MONTH: 'Month', - YEAR: 'Year', + HOUR: "Hour", + QUARTER_DAY: "Quarter Day", + HALF_DAY: "Half Day", + DAY: "Day", + WEEK: "Week", + MONTH: "Month", + YEAR: "Year", +}; + +const VIEW_MODE_PADDING = { + HOUR: ["7d", "7d"], + QUARTER_DAY: ["7d", "7d"], + HALF_DAY: ["7d", "7d"], + DAY: ["1m", "1m"], + WEEK: ["1m", "1m"], + MONTH: ["1m", "1m"], + YEAR: ["2y", "2y"], }; export default class Gantt { - constructor(wrapper, tasks, options) { - this.setup_wrapper(wrapper); - this.setup_options(options); - this.setup_tasks(tasks); - // initialize with default view mode - this.change_view_mode(); - this.bind_events(); + constructor(wrapper, tasks, options) { + this.setup_wrapper(wrapper); + this.setup_options(options); + this.setup_tasks(tasks); + // initialize with default view mode + this.change_view_mode(); + this.bind_events(); + } + + setup_wrapper(element) { + let svg_element, wrapper_element; + + // CSS Selector is passed + if (typeof element === "string") { + element = document.querySelector(element); } - setup_wrapper(element) { - let svg_element, wrapper_element; - - // CSS Selector is passed - if (typeof element === 'string') { - element = document.querySelector(element); - } - - // get the SVGElement - if (element instanceof HTMLElement) { - wrapper_element = element; - svg_element = element.querySelector('svg'); - } else if (element instanceof SVGElement) { - svg_element = element; - } else { - throw new TypeError( - 'Frappé Gantt only supports usage of a string CSS selector,' + - " HTML DOM element or SVG DOM element for the 'element' parameter" - ); - } - - // svg element - if (!svg_element) { - // create it - this.$svg = createSVG('svg', { - append_to: wrapper_element, - class: 'gantt', - }); - } else { - this.$svg = svg_element; - this.$svg.classList.add('gantt'); - } - - // wrapper element - this.$container = document.createElement('div'); - this.$container.classList.add('gantt-container'); - - const parent_element = this.$svg.parentElement; - parent_element.appendChild(this.$container); - this.$container.appendChild(this.$svg); - - // popup wrapper - this.popup_wrapper = document.createElement('div'); - this.popup_wrapper.classList.add('popup-wrapper'); - this.$container.appendChild(this.popup_wrapper); + // get the SVGElement + if (element instanceof HTMLElement) { + wrapper_element = element; + svg_element = element.querySelector("svg"); + } else if (element instanceof SVGElement) { + svg_element = element; + } else { + throw new TypeError( + "Frappé Gantt only supports usage of a string CSS selector," + + " HTML DOM element or SVG DOM element for the 'element' parameter", + ); } - setup_options(options) { - const default_options = { - header_height: 50, - column_width: 30, - step: 24, - view_modes: [...Object.values(VIEW_MODE)], - bar_height: 20, - bar_corner_radius: 3, - arrow_curve: 5, - padding: 18, - view_mode: 'Day', - date_format: 'YYYY-MM-DD', - popup_trigger: 'click', - custom_popup_html: null, - language: 'en', - }; - this.options = Object.assign({}, default_options, options); + // svg element + if (!svg_element) { + // create it + this.$svg = createSVG("svg", { + append_to: wrapper_element, + class: "gantt", + }); + } else { + this.$svg = svg_element; + this.$svg.classList.add("gantt"); } - setup_tasks(tasks) { - // prepare tasks - this.tasks = tasks.map((task, i) => { - // convert to Date objects - task._start = date_utils.parse(task.start); - task._end = date_utils.parse(task.end); + // wrapper element + this.$container = document.createElement("div"); + this.$container.classList.add("gantt-container"); - // make task invalid if duration too large - if (date_utils.diff(task._end, task._start, 'year') > 10) { - task.end = null; - } + const parent_element = this.$svg.parentElement; + parent_element.appendChild(this.$container); + this.$container.appendChild(this.$svg); - // cache index - task._index = i; + // popup wrapper + this.popup_wrapper = document.createElement("div"); + this.popup_wrapper.classList.add("popup-wrapper"); + this.$container.appendChild(this.popup_wrapper); + } - // invalid dates - if (!task.start && !task.end) { - const today = date_utils.today(); - task._start = today; - task._end = date_utils.add(today, 2, 'day'); - } + setup_options(options) { + const default_options = { + header_height: 50, + column_width: 30, + step: 24, + view_modes: [...Object.values(VIEW_MODE)], + bar_height: 20, + bar_corner_radius: 3, + arrow_curve: 5, + padding: 18, + view_mode: "Day", + date_format: "YYYY-MM-DD", + popup_trigger: "click", + custom_popup_html: null, + language: "en", + }; + this.options = Object.assign({}, default_options, options); + for (let [key, value] of Object.entries(options.view_mode_padding)) { + if (typeof value === "string") { + // Configure for single value given + options.view_mode_padding[key] = [value, value]; + } + } - if (!task.start && task.end) { - task._start = date_utils.add(task._end, -2, 'day'); - } + this.options.view_mode_padding = { + ...VIEW_MODE_PADDING, + ...options.view_mode_padding, + }; + } - if (task.start && !task.end) { - task._end = date_utils.add(task._start, 2, 'day'); - } + setup_tasks(tasks) { + // prepare tasks + this.tasks = tasks.map((task, i) => { + // convert to Date objects + task._start = date_utils.parse(task.start); + if (task.end === undefined && task.duration !== undefined) { + task.end = task._start; + let durations = task.duration.split(" "); - // if hours is not set, assume the last day is full day - // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 - const task_end_values = date_utils.get_date_values(task._end); - if (task_end_values.slice(3).every((d) => d === 0)) { - task._end = date_utils.add(task._end, 24, 'hour'); - } - - // invalid flag - if (!task.start || !task.end) { - task.invalid = true; - } - - // dependencies - if (typeof task.dependencies === 'string' || !task.dependencies) { - let deps = []; - if (task.dependencies) { - deps = task.dependencies - .split(',') - .map((d) => d.trim()) - .filter((d) => d); - } - task.dependencies = deps; - } - - // uids - if (!task.id) { - task.id = generate_id(task); - } - - return task; + durations.forEach((tmpDuration) => { + let { duration, scale } = date_utils.parse_duration(tmpDuration); + task.end = date_utils.add(task.end, duration, scale); }); + } + task._end = date_utils.parse(task.end); - this.setup_dependencies(); - } + // make task invalid if duration too large + if (date_utils.diff(task._end, task._start, "year") > 10) { + task.end = null; + } - setup_dependencies() { - this.dependency_map = {}; - for (let t of this.tasks) { - for (let d of t.dependencies) { - this.dependency_map[d] = this.dependency_map[d] || []; - this.dependency_map[d].push(t.id); - } + // cache index + task._index = i; + + // invalid dates + if (!task.start && !task.end) { + const today = date_utils.today(); + task._start = today; + task._end = date_utils.add(today, 2, "day"); + } + + if (!task.start && task.end) { + task._start = date_utils.add(task._end, -2, "day"); + } + + if (task.start && !task.end) { + task._end = date_utils.add(task._start, 2, "day"); + } + + // if hours is not set, assume the last day is full day + // e.g: 2018-09-09 becomes 2018-09-09 23:59:59 + const task_end_values = date_utils.get_date_values(task._end); + if (task_end_values.slice(3).every((d) => d === 0)) { + task._end = date_utils.add(task._end, 24, "hour"); + } + + // invalid flag + if (!task.start || !task.end) { + task.invalid = true; + } + + // dependencies + if (typeof task.dependencies === "string" || !task.dependencies) { + let deps = []; + if (task.dependencies) { + deps = task.dependencies + .split(",") + .map((d) => d.trim()) + .filter((d) => d); } + task.dependencies = deps; + } + + // uids + if (!task.id) { + task.id = generate_id(task); + } + + return task; + }); + + this.setup_dependencies(); + } + + setup_dependencies() { + this.dependency_map = {}; + for (let t of this.tasks) { + for (let d of t.dependencies) { + this.dependency_map[d] = this.dependency_map[d] || []; + this.dependency_map[d].push(t.id); + } + } + } + + refresh(tasks) { + this.setup_tasks(tasks); + this.change_view_mode(); + } + + change_view_mode(mode = this.options.view_mode) { + this.update_view_scale(mode); + this.setup_dates(); + this.render(); + // fire viewmode_change event + this.trigger_event("view_change", [mode]); + } + + update_view_scale(view_mode) { + this.options.view_mode = view_mode; + if (view_mode === VIEW_MODE.HOUR) { + this.options.step = 24 / 24; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.DAY) { + this.options.step = 24; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.HALF_DAY) { + this.options.step = 24 / 2; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.QUARTER_DAY) { + this.options.step = 24 / 4; + this.options.column_width = 38; + } else if (view_mode === VIEW_MODE.WEEK) { + this.options.step = 24 * 7; + this.options.column_width = 140; + } else if (view_mode === VIEW_MODE.MONTH) { + this.options.step = 24 * 30; + this.options.column_width = 120; + } else if (view_mode === VIEW_MODE.YEAR) { + this.options.step = 24 * 365; + this.options.column_width = 120; + } + } + + setup_dates() { + this.setup_gantt_dates(); + this.setup_date_values(); + } + + setup_gantt_dates() { + this.gantt_start = this.gantt_end = null; + + for (let task of this.tasks) { + // set global start and end date + if (!this.gantt_start || task._start < this.gantt_start) { + this.gantt_start = task._start; + } + if (!this.gantt_end || task._end > this.gantt_end) { + this.gantt_end = task._end; + } + } + let gantt_start, gantt_end; + if (!this.gantt_start) gantt_start = new Date(); + else gantt_start = date_utils.start_of(this.gantt_start, "day"); + if (!this.gantt_end) gantt_end = new Date(); + else gantt_end = date_utils.start_of(this.gantt_end, "day"); + + // add date padding on both sides + let viewKey; + for (let [key, value] of Object.entries(VIEW_MODE)) { + if (value === this.options.view_mode) { + viewKey = key; + } + } + const [padding_start, padding_end] = this.options.view_mode_padding[ + viewKey + ].map(date_utils.parse_duration); + + this.gantt_start = date_utils.add( + gantt_start, + -padding_start.duration, + padding_start.scale, + ); + + let format_string; + if (this.view_is(VIEW_MODE.YEAR)) { + format_string = "YYYY" + } else if (this.view_is(VIEW_MODE.MONTH)) { + format_string = "YYYY-MM" + } else if (this.view_is(VIEW_MODE.DAY)) { + format_string = "YYYY-MM-DD" + } else { + format_string = "YYYY-MM-DD HH" } - refresh(tasks) { - this.setup_tasks(tasks); - this.change_view_mode(); - } + this.gantt_start = new Date( + date_utils.format( + date_utils.add(gantt_start, -padding_end.duration, padding_end.scale), + format_string + ) + ); + this.gantt_start.setHours(0, 0, 0, 0) - change_view_mode(mode = this.options.view_mode) { - this.update_view_scale(mode); - this.setup_dates(); - this.render(); - // fire viewmode_change event - this.trigger_event('view_change', [mode]); - } + this.gantt_end = date_utils.add( + gantt_end, + padding_end.duration, + padding_end.scale, + ); + } - update_view_scale(view_mode) { - this.options.view_mode = view_mode; + setup_date_values() { + this.dates = []; + let cur_date = null; - if (view_mode === VIEW_MODE.DAY) { - this.options.step = 24; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.HALF_DAY) { - this.options.step = 24 / 2; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.QUARTER_DAY) { - this.options.step = 24 / 4; - this.options.column_width = 38; - } else if (view_mode === VIEW_MODE.WEEK) { - this.options.step = 24 * 7; - this.options.column_width = 140; - } else if (view_mode === VIEW_MODE.MONTH) { - this.options.step = 24 * 30; - this.options.column_width = 120; - } else if (view_mode === VIEW_MODE.YEAR) { - this.options.step = 24 * 365; - this.options.column_width = 120; - } - } - - setup_dates() { - this.setup_gantt_dates(); - this.setup_date_values(); - } - - setup_gantt_dates() { - this.gantt_start = this.gantt_end = null; - - for (let task of this.tasks) { - // set global start and end date - if (!this.gantt_start || task._start < this.gantt_start) { - this.gantt_start = task._start; - } - if (!this.gantt_end || task._end > this.gantt_end) { - this.gantt_end = task._end; - } - } - - this.gantt_start = date_utils.start_of(this.gantt_start, 'day'); - this.gantt_end = date_utils.start_of(this.gantt_end, 'day'); - - // add date padding on both sides - if (this.view_is([VIEW_MODE.QUARTER_DAY, VIEW_MODE.HALF_DAY])) { - this.gantt_start = date_utils.add(this.gantt_start, -7, 'day'); - this.gantt_end = date_utils.add(this.gantt_end, 7, 'day'); + while (cur_date === null || cur_date < this.gantt_end) { + if (!cur_date) { + cur_date = date_utils.clone(this.gantt_start); + } else { + if (this.view_is(VIEW_MODE.YEAR)) { + cur_date = date_utils.add(cur_date, 1, "year"); } else if (this.view_is(VIEW_MODE.MONTH)) { - this.gantt_start = date_utils.start_of(this.gantt_start, 'year'); - this.gantt_end = date_utils.add(this.gantt_end, 1, 'year'); - } else if (this.view_is(VIEW_MODE.YEAR)) { - this.gantt_start = date_utils.add(this.gantt_start, -2, 'year'); - this.gantt_end = date_utils.add(this.gantt_end, 2, 'year'); + cur_date = date_utils.add(cur_date, 1, "month"); } else { - this.gantt_start = date_utils.add(this.gantt_start, -1, 'month'); - this.gantt_end = date_utils.add(this.gantt_end, 1, 'month'); + cur_date = date_utils.add(cur_date, this.options.step, "hour"); } + } + this.dates.push(cur_date); + } + } + + bind_events() { + this.bind_grid_click(); + this.bind_bar_events(); + } + + render() { + this.clear(); + this.setup_layers(); + this.make_grid(); + this.make_dates(); + this.make_bars(); + this.make_arrows(); + this.map_arrows_on_bars(); + this.set_width(); + this.set_scroll_position(); + } + + setup_layers() { + this.layers = {}; + const layers = ["grid", "date", "arrow", "progress", "bar", "details"]; + // make group layers + for (let layer of layers) { + this.layers[layer] = createSVG("g", { + class: layer, + append_to: this.$svg, + }); + } + } + + make_grid() { + this.make_grid_background(); + this.make_grid_rows(); + this.make_grid_header(); + this.make_grid_ticks(); + this.make_grid_highlights(); + } + + make_grid_background() { + const grid_width = this.dates.length * this.options.column_width; + const grid_height = + this.options.header_height + + this.options.padding + + (this.options.bar_height + this.options.padding) * this.tasks.length; + + createSVG("rect", { + x: 0, + y: 0, + width: grid_width, + height: grid_height, + class: "grid-background", + append_to: this.layers.grid, + }); + + $.attr(this.$svg, { + height: grid_height + this.options.padding + 100, + width: "100%", + }); + } + + make_grid_rows() { + const rows_layer = createSVG("g", { append_to: this.layers.grid }); + const lines_layer = createSVG("g", { append_to: this.layers.grid }); + + const row_width = this.dates.length * this.options.column_width; + const row_height = this.options.bar_height + this.options.padding; + + let row_y = this.options.header_height + this.options.padding / 2; + + for (let task of this.tasks) { + createSVG("rect", { + x: 0, + y: row_y, + width: row_width, + height: row_height, + class: "grid-row", + append_to: rows_layer, + }); + + createSVG("line", { + x1: 0, + y1: row_y + row_height, + x2: row_width, + y2: row_y + row_height, + class: "row-line", + append_to: lines_layer, + }); + + row_y += this.options.bar_height + this.options.padding; + } + } + + make_grid_header() { + const header_width = this.dates.length * this.options.column_width; + const header_height = this.options.header_height + 10; + createSVG("rect", { + x: 0, + y: 0, + width: header_width, + height: header_height, + class: "grid-header", + append_to: this.layers.grid, + }); + } + + make_grid_ticks() { + let tick_x = 0; + let tick_y = this.options.header_height + this.options.padding / 2; + let tick_height = + (this.options.bar_height + this.options.padding) * this.tasks.length; + + for (let date of this.dates) { + let tick_class = "tick"; + // thick tick for monday + if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) { + tick_class += " thick"; + } + // thick tick for first week + if ( + this.view_is(VIEW_MODE.WEEK) && + date.getDate() >= 1 && + date.getDate() < 8 + ) { + tick_class += " thick"; + } + // thick ticks for quarters + if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) { + tick_class += " thick"; + } + + createSVG("path", { + d: `M ${tick_x} ${tick_y} v ${tick_height}`, + class: tick_class, + append_to: this.layers.grid, + }); + + if (this.view_is(VIEW_MODE.MONTH)) { + tick_x += + (date_utils.get_days_in_month(date) * this.options.column_width) / 30; + } else { + tick_x += this.options.column_width; + } + } + } + + //compute the horizontal x distance + computeGridHighlightDimensions(view_mode) { + let xDist = 0; + + if (this.view_is(VIEW_MODE.DAY)) { + return ( + (date_utils.diff(date_utils.today(), this.gantt_start, "hour") / + this.options.step) * + this.options.column_width + ); } - setup_date_values() { - this.dates = []; - let cur_date = null; - - while (cur_date === null || cur_date < this.gantt_end) { - if (!cur_date) { - cur_date = date_utils.clone(this.gantt_start); - } else { - if (this.view_is(VIEW_MODE.YEAR)) { - cur_date = date_utils.add(cur_date, 1, 'year'); - } else if (this.view_is(VIEW_MODE.MONTH)) { - cur_date = date_utils.add(cur_date, 1, 'month'); - } else { - cur_date = date_utils.add( - cur_date, - this.options.step, - 'hour' - ); - } - } - this.dates.push(cur_date); - } + for (let date of this.dates) { + const todayDate = new Date(); + const startDate = new Date(date); + const endDate = new Date(date); + switch (view_mode) { + case VIEW_MODE.WEEK: + endDate.setDate(date.getDate() + 7); + break; + case VIEW_MODE.MONTH: + endDate.setMonth(date.getMonth() + 1); + break; + case VIEW_MODE.YEAR: + endDate.setFullYear(date.getFullYear() + 1); + break; + } + if (todayDate >= startDate && todayDate <= endDate) { + break; + } else { + xDist += this.options.column_width; + } } + return xDist; + } - bind_events() { - this.bind_grid_click(); - this.bind_bar_events(); + make_grid_highlights() { + // highlight today's | week's | month's | year's + if ( + this.view_is(VIEW_MODE.DAY) || + this.view_is(VIEW_MODE.WEEK) || + this.view_is(VIEW_MODE.MONTH) || + this.view_is(VIEW_MODE.YEAR) + ) { + const x = this.computeGridHighlightDimensions(this.options.view_mode); + const y = 0; + const width = this.options.column_width; + const height = + (this.options.bar_height + this.options.padding) * this.tasks.length + + this.options.header_height + + this.options.padding / 2; + + let className = ""; + switch (this.options.view_mode) { + case VIEW_MODE.DAY: + className = "today-highlight"; + break; + case VIEW_MODE.WEEK: + className = "week-highlight"; + break; + case VIEW_MODE.MONTH: + className = "month-highlight"; + break; + case VIEW_MODE.YEAR: + className = "year-highlight"; + break; + } + createSVG("rect", { + x, + y, + width, + height, + class: className, + append_to: this.layers.grid, + }); } + } - render() { - this.clear(); - this.setup_layers(); - this.make_grid(); - this.make_dates(); - this.make_bars(); - this.make_arrows(); - this.map_arrows_on_bars(); - this.set_width(); - this.set_scroll_position(); - } + make_dates() { + for (let date of this.get_dates_to_draw()) { + createSVG("text", { + x: date.lower_x, + y: date.lower_y, + innerHTML: date.lower_text, + class: "lower-text", + append_to: this.layers.date, + }); - setup_layers() { - this.layers = {}; - const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details']; - // make group layers - for (let layer of layers) { - this.layers[layer] = createSVG('g', { - class: layer, - append_to: this.$svg, - }); - } - } - - make_grid() { - this.make_grid_background(); - this.make_grid_rows(); - this.make_grid_header(); - this.make_grid_ticks(); - this.make_grid_highlights(); - } - - make_grid_background() { - const grid_width = this.dates.length * this.options.column_width; - const grid_height = - this.options.header_height + - this.options.padding + - (this.options.bar_height + this.options.padding) * - this.tasks.length; - - createSVG('rect', { - x: 0, - y: 0, - width: grid_width, - height: grid_height, - class: 'grid-background', - append_to: this.layers.grid, + if (date.upper_text) { + const $upper_text = createSVG("text", { + x: date.upper_x, + y: date.upper_y, + innerHTML: date.upper_text, + class: "upper-text", + append_to: this.layers.date, }); - $.attr(this.$svg, { - height: grid_height + this.options.padding + 100, - width: '100%', - }); - } - - make_grid_rows() { - const rows_layer = createSVG('g', { append_to: this.layers.grid }); - const lines_layer = createSVG('g', { append_to: this.layers.grid }); - - const row_width = this.dates.length * this.options.column_width; - const row_height = this.options.bar_height + this.options.padding; - - let row_y = this.options.header_height + this.options.padding / 2; - - for (let task of this.tasks) { - createSVG('rect', { - x: 0, - y: row_y, - width: row_width, - height: row_height, - class: 'grid-row', - append_to: rows_layer, - }); - - createSVG('line', { - x1: 0, - y1: row_y + row_height, - x2: row_width, - y2: row_y + row_height, - class: 'row-line', - append_to: lines_layer, - }); - - row_y += this.options.bar_height + this.options.padding; + // remove out-of-bound dates + if ($upper_text.getBBox().x2 > this.layers.grid.getBBox().width) { + $upper_text.remove(); } + } } + } - make_grid_header() { - const header_width = this.dates.length * this.options.column_width; - const header_height = this.options.header_height + 10; - createSVG('rect', { - x: 0, - y: 0, - width: header_width, - height: header_height, - class: 'grid-header', - append_to: this.layers.grid, - }); + get_dates_to_draw() { + let last_date = null; + const dates = this.dates.map((date, i) => { + const d = this.get_date_info(date, last_date, i); + last_date = date; + return d; + }); + return dates; + } + + get_date_info(date, last_date, i) { + if (!last_date) { + last_date = date_utils.add(date, 1, "day"); } + const date_text = { + Hour_lower: date_utils.format(date, "HH", this.options.language), + "Quarter Day_lower": date_utils.format(date, "HH", this.options.language), + "Half Day_lower": date_utils.format(date, "HH", this.options.language), + Day_lower: + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D", this.options.language) + : "", + Week_lower: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "D MMM", this.options.language) + : date_utils.format(date, "D", this.options.language), + Month_lower: date_utils.format(date, "MMMM", this.options.language), + Year_lower: date_utils.format(date, "YYYY", this.options.language), + Hour_upper: + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D MMMM", this.options.language) + : "", + "Quarter Day_upper": + date.getDate() !== last_date.getDate() + ? date_utils.format(date, "D MMM", this.options.language) + : "", + "Half Day_upper": + date.getDate() !== last_date.getDate() + ? date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "D MMM", this.options.language) + : date_utils.format(date, "D", this.options.language) + : "", + Day_upper: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "MMMM", this.options.language) + : "", + Week_upper: + date.getMonth() !== last_date.getMonth() + ? date_utils.format(date, "MMMM", this.options.language) + : "", + Month_upper: + date.getFullYear() !== last_date.getFullYear() + ? date_utils.format(date, "YYYY", this.options.language) + : "", + Year_upper: + date.getFullYear() !== last_date.getFullYear() + ? date_utils.format(date, "YYYY", this.options.language) + : "", + }; - make_grid_ticks() { - let tick_x = 0; - let tick_y = this.options.header_height + this.options.padding / 2; - let tick_height = - (this.options.bar_height + this.options.padding) * - this.tasks.length; + const base_pos = { + x: i * this.options.column_width, + lower_y: this.options.header_height, + upper_y: this.options.header_height - 25, + }; - for (let date of this.dates) { - let tick_class = 'tick'; - // thick tick for monday - if (this.view_is(VIEW_MODE.DAY) && date.getDate() === 1) { - tick_class += ' thick'; - } - // thick tick for first week - if ( - this.view_is(VIEW_MODE.WEEK) && - date.getDate() >= 1 && - date.getDate() < 8 - ) { - tick_class += ' thick'; - } - // thick ticks for quarters - if (this.view_is(VIEW_MODE.MONTH) && date.getMonth() % 3 === 0) { - tick_class += ' thick'; - } + const x_pos = { + Hour_lower: this.options.column_width / 2, + Hour_upper: this.options.column_width * 12, + "Quarter Day_lower": this.options.column_width / 2, + "Quarter Day_upper": this.options.column_width * 2, + "Half Day_lower": this.options.column_width / 2, + "Half Day_upper": this.options.column_width, + Day_lower: this.options.column_width / 2, + Day_upper: (this.options.column_width * 30) / 2, + Week_lower: 0, + Week_upper: (this.options.column_width * 4) / 2, + Month_lower: this.options.column_width / 2, + Month_upper: (this.options.column_width * 12) / 2, + Year_lower: this.options.column_width / 2, + Year_upper: (this.options.column_width * 30) / 2, + }; - createSVG('path', { - d: `M ${tick_x} ${tick_y} v ${tick_height}`, - class: tick_class, - append_to: this.layers.grid, - }); + return { + upper_text: date_text[`${this.options.view_mode}_upper`], + lower_text: date_text[`${this.options.view_mode}_lower`], + upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`], + upper_y: base_pos.upper_y, + lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`], + lower_y: base_pos.lower_y, + }; + } - if (this.view_is(VIEW_MODE.MONTH)) { - tick_x += - (date_utils.get_days_in_month(date) * - this.options.column_width) / - 30; - } else { - tick_x += this.options.column_width; - } - } + make_bars() { + this.bars = this.tasks.map((task) => { + const bar = new Bar(this, task); + this.layers.bar.appendChild(bar.group); + return bar; + }); + } + + make_arrows() { + this.arrows = []; + for (let task of this.tasks) { + let arrows = []; + arrows = task.dependencies + .map((task_id) => { + const dependency = this.get_task(task_id); + if (!dependency) return; + const arrow = new Arrow( + this, + this.bars[dependency._index], // from_task + this.bars[task._index], // to_task + ); + this.layers.arrow.appendChild(arrow.element); + return arrow; + }) + .filter(Boolean); // filter falsy values + this.arrows = this.arrows.concat(arrows); } + } - //compute the horizontal x distance - computeGridHighlightDimensions(view_mode) { - let xDist = 0; - - if (this.view_is(VIEW_MODE.DAY)) { - return (date_utils.diff(date_utils.today(), this.gantt_start, 'hour') / - this.options.step) * - this.options.column_width; - } - - for (let date of this.dates) { - const todayDate = new Date(); - const startDate = new Date(date); - const endDate = new Date(date); - switch (view_mode) { - case VIEW_MODE.WEEK: - endDate.setDate(date.getDate() + 7); - break; - case VIEW_MODE.MONTH: - endDate.setMonth(date.getMonth() + 1); - break; - case VIEW_MODE.YEAR: - endDate.setFullYear(date.getFullYear() + 1); - break; - } - if (todayDate >= startDate && todayDate <= endDate) { - break; - } else { - xDist += this.options.column_width; - } - } - return xDist; - } - - make_grid_highlights() { - // highlight today's | week's | month's | year's - if (this.view_is(VIEW_MODE.DAY) || this.view_is(VIEW_MODE.WEEK) || this.view_is(VIEW_MODE.MONTH) || this.view_is(VIEW_MODE.YEAR)) { - - const x = this.computeGridHighlightDimensions(this.options.view_mode); - const y = 0; - const width = this.options.column_width; - const height = - (this.options.bar_height + this.options.padding) * - this.tasks.length + - this.options.header_height + - this.options.padding / 2; - - let className = ''; - switch (this.options.view_mode) { - case VIEW_MODE.DAY: - className = 'today-highlight' - break; - case VIEW_MODE.WEEK: - className = 'week-highlight' - break; - case VIEW_MODE.MONTH: - className = 'month-highlight' - break; - case VIEW_MODE.YEAR: - className = 'year-highlight' - break; - } - createSVG('rect', { - x, - y, - width, - height, - class: className, - append_to: this.layers.grid, - }); - } - } - - make_dates() { - for (let date of this.get_dates_to_draw()) { - createSVG('text', { - x: date.lower_x, - y: date.lower_y, - innerHTML: date.lower_text, - class: 'lower-text', - append_to: this.layers.date, - }); - - if (date.upper_text) { - const $upper_text = createSVG('text', { - x: date.upper_x, - y: date.upper_y, - innerHTML: date.upper_text, - class: 'upper-text', - append_to: this.layers.date, - }); - - // remove out-of-bound dates - if ( - $upper_text.getBBox().x2 > this.layers.grid.getBBox().width - ) { - $upper_text.remove(); - } - } - } - } - - get_dates_to_draw() { - let last_date = null; - const dates = this.dates.map((date, i) => { - const d = this.get_date_info(date, last_date, i); - last_date = date; - return d; - }); - return dates; - } - - get_date_info(date, last_date, i) { - if (!last_date) { - last_date = date_utils.add(date, 1, 'day'); - } - const date_text = { - 'Quarter Day_lower': date_utils.format( - date, - 'HH', - this.options.language - ), - 'Half Day_lower': date_utils.format( - date, - 'HH', - this.options.language - ), - Day_lower: - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D', this.options.language) - : '', - Week_lower: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'D MMM', this.options.language) - : date_utils.format(date, 'D', this.options.language), - Month_lower: date_utils.format(date, 'MMMM', this.options.language), - Year_lower: date_utils.format(date, 'YYYY', this.options.language), - 'Quarter Day_upper': - date.getDate() !== last_date.getDate() - ? date_utils.format(date, 'D MMM', this.options.language) - : '', - 'Half Day_upper': - date.getDate() !== last_date.getDate() - ? date.getMonth() !== last_date.getMonth() - ? date_utils.format( - date, - 'D MMM', - this.options.language - ) - : date_utils.format(date, 'D', this.options.language) - : '', - Day_upper: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Week_upper: - date.getMonth() !== last_date.getMonth() - ? date_utils.format(date, 'MMMM', this.options.language) - : '', - Month_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - Year_upper: - date.getFullYear() !== last_date.getFullYear() - ? date_utils.format(date, 'YYYY', this.options.language) - : '', - }; - - const base_pos = { - x: i * this.options.column_width, - lower_y: this.options.header_height, - upper_y: this.options.header_height - 25, - }; - - const x_pos = { - 'Quarter Day_lower': this.options.column_width / 2, - 'Quarter Day_upper': this.options.column_width * 2, - 'Half Day_lower': this.options.column_width / 2, - 'Half Day_upper': this.options.column_width, - Day_lower: this.options.column_width / 2, - Day_upper: (this.options.column_width * 30) / 2, - Week_lower: 0, - Week_upper: (this.options.column_width * 4) / 2, - Month_lower: this.options.column_width / 2, - Month_upper: (this.options.column_width * 12) / 2, - Year_lower: this.options.column_width / 2, - Year_upper: (this.options.column_width * 30) / 2, - }; - - return { - upper_text: date_text[`${this.options.view_mode}_upper`], - lower_text: date_text[`${this.options.view_mode}_lower`], - upper_x: base_pos.x + x_pos[`${this.options.view_mode}_upper`], - upper_y: base_pos.upper_y, - lower_x: base_pos.x + x_pos[`${this.options.view_mode}_lower`], - lower_y: base_pos.lower_y, - }; - } - - make_bars() { - this.bars = this.tasks.map((task) => { - const bar = new Bar(this, task); - this.layers.bar.appendChild(bar.group); - return bar; - }); - } - - make_arrows() { - this.arrows = []; - for (let task of this.tasks) { - let arrows = []; - arrows = task.dependencies - .map((task_id) => { - const dependency = this.get_task(task_id); - if (!dependency) return; - const arrow = new Arrow( - this, - this.bars[dependency._index], // from_task - this.bars[task._index] // to_task - ); - this.layers.arrow.appendChild(arrow.element); - return arrow; - }) - .filter(Boolean); // filter falsy values - this.arrows = this.arrows.concat(arrows); - } - } - - map_arrows_on_bars() { - for (let bar of this.bars) { - bar.arrows = this.arrows.filter((arrow) => { - return ( - arrow.from_task.task.id === bar.task.id || - arrow.to_task.task.id === bar.task.id - ); - }); - } - } - - set_width() { - const cur_width = this.$svg.getBoundingClientRect().width; - const actual_width = this.$svg - .querySelector('.grid .grid-row') - .getAttribute('width'); - if (cur_width < actual_width) { - this.$svg.setAttribute('width', actual_width); - } - } - - set_scroll_position() { - const parent_element = this.$svg.parentElement; - if (!parent_element) return; - - const hours_before_first_task = date_utils.diff( - this.get_oldest_starting_date(), - this.gantt_start, - 'hour' + map_arrows_on_bars() { + for (let bar of this.bars) { + bar.arrows = this.arrows.filter((arrow) => { + return ( + arrow.from_task.task.id === bar.task.id || + arrow.to_task.task.id === bar.task.id ); + }); + } + } - const scroll_pos = - (hours_before_first_task / this.options.step) * - this.options.column_width - - this.options.column_width; + set_width() { + const cur_width = this.$svg.getBoundingClientRect().width; + const actual_width = this.$svg.querySelector('.grid .grid-row') ? this.$svg + .querySelector('.grid .grid-row') + .getAttribute('width') : 0; + if (cur_width < actual_width) { + this.$svg.setAttribute("width", actual_width); + } + } - parent_element.scrollLeft = scroll_pos; + set_scroll_position() { + const parent_element = this.$svg.parentElement; + if (!parent_element) return; + + const hours_before_first_task = date_utils.diff( + this.get_oldest_starting_date(), + this.gantt_start, + "hour", + ); + + const scroll_pos = + (hours_before_first_task / this.options.step) * + this.options.column_width - + this.options.column_width; + + parent_element.scrollLeft = scroll_pos; + } + + bind_grid_click() { + $.on( + this.$svg, + this.options.popup_trigger, + ".grid-row, .grid-header", + () => { + this.unselect_all(); + this.hide_popup(); + }, + ); + } + + bind_bar_events() { + let is_dragging = false; + let x_on_start = 0; + let y_on_start = 0; + let is_resizing_left = false; + let is_resizing_right = false; + let parent_bar_id = null; + let bars = []; // instanceof Bar + this.bar_being_dragged = null; + + function action_in_progress() { + return is_dragging || is_resizing_left || is_resizing_right; } - bind_grid_click() { - $.on( - this.$svg, - this.options.popup_trigger, - '.grid-row, .grid-header', - () => { - this.unselect_all(); - this.hide_popup(); - } - ); - } + $.on(this.$svg, "mousedown", ".bar-wrapper, .handle", (e, element) => { + const bar_wrapper = $.closest(".bar-wrapper", element); - bind_bar_events() { - let is_dragging = false; - let x_on_start = 0; - let y_on_start = 0; - let is_resizing_left = false; - let is_resizing_right = false; - let parent_bar_id = null; - let bars = []; // instanceof Bar - this.bar_being_dragged = null; + if (element.classList.contains("left")) { + is_resizing_left = true; + } else if (element.classList.contains("right")) { + is_resizing_right = true; + } else if (element.classList.contains("bar-wrapper")) { + is_dragging = true; + } - function action_in_progress() { - return is_dragging || is_resizing_left || is_resizing_right; - } + bar_wrapper.classList.add("active"); - $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => { - const bar_wrapper = $.closest('.bar-wrapper', element); + x_on_start = e.offsetX; + y_on_start = e.offsetY; - if (element.classList.contains('left')) { - is_resizing_left = true; - } else if (element.classList.contains('right')) { - is_resizing_right = true; - } else if (element.classList.contains('bar-wrapper')) { - is_dragging = true; - } + parent_bar_id = bar_wrapper.getAttribute("data-id"); + const ids = [ + parent_bar_id, + ...this.get_all_dependent_tasks(parent_bar_id), + ]; + bars = ids.map((id) => this.get_bar(id)); - bar_wrapper.classList.add('active'); + this.bar_being_dragged = parent_bar_id; - x_on_start = e.offsetX; - y_on_start = e.offsetY; + bars.forEach((bar) => { + const $bar = bar.$bar; + $bar.ox = $bar.getX(); + $bar.oy = $bar.getY(); + $bar.owidth = $bar.getWidth(); + $bar.finaldx = 0; + }); + }); - parent_bar_id = bar_wrapper.getAttribute('data-id'); - const ids = [ - parent_bar_id, - ...this.get_all_dependent_tasks(parent_bar_id), - ]; - bars = ids.map((id) => this.get_bar(id)); + $.on(this.$svg, "mousemove", (e) => { + if (!action_in_progress()) return; + const dx = e.offsetX - x_on_start; + const dy = e.offsetY - y_on_start; - this.bar_being_dragged = parent_bar_id; - - bars.forEach((bar) => { - const $bar = bar.$bar; - $bar.ox = $bar.getX(); - $bar.oy = $bar.getY(); - $bar.owidth = $bar.getWidth(); - $bar.finaldx = 0; + bars.forEach((bar) => { + const $bar = bar.$bar; + $bar.finaldx = this.get_snap_position(dx); + this.hide_popup(); + if (is_resizing_left) { + if (parent_bar_id === bar.task.id) { + bar.update_bar_position({ + x: $bar.ox + $bar.finaldx, + width: $bar.owidth - $bar.finaldx, }); - }); - - $.on(this.$svg, 'mousemove', (e) => { - if (!action_in_progress()) return; - const dx = e.offsetX - x_on_start; - const dy = e.offsetY - y_on_start; - - bars.forEach((bar) => { - const $bar = bar.$bar; - $bar.finaldx = this.get_snap_position(dx); - this.hide_popup(); - if (is_resizing_left) { - if (parent_bar_id === bar.task.id) { - bar.update_bar_position({ - x: $bar.ox + $bar.finaldx, - width: $bar.owidth - $bar.finaldx, - }); - } else { - bar.update_bar_position({ - x: $bar.ox + $bar.finaldx, - }); - } - } else if (is_resizing_right) { - if (parent_bar_id === bar.task.id) { - bar.update_bar_position({ - width: $bar.owidth + $bar.finaldx, - }); - } - } else if (is_dragging) { - bar.update_bar_position({ x: $bar.ox + $bar.finaldx }); - } + } else { + bar.update_bar_position({ + x: $bar.ox + $bar.finaldx, }); - }); - - document.addEventListener('mouseup', (e) => { - if (is_dragging || is_resizing_left || is_resizing_right) { - bars.forEach((bar) => bar.group.classList.remove('active')); - } - - is_dragging = false; - is_resizing_left = false; - is_resizing_right = false; - }); - - $.on(this.$svg, 'mouseup', (e) => { - this.bar_being_dragged = null; - bars.forEach((bar) => { - const $bar = bar.$bar; - if (!$bar.finaldx) return; - bar.date_changed(); - bar.set_action_completed(); + } + } else if (is_resizing_right) { + if (parent_bar_id === bar.task.id) { + bar.update_bar_position({ + width: $bar.owidth + $bar.finaldx, }); - }); - - this.bind_bar_progress(); - } - - bind_bar_progress() { - let x_on_start = 0; - let y_on_start = 0; - let is_resizing = null; - let bar = null; - let $bar_progress = null; - let $bar = null; - - $.on(this.$svg, 'mousedown', '.handle.progress', (e, handle) => { - is_resizing = true; - x_on_start = e.offsetX; - y_on_start = e.offsetY; - - const $bar_wrapper = $.closest('.bar-wrapper', handle); - const id = $bar_wrapper.getAttribute('data-id'); - bar = this.get_bar(id); - - $bar_progress = bar.$bar_progress; - $bar = bar.$bar; - - $bar_progress.finaldx = 0; - $bar_progress.owidth = $bar_progress.getWidth(); - $bar_progress.min_dx = -$bar_progress.getWidth(); - $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth(); - }); - - $.on(this.$svg, 'mousemove', (e) => { - if (!is_resizing) return; - let dx = e.offsetX - x_on_start; - let dy = e.offsetY - y_on_start; - - if (dx > $bar_progress.max_dx) { - dx = $bar_progress.max_dx; - } - if (dx < $bar_progress.min_dx) { - dx = $bar_progress.min_dx; - } - - const $handle = bar.$handle_progress; - $.attr($bar_progress, 'width', $bar_progress.owidth + dx); - $.attr($handle, 'points', bar.get_progress_polygon_points()); - $bar_progress.finaldx = dx; - }); - - $.on(this.$svg, 'mouseup', () => { - is_resizing = false; - if (!($bar_progress && $bar_progress.finaldx)) return; - bar.progress_changed(); - bar.set_action_completed(); - }); - } - - get_all_dependent_tasks(task_id) { - let out = []; - let to_process = [task_id]; - while (to_process.length) { - const deps = to_process.reduce((acc, curr) => { - acc = acc.concat(this.dependency_map[curr]); - return acc; - }, []); - - out = out.concat(deps); - to_process = deps.filter((d) => !to_process.includes(d)); + } + } else if (is_dragging) { + bar.update_bar_position({ x: $bar.ox + $bar.finaldx }); } + }); + }); - return out.filter(Boolean); + document.addEventListener("mouseup", (e) => { + if (is_dragging || is_resizing_left || is_resizing_right) { + bars.forEach((bar) => bar.group.classList.remove("active")); + } + + is_dragging = false; + is_resizing_left = false; + is_resizing_right = false; + }); + + $.on(this.$svg, "mouseup", (e) => { + this.bar_being_dragged = null; + bars.forEach((bar) => { + const $bar = bar.$bar; + if (!$bar.finaldx) return; + bar.date_changed(); + bar.set_action_completed(); + }); + }); + + this.bind_bar_progress(); + } + + bind_bar_progress() { + let x_on_start = 0; + let y_on_start = 0; + let is_resizing = null; + let bar = null; + let $bar_progress = null; + let $bar = null; + + $.on(this.$svg, "mousedown", ".handle.progress", (e, handle) => { + is_resizing = true; + x_on_start = e.offsetX; + y_on_start = e.offsetY; + + const $bar_wrapper = $.closest(".bar-wrapper", handle); + const id = $bar_wrapper.getAttribute("data-id"); + bar = this.get_bar(id); + + $bar_progress = bar.$bar_progress; + $bar = bar.$bar; + + $bar_progress.finaldx = 0; + $bar_progress.owidth = $bar_progress.getWidth(); + $bar_progress.min_dx = -$bar_progress.getWidth(); + $bar_progress.max_dx = $bar.getWidth() - $bar_progress.getWidth(); + }); + + $.on(this.$svg, "mousemove", (e) => { + if (!is_resizing) return; + let dx = e.offsetX - x_on_start; + let dy = e.offsetY - y_on_start; + + if (dx > $bar_progress.max_dx) { + dx = $bar_progress.max_dx; + } + if (dx < $bar_progress.min_dx) { + dx = $bar_progress.min_dx; + } + + const $handle = bar.$handle_progress; + $.attr($bar_progress, "width", $bar_progress.owidth + dx); + $.attr($handle, "points", bar.get_progress_polygon_points()); + $bar_progress.finaldx = dx; + }); + + $.on(this.$svg, "mouseup", () => { + is_resizing = false; + if (!($bar_progress && $bar_progress.finaldx)) return; + bar.progress_changed(); + bar.set_action_completed(); + }); + } + + get_all_dependent_tasks(task_id) { + let out = []; + let to_process = [task_id]; + while (to_process.length) { + const deps = to_process.reduce((acc, curr) => { + acc = acc.concat(this.dependency_map[curr]); + return acc; + }, []); + + out = out.concat(deps); + to_process = deps.filter((d) => !to_process.includes(d)); } - get_snap_position(dx) { - let odx = dx, - rem, - position; + return out.filter(Boolean); + } - if (this.view_is(VIEW_MODE.WEEK)) { - rem = dx % (this.options.column_width / 7); - position = - odx - - rem + - (rem < this.options.column_width / 14 - ? 0 - : this.options.column_width / 7); - } else if (this.view_is(VIEW_MODE.MONTH)) { - rem = dx % (this.options.column_width / 30); - position = - odx - - rem + - (rem < this.options.column_width / 60 - ? 0 - : this.options.column_width / 30); - } else { - rem = dx % this.options.column_width; - position = - odx - - rem + - (rem < this.options.column_width / 2 - ? 0 - : this.options.column_width); - } - return position; + get_snap_position(dx) { + let odx = dx, + rem, + position; + + if (this.view_is(VIEW_MODE.WEEK)) { + rem = dx % (this.options.column_width / 7); + position = + odx - + rem + + (rem < this.options.column_width / 14 + ? 0 + : this.options.column_width / 7); + } else if (this.view_is(VIEW_MODE.MONTH)) { + rem = dx % (this.options.column_width / 30); + position = + odx - + rem + + (rem < this.options.column_width / 60 + ? 0 + : this.options.column_width / 30); + } else { + rem = dx % this.options.column_width; + position = + odx - + rem + + (rem < this.options.column_width / 2 ? 0 : this.options.column_width); + } + return position; + } + + unselect_all() { + [...this.$svg.querySelectorAll(".bar-wrapper")].forEach((el) => { + el.classList.remove("active"); + }); + } + + view_is(modes) { + if (typeof modes === "string") { + return this.options.view_mode === modes; } - unselect_all() { - [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => { - el.classList.remove('active'); - }); + if (Array.isArray(modes)) { + return modes.some((mode) => this.options.view_mode === mode); } - view_is(modes) { - if (typeof modes === 'string') { - return this.options.view_mode === modes; - } + return false; + } - if (Array.isArray(modes)) { - return modes.some((mode) => this.options.view_mode === mode); - } + get_task(id) { + return this.tasks.find((task) => { + return task.id === id; + }); + } - return false; + get_bar(id) { + return this.bars.find((bar) => { + return bar.task.id === id; + }); + } + + show_popup(options) { + if (!this.popup) { + this.popup = new Popup( + this.popup_wrapper, + this.options.custom_popup_html, + ); } + this.popup.show(options); + } - get_task(id) { - return this.tasks.find((task) => { - return task.id === id; - }); - } + hide_popup() { + this.popup && this.popup.hide(); + } - get_bar(id) { - return this.bars.find((bar) => { - return bar.task.id === id; - }); + trigger_event(event, args) { + if (this.options["on_" + event]) { + this.options["on_" + event].apply(null, args); } + } - show_popup(options) { - if (!this.popup) { - this.popup = new Popup( - this.popup_wrapper, - this.options.custom_popup_html - ); - } - this.popup.show(options); - } + /** + * Gets the oldest starting date from the list of tasks + * + * @returns Date + * @memberof Gantt + */ + get_oldest_starting_date() { + if (!this.tasks.length) return new Date() + return this.tasks + .map((task) => task._start) + .reduce((prev_date, cur_date) => + cur_date <= prev_date ? cur_date : prev_date, + ); + } - hide_popup() { - this.popup && this.popup.hide(); - } - - trigger_event(event, args) { - if (this.options['on_' + event]) { - this.options['on_' + event].apply(null, args); - } - } - - /** - * Gets the oldest starting date from the list of tasks - * - * @returns Date - * @memberof Gantt - */ - get_oldest_starting_date() { - return this.tasks - .map((task) => task._start) - .reduce((prev_date, cur_date) => - cur_date <= prev_date ? cur_date : prev_date - ); - } - - /** - * Clear all elements from the parent svg element - * - * @memberof Gantt - */ - clear() { - this.$svg.innerHTML = ''; - } + /** + * Clear all elements from the parent svg element + * + * @memberof Gantt + */ + clear() { + this.$svg.innerHTML = ""; + } } Gantt.VIEW_MODE = VIEW_MODE; function generate_id(task) { - return task.name + '_' + Math.random().toString(36).slice(2, 12); + return task.name + "_" + Math.random().toString(36).slice(2, 12); } diff --git a/src/popup.js b/src/popup.js index e9e9314..33eb90f 100644 --- a/src/popup.js +++ b/src/popup.js @@ -1,69 +1,69 @@ export default class Popup { - constructor(parent, custom_html) { - this.parent = parent; - this.custom_html = custom_html; - this.make(); - } + constructor(parent, custom_html) { + this.parent = parent; + this.custom_html = custom_html; + this.make(); + } - make() { - this.parent.innerHTML = ` + make() { + this.parent.innerHTML = `
`; - this.hide(); + this.hide(); - this.title = this.parent.querySelector('.title'); - this.subtitle = this.parent.querySelector('.subtitle'); - this.pointer = this.parent.querySelector('.pointer'); + this.title = this.parent.querySelector(".title"); + this.subtitle = this.parent.querySelector(".subtitle"); + this.pointer = this.parent.querySelector(".pointer"); + } + + show(options) { + if (!options.target_element) { + throw new Error("target_element is required to show popup"); + } + if (!options.position) { + options.position = "left"; + } + const target_element = options.target_element; + + if (this.custom_html) { + let html = this.custom_html(options.task); + html += '
'; + this.parent.innerHTML = html; + this.pointer = this.parent.querySelector(".pointer"); + } else { + // set data + this.title.innerHTML = options.title; + this.subtitle.innerHTML = options.subtitle; + this.parent.style.width = this.parent.clientWidth + "px"; } - show(options) { - if (!options.target_element) { - throw new Error('target_element is required to show popup'); - } - if (!options.position) { - options.position = 'left'; - } - const target_element = options.target_element; - - if (this.custom_html) { - let html = this.custom_html(options.task); - html += '
'; - this.parent.innerHTML = html; - this.pointer = this.parent.querySelector('.pointer'); - } else { - // set data - this.title.innerHTML = options.title; - this.subtitle.innerHTML = options.subtitle; - this.parent.style.width = this.parent.clientWidth + 'px'; - } - - // set position - let position_meta; - if (target_element instanceof HTMLElement) { - position_meta = target_element.getBoundingClientRect(); - } else if (target_element instanceof SVGElement) { - position_meta = options.target_element.getBBox(); - } - - if (options.position === 'left') { - this.parent.style.left = - position_meta.x + (position_meta.width + 10) + 'px'; - this.parent.style.top = position_meta.y + 'px'; - - this.pointer.style.transform = 'rotateZ(90deg)'; - this.pointer.style.left = '-7px'; - this.pointer.style.top = '2px'; - } - - // show - this.parent.style.opacity = 1; + // set position + let position_meta; + if (target_element instanceof HTMLElement) { + position_meta = target_element.getBoundingClientRect(); + } else if (target_element instanceof SVGElement) { + position_meta = options.target_element.getBBox(); } - hide() { - this.parent.style.opacity = 0; - this.parent.style.left = 0; + if (options.position === "left") { + this.parent.style.left = + position_meta.x + (position_meta.width + 10) + "px"; + this.parent.style.top = position_meta.y + "px"; + + this.pointer.style.transform = "rotateZ(90deg)"; + this.pointer.style.left = "-7px"; + this.pointer.style.top = "2px"; } + + // show + this.parent.style.opacity = 1; + } + + hide() { + this.parent.style.opacity = 0; + this.parent.style.left = 0; + } } diff --git a/src/svg_utils.js b/src/svg_utils.js index f58c319..cff6029 100644 --- a/src/svg_utils.js +++ b/src/svg_utils.js @@ -1,133 +1,133 @@ export function $(expr, con) { - return typeof expr === 'string' - ? (con || document).querySelector(expr) - : expr || null; + return typeof expr === "string" + ? (con || document).querySelector(expr) + : expr || null; } export function createSVG(tag, attrs) { - const elem = document.createElementNS('http://www.w3.org/2000/svg', tag); - for (let attr in attrs) { - if (attr === 'append_to') { - const parent = attrs.append_to; - parent.appendChild(elem); - } else if (attr === 'innerHTML') { - elem.innerHTML = attrs.innerHTML; - } else { - elem.setAttribute(attr, attrs[attr]); - } + const elem = document.createElementNS("http://www.w3.org/2000/svg", tag); + for (let attr in attrs) { + if (attr === "append_to") { + const parent = attrs.append_to; + parent.appendChild(elem); + } else if (attr === "innerHTML") { + elem.innerHTML = attrs.innerHTML; + } else { + elem.setAttribute(attr, attrs[attr]); } - return elem; + } + return elem; } export function animateSVG(svgElement, attr, from, to) { - const animatedSvgElement = getAnimationElement(svgElement, attr, from, to); + const animatedSvgElement = getAnimationElement(svgElement, attr, from, to); - if (animatedSvgElement === svgElement) { - // triggered 2nd time programmatically - // trigger artificial click event - const event = document.createEvent('HTMLEvents'); - event.initEvent('click', true, true); - event.eventName = 'click'; - animatedSvgElement.dispatchEvent(event); - } + if (animatedSvgElement === svgElement) { + // triggered 2nd time programmatically + // trigger artificial click event + const event = document.createEvent("HTMLEvents"); + event.initEvent("click", true, true); + event.eventName = "click"; + animatedSvgElement.dispatchEvent(event); + } } function getAnimationElement( - svgElement, - attr, + svgElement, + attr, + from, + to, + dur = "0.4s", + begin = "0.1s", +) { + const animEl = svgElement.querySelector("animate"); + if (animEl) { + $.attr(animEl, { + attributeName: attr, + from, + to, + dur, + begin: "click + " + begin, // artificial click + }); + return svgElement; + } + + const animateElement = createSVG("animate", { + attributeName: attr, from, to, - dur = '0.4s', - begin = '0.1s' -) { - const animEl = svgElement.querySelector('animate'); - if (animEl) { - $.attr(animEl, { - attributeName: attr, - from, - to, - dur, - begin: 'click + ' + begin, // artificial click - }); - return svgElement; - } + dur, + begin, + calcMode: "spline", + values: from + ";" + to, + keyTimes: "0; 1", + keySplines: cubic_bezier("ease-out"), + }); + svgElement.appendChild(animateElement); - const animateElement = createSVG('animate', { - attributeName: attr, - from, - to, - dur, - begin, - calcMode: 'spline', - values: from + ';' + to, - keyTimes: '0; 1', - keySplines: cubic_bezier('ease-out'), - }); - svgElement.appendChild(animateElement); - - return svgElement; + return svgElement; } function cubic_bezier(name) { - return { - ease: '.25 .1 .25 1', - linear: '0 0 1 1', - 'ease-in': '.42 0 1 1', - 'ease-out': '0 0 .58 1', - 'ease-in-out': '.42 0 .58 1', - }[name]; + return { + ease: ".25 .1 .25 1", + linear: "0 0 1 1", + "ease-in": ".42 0 1 1", + "ease-out": "0 0 .58 1", + "ease-in-out": ".42 0 .58 1", + }[name]; } $.on = (element, event, selector, callback) => { - if (!callback) { - callback = selector; - $.bind(element, event, callback); - } else { - $.delegate(element, event, selector, callback); - } + if (!callback) { + callback = selector; + $.bind(element, event, callback); + } else { + $.delegate(element, event, selector, callback); + } }; $.off = (element, event, handler) => { - element.removeEventListener(event, handler); + element.removeEventListener(event, handler); }; $.bind = (element, event, callback) => { - event.split(/\s+/).forEach(function (event) { - element.addEventListener(event, callback); - }); + event.split(/\s+/).forEach(function (event) { + element.addEventListener(event, callback); + }); }; $.delegate = (element, event, selector, callback) => { - element.addEventListener(event, function (e) { - const delegatedTarget = e.target.closest(selector); - if (delegatedTarget) { - e.delegatedTarget = delegatedTarget; - callback.call(this, e, delegatedTarget); - } - }); + element.addEventListener(event, function (e) { + const delegatedTarget = e.target.closest(selector); + if (delegatedTarget) { + e.delegatedTarget = delegatedTarget; + callback.call(this, e, delegatedTarget); + } + }); }; $.closest = (selector, element) => { - if (!element) return null; + if (!element) return null; - if (element.matches(selector)) { - return element; - } + if (element.matches(selector)) { + return element; + } - return $.closest(selector, element.parentNode); + return $.closest(selector, element.parentNode); }; $.attr = (element, attr, value) => { - if (!value && typeof attr === 'string') { - return element.getAttribute(attr); - } + if (!value && typeof attr === "string") { + return element.getAttribute(attr); + } - if (typeof attr === 'object') { - for (let key in attr) { - $.attr(element, key, attr[key]); - } - return; + if (typeof attr === "object") { + for (let key in attr) { + $.attr(element, key, attr[key]); } + return; + } - element.setAttribute(attr, value); + element.setAttribute(attr, value); }; diff --git a/tests/date_utils.test.js b/tests/date_utils.test.js index 93033bf..9f4875d 100644 --- a/tests/date_utils.test.js +++ b/tests/date_utils.test.js @@ -1,124 +1,124 @@ -import date_utils from '../src/date_utils'; +import date_utils from "../src/date_utils"; -test('Parse: parses string date', () => { - const date = date_utils.parse('2017-09-09'); +test("Parse: parses string date", () => { + const date = date_utils.parse("2017-09-09"); - expect(date.getDate()).toBe(9); - expect(date.getMonth()).toBe(8); - expect(date.getFullYear()).toBe(2017); + expect(date.getDate()).toBe(9); + expect(date.getMonth()).toBe(8); + expect(date.getFullYear()).toBe(2017); }); -test('Parse: parses string datetime', () => { - const date = date_utils.parse('2017-08-27 16:08:34'); +test("Parse: parses string datetime", () => { + const date = date_utils.parse("2017-08-27 16:08:34"); - expect(date.getFullYear()).toBe(2017); - expect(date.getMonth()).toBe(7); - expect(date.getDate()).toBe(27); - expect(date.getHours()).toBe(16); - expect(date.getMinutes()).toBe(8); - expect(date.getSeconds()).toBe(34); + expect(date.getFullYear()).toBe(2017); + expect(date.getMonth()).toBe(7); + expect(date.getDate()).toBe(27); + expect(date.getHours()).toBe(16); + expect(date.getMinutes()).toBe(8); + expect(date.getSeconds()).toBe(34); }); -test('Parse: parses string datetime', () => { - const date = date_utils.parse('2016-02-29 16:08:34.3'); +test("Parse: parses string datetime", () => { + const date = date_utils.parse("2016-02-29 16:08:34.3"); - expect(date.getFullYear()).toBe(2016); - expect(date.getMonth()).toBe(1); - expect(date.getDate()).toBe(29); - expect(date.getHours()).toBe(16); - expect(date.getMinutes()).toBe(8); - expect(date.getSeconds()).toBe(34); - expect(date.getMilliseconds()).toBe(300); + expect(date.getFullYear()).toBe(2016); + expect(date.getMonth()).toBe(1); + expect(date.getDate()).toBe(29); + expect(date.getHours()).toBe(16); + expect(date.getMinutes()).toBe(8); + expect(date.getSeconds()).toBe(34); + expect(date.getMilliseconds()).toBe(300); }); -test('Parse: parses string datetime', () => { - const date = date_utils.parse('2015-07-01 00:00:59.200'); +test("Parse: parses string datetime", () => { + const date = date_utils.parse("2015-07-01 00:00:59.200"); - expect(date.getFullYear()).toBe(2015); - expect(date.getMonth()).toBe(6); - expect(date.getDate()).toBe(1); - expect(date.getHours()).toBe(0); - expect(date.getMinutes()).toBe(0); - expect(date.getSeconds()).toBe(59); - expect(date.getMilliseconds()).toBe(200); + expect(date.getFullYear()).toBe(2015); + expect(date.getMonth()).toBe(6); + expect(date.getDate()).toBe(1); + expect(date.getHours()).toBe(0); + expect(date.getMinutes()).toBe(0); + expect(date.getSeconds()).toBe(59); + expect(date.getMilliseconds()).toBe(200); }); -test('Format: converts date object to string', () => { - const date = new Date('2017-09-18'); - expect(date_utils.to_string(date)).toBe('2017-09-18'); +test("Format: converts date object to string", () => { + const date = new Date("2017-09-18"); + expect(date_utils.to_string(date)).toBe("2017-09-18"); }); -test('Format: converts date object to string', () => { - const date = new Date('2016-02-29 16:08:34.3'); - expect(date_utils.to_string(date, true)).toBe('2016-02-29 16:08:34.300'); +test("Format: converts date object to string", () => { + const date = new Date("2016-02-29 16:08:34.3"); + expect(date_utils.to_string(date, true)).toBe("2016-02-29 16:08:34.300"); }); -test('Format: converts date object to string', () => { - const date = new Date('2016-02-29 16:08:34.3'); - expect(date_utils.to_string(date, true)).toBe('2016-02-29 16:08:34.300'); +test("Format: converts date object to string", () => { + const date = new Date("2016-02-29 16:08:34.3"); + expect(date_utils.to_string(date, true)).toBe("2016-02-29 16:08:34.300"); }); -test('Parse: returns Date Object as is', () => { - const d = new Date(); - const date = date_utils.parse(d); +test("Parse: returns Date Object as is", () => { + const d = new Date(); + const date = date_utils.parse(d); - expect(d).toBe(date); + expect(d).toBe(date); }); -test('Diff: returns diff between 2 date objects', () => { - const a = date_utils.parse('2017-09-08'); - const b = date_utils.parse('2017-06-07'); +test("Diff: returns diff between 2 date objects", () => { + const a = date_utils.parse("2017-09-08"); + const b = date_utils.parse("2017-06-07"); - expect(date_utils.diff(a, b, 'day')).toBe(93); - expect(date_utils.diff(a, b, 'month')).toBe(3); - expect(date_utils.diff(a, b, 'year')).toBe(0); + expect(date_utils.diff(a, b, "day")).toBe(93); + expect(date_utils.diff(a, b, "month")).toBe(3); + expect(date_utils.diff(a, b, "year")).toBe(0); }); -test('StartOf', () => { - const date = date_utils.parse('2017-08-12 15:07:34.012'); +test("StartOf", () => { + const date = date_utils.parse("2017-08-12 15:07:34.012"); - const start_of_millisecond = date_utils.start_of(date, 'millisecond'); - expect(date_utils.to_string(start_of_millisecond, true)).toBe( - '2017-08-12 15:07:34.012' - ); + const start_of_millisecond = date_utils.start_of(date, "millisecond"); + expect(date_utils.to_string(start_of_millisecond, true)).toBe( + "2017-08-12 15:07:34.012", + ); - const start_of_second = date_utils.start_of(date, 'second'); - expect(date_utils.to_string(start_of_second, true)).toBe( - '2017-08-12 15:07:34.000' - ); + const start_of_second = date_utils.start_of(date, "second"); + expect(date_utils.to_string(start_of_second, true)).toBe( + "2017-08-12 15:07:34.000", + ); - const start_of_minute = date_utils.start_of(date, 'minute'); - expect(date_utils.to_string(start_of_minute, true)).toBe( - '2017-08-12 15:07:00.000' - ); + const start_of_minute = date_utils.start_of(date, "minute"); + expect(date_utils.to_string(start_of_minute, true)).toBe( + "2017-08-12 15:07:00.000", + ); - const start_of_hour = date_utils.start_of(date, 'hour'); - expect(date_utils.to_string(start_of_hour, true)).toBe( - '2017-08-12 15:00:00.000' - ); + const start_of_hour = date_utils.start_of(date, "hour"); + expect(date_utils.to_string(start_of_hour, true)).toBe( + "2017-08-12 15:00:00.000", + ); - const start_of_day = date_utils.start_of(date, 'day'); - expect(date_utils.to_string(start_of_day, true)).toBe( - '2017-08-12 00:00:00.000' - ); + const start_of_day = date_utils.start_of(date, "day"); + expect(date_utils.to_string(start_of_day, true)).toBe( + "2017-08-12 00:00:00.000", + ); - const start_of_month = date_utils.start_of(date, 'month'); - expect(date_utils.to_string(start_of_month, true)).toBe( - '2017-08-01 00:00:00.000' - ); + const start_of_month = date_utils.start_of(date, "month"); + expect(date_utils.to_string(start_of_month, true)).toBe( + "2017-08-01 00:00:00.000", + ); - const start_of_year = date_utils.start_of(date, 'year'); - expect(date_utils.to_string(start_of_year, true)).toBe( - '2017-01-01 00:00:00.000' - ); + const start_of_year = date_utils.start_of(date, "year"); + expect(date_utils.to_string(start_of_year, true)).toBe( + "2017-01-01 00:00:00.000", + ); }); -test('format', () => { - const date = date_utils.parse('2017-08-12 15:07:23'); - expect(date_utils.format(date, 'YYYY-MM-DD')).toBe('2017-08-12'); +test("format", () => { + const date = date_utils.parse("2017-08-12 15:07:23"); + expect(date_utils.format(date, "YYYY-MM-DD")).toBe("2017-08-12"); }); -test('format', () => { - const date = date_utils.parse('2016-02-29 16:08:34.3'); - expect(date_utils.format(date)).toBe('2016-02-29 16:08:34.300'); +test("format", () => { + const date = date_utils.parse("2016-02-29 16:08:34.3"); + expect(date_utils.format(date)).toBe("2016-02-29 16:08:34.300"); }); diff --git a/yarn.lock b/yarn.lock index 7fba4cc..22541d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2706,10 +2706,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" - integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== +prettier@3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-format@^22.1.0: version "22.1.0"