Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@energiency/gantt

Package Overview
Dependencies
Maintainers
2
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@energiency/gantt - npm Package Compare versions

Comparing version 1.0.0 to 1.0.1

2

dist/frappe-gantt.min.js

@@ -1,2 +0,2 @@

var Gantt=function(){"use strict";const t="year",e="month",s="day",i="hour",o="minute",a="second",n="millisecond",r={January:"Jan",February:"Feb",March:"Mar",April:"Apr",May:"May",June:"Jun",July:"Jul",August:"Aug",September:"Sep",October:"Oct",November:"Nov",December:"Dec"};var h={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 a=t.split(" ");i=a[0].split(e).map((t=>parseInt(t,10))),o=a[1]&&a[1].split(s),i[1]=i[1]?i[1]-1:0;let n=i;return o&&o.length&&(4===o.length&&(o[3]="0."+o[3],o[3]=1e3*parseFloat(o[3])),n=n.concat(o)),new Date(...n)}},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),d(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),a=this.get_date_values(t).map((t=>d(t,2,0))),n={YYYY:a[0],MM:d(+a[1]+1,2,0),DD:a[2],HH:a[3],mm:a[4],ss:a[5],SSS:a[6],D:a[2],MMMM:o,MMM:r[o]};let h=e;const p=[];return Object.keys(n).sort(((t,e)=>e.length-t.length)).forEach((t=>{h.includes(t)&&(h=h.replaceAll(t,`$${p.length}`),p.push(n[t]))})),p.forEach(((t,e)=>{h=h.replaceAll(`$${e}`,t)})),h},diff(t,e,i=s){let o,a,n,r,h,d,p;return o=t-e,a=o/1e3,r=a/60,n=r/60,h=n/24,d=h/30,p=d/12,i.endsWith("s")||(i+="s"),Math.floor({milliseconds:o,seconds:a,minutes:r,hours:n,days:h,months:d,years:p}[i])},today(){const t=this.get_date_values(new Date).slice(0,3);return new Date(...t)},now:()=>new Date,add(r,h,d){h=parseInt(h,10);const p=[r.getFullYear()+(d===t?h:0),r.getMonth()+(d===e?h:0),r.getDate()+(d===s?h:0),r.getHours()+(d===i?h:0),r.getMinutes()+(d===o?h:0),r.getSeconds()+(d===a?h:0),r.getMilliseconds()+(d===n?h:0)];return new Date(...p)},start_of(r,h){const d={[t]:6,[e]:5,[s]:4,[i]:3,[o]:2,[a]:1,[n]:0};function p(t){return d[t]<=d[h]}const l=[r.getFullYear(),p(t)?0:r.getMonth(),p(e)?1:r.getDate(),p(s)?0:r.getHours(),p(i)?0:r.getMinutes(),p(o)?0:r.getSeconds(),p(a)?0:r.getMilliseconds()];return new Date(...l)},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 d(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 l(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:"clipPath"===t?s.setAttribute("clip-path","url(#"+e[t]+")"):s.setAttribute(t,e[t]);return s}function _(t,e,s,i){const o=function(t,e,s,i,o="0.4s",a="0.1s"){const n=t.querySelector("animate");if(n)return p.attr(n,{attributeName:e,from:s,to:i,dur:o,begin:"click + "+a}),t;const r=l("animate",{attributeName:e,from:s,to:i,dur:o,begin:a,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 u{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.image_size=this.height-5,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=l("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:"")+(this.task.important?" important":""),"data-id":this.task.id}),this.bar_group=l("g",{class:"bar-group",append_to:this.group}),this.handle_group=l("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.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail()}draw_bar(){this.$bar=l("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=l("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(){if(this.invalid)return;this.$bar_progress=l("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});const t=h.diff(this.task._start,this.gantt.gantt_start,"hour")/this.gantt.options.step*this.gantt.options.column_width;let e=document.createElement("div");e.id=`${this.task.id}-highlight`,e.classList.add("date-highlight"),e.style.height=.8*this.height+"px",e.style.width=this.width+"px",e.style.top=this.gantt.options.header_height-25+"px",e.style.left=t+"px",this.$date_highlight=e,this.gantt.$lower_header.prepend(e),_(this.$bar_progress,"width",0,this.progress_width)}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),l("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame((()=>this.update_label_position()))}draw_thumbnail(){let t,e;t=l("defs",{append_to:this.bar_group}),l("rect",{id:"rect_"+this.task.id,x:this.x+10,y:this.y+2,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:t}),e=l("clipPath",{id:"clip_"+this.task.id,append_to:t}),l("use",{href:"#rect_"+this.task.id,append_to:e}),l("image",{x:this.x+10,y:this.y+2,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;l("rect",{x:t.getX()+t.getWidth()+8-4,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}),l("rect",{x:t.getX()-8-4,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=l("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()/2,t.getEndX(),t.getY()+t.getHeight()/2-7.5,t.getEndX()+5,t.getY()+t.getHeight()/2,t.getEndX(),t.getY()+t.getHeight()/2+7.5,t.getEndX()-5,t.getY()+t.getHeight()/2]}bind(){this.invalid||this.setup_click_event()}setup_click_event(){let t,e=this.task.id;p.on(this.group,"mouseover",(t=>{this.gantt.trigger_event("hover",[this.task,t.screenX,t.screenY,t])})),p.on(this.group,"mouseenter",(s=>t=setTimeout((()=>{this.show_popup(s.offsetX),document.querySelector(`#${e}-highlight`).style.display="block"}),200))),p.on(this.group,"mouseleave",(()=>{clearTimeout(t),this.gantt.popup?.hide?.(),document.querySelector(`#${e}-highlight`).style.display="none"})),p.on(this.group,this.gantt.options.popup_trigger,(()=>{this.gantt.trigger_event("click",[this.task])})),p.on(this.group,"dblclick",(t=>{this.action_completed||this.gantt.trigger_event("double_click",[this.task])}))}show_popup(t){if(this.gantt.bar_being_dragged)return;const e=`${h.format(this.task._start,"MMM D",this.gantt.options.language)} - ${h.format(h.add(this.task._end,-1,"second"),"MMM D",this.gantt.options.language)}<br/>Progress: ${this.task.progress}`;this.gantt.show_popup({x:t,target_element:this.$bar,title:this.task.name,subtitle:e,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),this.$date_highlight.style.left=t+"px"}e&&(this.update_attr(s,"width",e),this.$date_highlight.style.width=e+"px"),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()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const s=document.querySelector(".gantt-container"),i=this.group.querySelector(".bar-label"),o=this.group.querySelector(".bar-img")||"",a=this.bar_group.querySelector(".img_mask")||"";let n=this.$bar.getX()+this.$bar.getWidth(),r=i.getX()+t,h=o&&o.getX()+t||0,d=o&&o.getBBox().width+7||7,p=r+i.getBBox().width+7,l=e+s.clientWidth/2;i.classList.contains("big")||(p<n&&t>0&&p<l||r-d>this.$bar.getX()&&t<0&&p>l)&&(i.setAttribute("x",r),o&&(o.setAttribute("x",h),a.setAttribute("x",h)))}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,h.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=h.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:h.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=h.diff(h.today(),this.task._start,"hour")/this.gantt.options.step,this.expected_progress=100*(this.expected_progress<this.duration?this.expected_progress:this.duration)/this.duration}compute_x(){const{step:t,column_width:e}=this.gantt.options,s=this.task._start,i=this.gantt.gantt_start;let o=h.diff(s,i,"hour")/t*e;if(this.gantt.view_is("Month")){o=h.diff(s,i,"day")*e/30}this.x=o}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=h.diff(this.task._end,this.task._start,"hour")/this.gantt.options.step}get_snap_position(t){let e,s,i=t;return this.gantt.view_is("Week")?(e=t%(this.gantt.options.column_width/7),s=i-e+(e<this.gantt.options.column_width/14?0:this.gantt.options.column_width/7)):this.gantt.view_is("Month")?(e=t%(this.gantt.options.column_width/30),s=i-e+(e<this.gantt.options.column_width/60?0:this.gantt.options.column_width/30)):(e=t%this.gantt.options.column_width,s=i-e+(e<this.gantt.options.column_width/2?0:this.gantt.options.column_width)),s}update_attr(t,e,s){return s=+s,isNaN(s)||t.setAttribute(e,s),t}update_expected_progressbar_position(){this.invalid||(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(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.$bar.getWidth()*(this.task.progress/100)))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,s=this.group.querySelector(".bar-label"),i=this.group.querySelector(".bar-img");let o=this.image_size+10;const a=s.getBBox().width,n=e.getWidth();a>n?(s.classList.add("big"),i?(i.setAttribute("x",e.getX()+e.getWidth()+5),t.setAttribute("x",e.getX()+e.getWidth()+5),s.setAttribute("x",e.getX()+e.getWidth()+o)):s.setAttribute("x",e.getX()+e.getWidth()+5)):(s.classList.remove("big"),i?(i.setAttribute("x",e.getX()+5),t.setAttribute("x",e.getX()+5),s.setAttribute("x",e.getX()+n/2+o)):s.setAttribute("x",e.getX()+n/2-a/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()-12),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()+4);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 c{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()<t+this.gantt.options.padding&&t>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-7,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,a=this.from_task.task._index>this.to_task.task._index,n=this.gantt.options.arrow_curve,r=a?1:0,h=a?-n:n,d=a?o+this.gantt.options.arrow_curve:o-this.gantt.options.arrow_curve;if(this.path=`\n M ${t} ${s}\n V ${d}\n a ${n} ${n} 0 0 ${r} ${n} ${h}\n L ${i} ${o}\n m -5 -5\n l 5 5\n l -5 5`,this.to_task.$bar.getX()<this.from_task.$bar.getX()+this.gantt.options.padding){const e=this.gantt.options.padding/2-n,a=this.to_task.$bar.getY()+this.to_task.$bar.getHeight()/2-h,d=this.to_task.$bar.getX()-this.gantt.options.padding;this.path=`\n M ${t} ${s}\n v ${e}\n a ${n} ${n} 0 0 1 -${n} ${n}\n H ${d}\n a ${n} ${n} 0 0 ${r} -${n} ${h}\n V ${a}\n a ${n} ${n} 0 0 ${r} ${n} ${h}\n L ${i} ${o}\n m -5 -5\n l 5 5\n l -5 5`}}draw(){this.element=l("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 m{constructor(t,e){this.parent=t,this.custom_html=e,this.make()}make(){this.parent.innerHTML='\n <div class="title"></div>\n <div class="subtitle"></div>\n <div class="pointer"></div>\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");const e=t.target_element;if(this.custom_html){let e=this.custom_html(t.task);e+='<div class="pointer"></div>',this.parent.innerHTML=e,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle;let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),this.parent.style.left=t.x-this.parent.clientWidth/2+"px",this.parent.style.top=s.y+s.height+10+"px",this.pointer.style.left=this.parent.clientWidth/2+"px",this.pointer.style.top="-15px",this.parent.style.opacity=1}hide(){this.parent.style.opacity=0,this.parent.style.left=0}}const w={HOUR:"Hour",QUARTER_DAY:"Quarter Day",HALF_DAY:"Half Day",DAY:"Day",WEEK:"Week",MONTH:"Month",YEAR:"Year"},f={HOUR:["7d","7d"],QUARTER_DAY:["7d","7d"],HALF_DAY:["7d","7d"],DAY:["1m","1m"],WEEK:["1m","1m"],MONTH:["1m","1m"],YEAR:["2y","2y"]},b={header_height:65,column_width:30,step:24,view_modes:[...Object.values(w)],bar_height:30,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",popup_trigger:"click",show_expected_progress:!1,popup:null,language:"en",readonly:!1,highlight_weekend:!0,scroll_to:"start",lines:"both",auto_move_label:!0,today_button:!0,view_mode_select:!1};class y{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=l("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){this.options={...b,...t},t.view_mode_padding||(t.view_mode_padding={});for(let[e,s]of Object.entries(t.view_mode_padding))"string"==typeof s&&(t.view_mode_padding[e]=[s,s]);this.options.view_mode_padding={...f,...t.view_mode_padding}}setup_tasks(t){this.tasks=t.map(((t,e)=>{if(t._start=h.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}=h.parse_duration(e);t.end=h.add(t.end,s,i)}))}if(t._end=h.parse(t.end),h.diff(t._end,t._start,"year")<0)throw Error("start of task can't be after end of task: in task #, "+(e+1));if(h.diff(t._end,t._start,"year")>10&&(t.end=null),t._index=e,!t.start&&!t.end){const e=h.today();t._start=e,t._end=h.add(e,2,"day")}!t.start&&t.end&&(t._start=h.add(t._end,-2,"day")),t.start&&!t.end&&(t._end=h.add(t._start,2,"day"));if(h.get_date_values(t._end).slice(3).every((t=>0===t))&&(t._end=h.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().replaceAll(" ","_"))).filter((t=>t))),t.dependencies=e}return t.id?"string"==typeof t.id?t.id=t.id.replaceAll(" ","_"):t.id=`${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===w.HOUR?(this.options.step=1,this.options.column_width=38):t===w.DAY?(this.options.step=24,this.options.column_width=38):t===w.HALF_DAY?(this.options.step=12,this.options.column_width=38):t===w.QUARTER_DAY?(this.options.step=6,this.options.column_width=38):t===w.WEEK?(this.options.step=168,this.options.column_width=140):t===w.MONTH?(this.options.step=720,this.options.column_width=120):t===w.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._start<this.gantt_start)&&(this.gantt_start=t._start),(!this.gantt_end||t._end>this.gantt_end)&&(this.gantt_end=t._end);let t,e,s;t=this.gantt_start?h.start_of(this.gantt_start,"day"):new Date,e=this.gantt_end?h.start_of(this.gantt_end,"day"):new Date;for(let[t,e]of Object.entries(w))e===this.options.view_mode&&(s=t);const[i,o]=this.options.view_mode_padding[s].map(h.parse_duration);let a;t=h.add(t,-i.duration,i.scale),a=this.view_is(w.YEAR)?"YYYY":this.view_is(w.MONTH)?"YYYY-MM":this.view_is(w.DAY)?"YYYY-MM-DD":"YYYY-MM-DD HH",this.gantt_start=h.parse(h.format(t,a)),this.gantt_start.setHours(0,0,0,0),this.gantt_end=h.add(e,o.duration,o.scale)}setup_date_values(){this.dates=[];let t=null;for(;null===t||t<this.gantt_end;)t=t?this.view_is(w.YEAR)?h.add(t,1,"year"):this.view_is(w.MONTH)?h.add(t,1,"month"):h.add(t,this.options.step,"hour"):h.clone(this.gantt_start),this.dates.push(t)}bind_events(){this.options.readonly||(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_grid_extras(),this.make_arrows(),this.map_arrows_on_bars(),this.set_width(),this.set_scroll_position(this.options.scroll_to)}setup_layers(){this.layers={};const t=["grid","arrow","progress","bar","details"];for(let e of t)this.layers[e]=l("g",{class:e,append_to:this.$svg})}make_grid(){this.make_grid_background(),this.make_grid_rows(),this.make_grid_header()}make_grid_extras(){this.make_grid_highlights(),this.make_grid_ticks()}make_grid_background(){const t=this.dates.length*this.options.column_width,e=this.options.header_height+this.options.padding+(this.options.bar_height+this.options.padding)*this.tasks.length;l("rect",{x:0,y:0,width:t,height:e,class:"grid-background",append_to:this.$svg}),p.attr(this.$svg,{height:e+this.options.padding+100,width:"100%"})}make_grid_rows(){const t=l("g",{append_to:this.layers.grid}),e=this.dates.length*this.options.column_width,s=this.options.bar_height+this.options.padding;let i=this.options.header_height+this.options.padding/2;for(let o of this.tasks)l("rect",{x:0,y:i,width:e,height:s,class:"grid-row",append_to:t}),"both"===this.options.lines||this.options.lines,i+=this.options.bar_height+this.options.padding}make_grid_header(){document.querySelector(".grid-header");let t=document.createElement("div");t.style.height=this.options.header_height+10+"px",t.style.width=this.dates.length*this.options.column_width+"px",t.classList.add("grid-header"),this.$header=t,this.$container.appendChild(t);let e=document.createElement("div");e.classList.add("upper-header"),this.$upper_header=e,this.$header.appendChild(e);let s=document.createElement("div");s.classList.add("lower-header"),this.$lower_header=s,this.$header.appendChild(s),this.make_side_header()}make_side_header(){let t=document.createElement("div");if(t.classList.add("side-header"),this.options.view_mode_select){const e=document.createElement("select");e.classList.add("viewmode-select");const s=document.createElement("option");s.selected=!0,s.disabled=!0,s.textContent="Mode",e.appendChild(s);for(const t in w){const s=document.createElement("option");s.value=w[t],s.textContent=w[t],e.appendChild(s)}e.addEventListener("change",function(){this.change_view_mode(e.value)}.bind(this)),t.appendChild(e)}if(this.options.today_button){let e=document.createElement("button");e.classList.add("today-button"),e.textContent="Today",e.onclick=this.scroll_today.bind(this),t.appendChild(e)}this.$header.appendChild(t);const{left:e,y:s}=this.$header.getBoundingClientRect(),i=Math.min(this.$header.clientWidth,this.$container.clientWidth);t.style.left=e+this.$container.scrollLeft+i-t.clientWidth+"px",t.style.top=s+10+"px"}make_grid_ticks(){if(!["both","vertical","horizontal"].includes(this.options.lines))return;let t=0,e=this.options.header_height+this.options.padding/2,s=(this.options.bar_height+this.options.padding)*this.tasks.length,i=l("g",{class:"lines_layer",append_to:this.layers.grid}),o=this.options.header_height+this.options.padding/2;const a=this.dates.length*this.options.column_width,n=this.options.bar_height+this.options.padding;if("vertical"!==this.options.lines)for(let t of this.tasks)l("line",{x1:0,y1:o+n,x2:a,y2:o+n,class:"row-line",append_to:i}),o+=n;if("horizontal"!==this.options.lines)for(let i of this.dates){let o="tick";this.view_is(w.DAY)&&1===i.getDate()&&(o+=" thick"),this.view_is(w.WEEK)&&i.getDate()>=1&&i.getDate()<8&&(o+=" thick"),this.view_is(w.MONTH)&&i.getMonth()%3==0&&(o+=" thick"),l("path",{d:`M ${t} ${e} v ${s}`,class:o,append_to:this.layers.grid}),this.view_is(w.MONTH)?t+=h.get_days_in_month(i)*this.options.column_width/30:t+=this.options.column_width}}highlightWeekends(){if(this.view_is("Day")||this.view_is("Half Day"))for(let t=new Date(this.gantt_start);t<=this.gantt_end;t.setDate(t.getDate()+1))if(0===t.getDay()||6===t.getDay()){const e=h.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,s=(this.options.bar_height+this.options.padding)*this.tasks.length;l("rect",{x:e,y:this.options.header_height+this.options.padding/2,width:(this.view_is("Day")?1:2)*this.options.column_width,height:s,class:"holiday-highlight",append_to:this.layers.grid})}}computeGridHighlightDimensions(t){let e=this.options.column_width/2;if(this.view_is(w.DAY)){let t=h.today();return{x:e+h.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,date:t}}for(let s of this.dates){const i=new Date,o=new Date(s),a=new Date(s);switch(t){case w.WEEK:a.setDate(s.getDate()+7);break;case w.MONTH:a.setMonth(s.getMonth()+1);break;case w.YEAR:a.setFullYear(s.getFullYear()+1)}if(i>=o&&i<=a)return{x:e,date:o};e+=this.options.column_width}}make_grid_highlights(){if(this.options.highlight_weekend&&this.highlightWeekends(),this.view_is(w.DAY)||this.view_is(w.WEEK)||this.view_is(w.MONTH)||this.view_is(w.YEAR)){const{x:t,date:e}=this.computeGridHighlightDimensions(this.options.view_mode),s=this.options.header_height+this.options.padding/2,i=(this.options.bar_height+this.options.padding)*this.tasks.length;this.$current_highlight=this.create_el({top:s,left:t,height:i,classes:"current-highlight",append_to:this.$container});let o=document.getElementById(h.format(e).replaceAll(" ","_"));o.classList.add("current-date-highlight"),o.style.top=+o.style.top.slice(0,-2)-4+"px",o.style.left=+o.style.left.slice(0,-2)-8+"px"}}create_el({left:t,top:e,width:s,height:i,id:o,classes:a,append_to:n}){let r=document.createElement("div");return r.classList.add(a),r.style.top=e+"px",r.style.left=t+"px",o&&(r.id=o),s&&(r.style.width=i+"px"),i&&(r.style.height=i+"px"),n.appendChild(r),r}make_dates(){this.upper_texts_x={},this.get_dates_to_draw().forEach(((t,e)=>{let s=this.create_el({left:t.lower_x,top:t.lower_y,id:t.formatted_date,classes:"lower-text",append_to:this.$lower_header});if(s.innerText=t.lower_text,s.style.left=+s.style.left.slice(0,-2)-s.clientWidth/2+"px",t.upper_text){this.upper_texts_x[t.upper_text]=t.upper_x;let e=document.createElement("div");e.classList.add("upper-text"),e.style.left=t.upper_x+"px",e.style.top=t.upper_y+"px",e.innerText=t.upper_text,this.$upper_header.appendChild(e),t.upper_x>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=i,i}))}get_date_info(t,e){let s=e?e.date:h.add(t,1,"day");const i={Hour_lower:h.format(t,"HH",this.options.language),"Quarter Day_lower":h.format(t,"HH",this.options.language),"Half Day_lower":h.format(t,"HH",this.options.language),Day_lower:t.getDate()!==s.getDate()?h.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language),Month_lower:h.format(t,"MMMM",this.options.language),Year_lower:h.format(t,"YYYY",this.options.language),Hour_upper:t.getDate()!==s.getDate()?h.format(t,"D MMMM",this.options.language):"","Quarter Day_upper":t.getDate()!==s.getDate()?h.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==s.getDate()?t.getMonth()!==s.getMonth()?h.format(t,"D MMM",this.options.language):h.format(t,"D",this.options.language):"",Day_upper:t.getMonth()===s.getMonth()&&e?"":h.format(t,"MMMM",this.options.language),Week_upper:t.getMonth()!==s.getMonth()?h.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==s.getFullYear()?h.format(t,"YYYY",this.options.language):""};let o=this.view_is(w.MONTH)?h.get_days_in_month(t)*this.options.column_width/30:this.options.column_width;const a={x:e?e.base_pos_x+e.column_width:0,lower_y:this.options.header_height-20,upper_y:this.options.header_height-50},n={Hour_lower:o/2,Hour_upper:12*o,"Quarter Day_lower":o/2,"Quarter Day_upper":2*o,"Half Day_lower":o/2,"Half Day_upper":o,Day_lower:o/2,Day_upper:o/2,Week_lower:o/2,Week_upper:4*o/2,Month_lower:o/2,Month_upper:o/2,Year_lower:o/2,Year_upper:30*o/2};return{date:t,formatted_date:h.format(t).replaceAll(" ","_"),column_width:o,base_pos_x:a.x,upper_text:this.options.lower_text?this.options.upper_text(t,this.options.view_mode,i[`${this.options.view_mode}_upper`]):i[`${this.options.view_mode}_upper`],lower_text:this.options.lower_text?this.options.lower_text(t,this.options.view_mode,i[`${this.options.view_mode}_lower`]):i[`${this.options.view_mode}_lower`],upper_x:a.x+n[`${this.options.view_mode}_upper`],upper_y:a.upper_y,lower_x:a.x+n[`${this.options.view_mode}_lower`],lower_y:a.lower_y}}make_bars(){this.bars=this.tasks.map((t=>{const e=new u(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 c(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")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t<e&&this.$svg.setAttribute("width",e)}set_scroll_position(t){if(t&&"start"!==t){if("today"===t)return this.scroll_today();"string"==typeof t&&(t=h.parse(t))}else t=this.gantt_start;const e=this.$svg.parentElement;if(!e)return;const s=(h.diff(t,this.gantt_start,"hour")+24)/this.options.step*this.options.column_width-this.options.column_width;e.scrollTo({left:s,behavior:"smooth"})}scroll_today(){this.set_scroll_position(new Date)}bind_grid_click(){p.on(this.$svg,this.options.popup_trigger,".grid-row, .grid-header",(()=>{this.unselect_all(),this.hide_popup()}))}bind_bar_events(){let t=!1,e=0,s=0,i=0,o=!1,a=!1,n=null,r=[];this.bar_being_dragged=null,p.on(this.$svg,"mousedown",".bar-wrapper, .handle",((s,h)=>{const d=p.closest(".bar-wrapper",h);r.forEach((t=>t.group.classList.remove("active"))),h.classList.contains("left")?o=!0:h.classList.contains("right")?a=!0:h.classList.contains("bar-wrapper")&&(t=!0),d.classList.add("active"),this.popup.parent.classList.add("hidden"),e=s.offsetX,i=s.offsetY,n=d.getAttribute("data-id");const l=[n,...this.get_all_dependent_tasks(n)];r=l.map((t=>this.get_bar(t))),this.bar_being_dragged=n,r.forEach((t=>{const e=t.$bar;e.ox=e.getX(),e.oy=e.getY(),e.owidth=e.getWidth(),e.finaldx=0}))})),p.on(this.$container,"scroll",(t=>{let e=document.querySelectorAll(".bar-wrapper"),i=[];const o=[];let a;s&&(a=t.currentTarget.scrollLeft-s);const n=t.currentTarget.scrollLeft/this.options.column_width*this.options.step/24;let r="D MMM";["Year","Month"].includes(this.options.view_mode)?r="YYYY":["Day","Week"].includes(this.options.view_mode)?r="MMMM":this.view_is("Half Day")?r="D":this.view_is("Hour")&&(r="D MMMM");let d=h.format(h.add(this.gantt_start,n,"day"),r);const p=Array.from(document.querySelectorAll(".upper-text")).find((t=>t.textContent===d));if(p&&!p.classList.contains("current-upper")){const t=document.querySelector(".current-upper");t&&(t.classList.remove("current-upper"),t.style.left=this.upper_texts_x[t.textContent]+"px",t.style.top=this.options.header_height-50+"px"),p.classList.add("current-upper");let e=this.$svg.getBoundingClientRect();p.style.left=e.x+this.$container.scrollLeft+10+"px",p.style.top=e.y+this.options.header_height-50+"px"}Array.prototype.forEach.call(e,(function(t,e){o.push(t.getAttribute("data-id"))})),a&&(i=o.map((t=>this.get_bar(t))),this.options.auto_move_label&&i.forEach((e=>{e.update_label_position_on_horizontal_scroll({x:a,sx:t.currentTarget.scrollLeft})}))),s=t.currentTarget.scrollLeft})),p.on(this.$svg,"mousemove",(s=>{if(!(t||o||a))return;const i=s.offsetX-e;s.offsetY,r.forEach((e=>{const s=e.$bar;s.finaldx=this.get_snap_position(i),this.hide_popup(),o?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}):a?n===e.task.id&&e.update_bar_position({width:s.owidth+s.finaldx}):t&&!this.options.readonly&&e.update_bar_position({x:s.ox+s.finaldx})}))})),document.addEventListener("mouseup",(e=>{t=!1,o=!1,a=!1})),p.on(this.$svg,"mouseup",(t=>{this.bar_being_dragged=null,r.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,a=null;p.on(this.$svg,"mousedown",".handle.progress",((n,r)=>{s=!0,t=n.offsetX,e=n.offsetY;const h=p.closest(".bar-wrapper",r).getAttribute("data-id");i=this.get_bar(h),o=i.$bar_progress,a=i.$bar,o.finaldx=0,o.owidth=o.getWidth(),o.min_dx=-o.getWidth(),o.max_dx=a.getWidth()-o.getWidth()})),p.on(this.$svg,"mousemove",(e=>{if(!s)return;let a=e.offsetX-t;e.offsetY,a>o.max_dx&&(a=o.max_dx),a<o.min_dx&&(a=o.min_dx);const n=i.$handle_progress;p.attr(o,"width",o.owidth+a),p.attr(n,"points",i.get_progress_polygon_points()),o.finaldx=a})),p.on(this.$svg,"mouseup",(()=>{s=!1,o&&o.finaldx&&(o.finaldx=0,i.progress_changed(),i.set_action_completed(),i=null,o=null,a=null)}))}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(w.WEEK)?(e=t%(this.options.column_width/7),s=i-e+(e<this.options.column_width/14?0:this.options.column_width/7)):this.view_is(w.MONTH)?(e=t%(this.options.column_width/30),s=i-e+(e<this.options.column_width/60?0:this.options.column_width/30)):(e=t%this.options.column_width,s=i-e+(e<this.options.column_width/2?0:this.options.column_width)),s}unselect_all(){[...this.$svg.querySelectorAll(".bar-wrapper")].forEach((t=>{t.classList.remove("active")})),this.popup.parent.classList.remove("hidden")}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){!1!==this.options.popup&&(this.popup||(this.popup=new m(this.$popup_wrapper,this.options.popup)),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.length?this.tasks.map((t=>t._start)).reduce(((t,e)=>e<=t?e:t)):new Date}clear(){this.$svg.innerHTML="",this.$header?.remove?.(),this.$current_highlight?.remove?.(),this.popup?.hide?.()}}return y.VIEW_MODE=w,y}();
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){const t={y:"year",m:"month",d:"day",h:"hour",min:"minute",s:"second",ms:"millisecond"}[e[2]];if(t)return{duration:parseInt(e[1]),scale:t}}},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]?i[1]-1:0;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=new Intl.DateTimeFormat(s,{month:"short"}).format(t),n=i.charAt(0).toUpperCase()+i.slice(1),a=this.get_date_values(t).map((t=>h(t,2,0))),r={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:o};let d=e;const p=[];return Object.keys(r).sort(((t,e)=>e.length-t.length)).forEach((t=>{d.includes(t)&&(d=d.replaceAll(t,`$${p.length}`),p.push(r[t]))})),p.forEach(((t,e)=>{d=d.replaceAll(`$${e}`,t)})),d},diff(t,e,i=s){let o,n,a,r,h,d,p;return o=t-e,n=o/1e3,r=n/60,a=r/60,h=a/24,d=h/30,p=d/12,i.endsWith("s")||(i+="s"),Math.floor({milliseconds:o,seconds:n,minutes:r,hours:a,days:h,months:d,years:p}[i])},today(){const t=this.get_date_values(new Date).slice(0,3);return new Date(...t)},now:()=>new Date,add(r,h,d){h=parseInt(h,10);const p=[r.getFullYear()+(d===t?h:0),r.getMonth()+(d===e?h:0),r.getDate()+(d===s?h:0),r.getHours()+(d===i?h:0),r.getMinutes()+(d===o?h:0),r.getSeconds()+(d===n?h:0),r.getMilliseconds()+(d===a?h:0)];return new Date(...p)},start_of(r,h){const d={[t]:6,[e]:5,[s]:4,[i]:3,[o]:2,[n]:1,[a]:0};function p(t){return d[t]<=d[h]}const l=[r.getFullYear(),p(t)?0:r.getMonth(),p(e)?1:r.getDate(),p(s)?0:r.getHours(),p(i)?0:r.getMinutes(),p(o)?0:r.getSeconds(),p(n)?0:r.getMilliseconds()];return new Date(...l)},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 d(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function p(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:"clipPath"===t?s.setAttribute("clip-path","url(#"+e[t]+")"):s.setAttribute(t,e[t]);return s}function l(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 d.attr(a,{attributeName:e,from:s,to:i,dur:o,begin:"click + "+n}),t;const r=p("animate",{attributeName:e,from:s,to:i,dur:o,begin:n,calcMode:"spline",values:s+";"+i,keyTimes:"0; 1",keySplines:_("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 _(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]}d.on=(t,e,s,i)=>{i?d.delegate(t,e,s,i):(i=s,d.bind(t,e,i))},d.off=(t,e,s)=>{t.removeEventListener(e,s)},d.bind=(t,e,s)=>{e.split(/\s+/).forEach((function(e){t.addEventListener(e,s)}))},d.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))}))},d.closest=(t,e)=>e?e.matches(t)?e:d.closest(t,e.parentNode):null,d.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)d.attr(t,s,e[s])};class g{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.image_size=this.height-5,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=p("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:"")+(this.task.important?" important":""),"data-id":this.task.id}),this.bar_group=p("g",{class:"bar-group",append_to:this.group}),this.handle_group=p("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.draw_progress_bar(),this.gantt.options.show_expected_progress&&(this.prepare_expected_progress_values(),this.draw_expected_progress_bar()),this.draw_label(),this.draw_resize_handles(),this.task.thumbnail&&this.draw_thumbnail()}draw_bar(){this.$bar=p("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}),l(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=p("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}),l(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.$bar_progress=p("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});const t=r.diff(this.task._start,this.gantt.gantt_start,"hour")/this.gantt.options.step*this.gantt.options.column_width;let e=document.createElement("div");e.id=`${this.task.id}-highlight`,e.classList.add("date-highlight"),e.style.height=.8*this.height+"px",e.style.width=this.width+"px",e.style.top=this.gantt.options.header_height-25+"px",e.style.left=t+"px",this.$date_highlight=e,this.gantt.$lower_header.prepend(e),l(this.$bar_progress,"width",0,this.progress_width)}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),p("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),requestAnimationFrame((()=>this.update_label_position()))}draw_thumbnail(){let t,e;t=p("defs",{append_to:this.bar_group}),p("rect",{id:"rect_"+this.task.id,x:this.x+10,y:this.y+2,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:t}),e=p("clipPath",{id:"clip_"+this.task.id,append_to:t}),p("use",{href:"#rect_"+this.task.id,append_to:e}),p("image",{x:this.x+10,y:this.y+2,width:this.image_size,height:this.image_size,class:"bar-img",href:this.task.thumbnail,clipPath:"clip_"+this.task.id,append_to:this.bar_group})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;p("rect",{x:t.getX()+t.getWidth()+8-4,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}),p("rect",{x:t.getX()-8-4,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=p("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()/2,t.getEndX(),t.getY()+t.getHeight()/2-7.5,t.getEndX()+5,t.getY()+t.getHeight()/2,t.getEndX(),t.getY()+t.getHeight()/2+7.5,t.getEndX()-5,t.getY()+t.getHeight()/2]}bind(){this.setup_click_event()}setup_click_event(){let t,e=this.task.id;d.on(this.group,"mouseover",(t=>{this.gantt.trigger_event("hover",[this.task,t.screenX,t.screenY,t])})),d.on(this.group,"mouseenter",(s=>{let i=s.offsetX;t=setTimeout((()=>{this.show_popup(i),document.querySelector(`#${e}-highlight`).style.display="block"}),200)})),d.on(this.group,"mouseleave",(()=>{clearTimeout(t),this.gantt.popup?.hide?.(),document.querySelector(`#${e}-highlight`).style.display="none"})),d.on(this.group,this.gantt.options.popup_trigger,(()=>{this.gantt.trigger_event("click",[this.task])})),d.on(this.group,"dblclick",(t=>{this.action_completed||this.gantt.trigger_event("double_click",[this.task])}))}show_popup(t){if(this.gantt.bar_being_dragged)return;const e=`${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)}<br/>Progress: ${this.task.progress}`;this.gantt.show_popup({x:t,target_element:this.$bar,title:this.task.name,subtitle:e,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),this.$date_highlight.style.left=t+"px"}e&&(this.update_attr(s,"width",e),this.$date_highlight.style.width=e+"px"),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()}update_label_position_on_horizontal_scroll({x:t,sx:e}){const s=document.querySelector(".gantt-container"),i=this.group.querySelector(".bar-label"),o=this.group.querySelector(".bar-img")||"",n=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),r=i.getX()+t,h=o&&o.getX()+t||0,d=o&&o.getBBox().width+7||7,p=r+i.getBBox().width+7,l=e+s.clientWidth/2;i.classList.contains("big")||(p<a&&t>0&&p<l||r-d>this.$bar.getX()&&t<0&&p>l)&&(i.setAttribute("x",r),o&&(o.setAttribute("x",h),n.setAttribute("x",h)))}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_progress<this.duration?this.expected_progress:this.duration)/this.duration}compute_x(){const{step:t,column_width:e}=this.gantt.options,s=this.task._start,i=this.gantt.gantt_start;let o=r.diff(s,i,"hour")/t*e;if(this.gantt.view_is("Month")){o=r.diff(s,i,"day")*e/30}this.x=o}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=r.diff(this.task._end,this.task._start,"hour")/this.gantt.options.step}get_snap_position(t){let e,s,i=t;return this.gantt.view_is("Week")?(e=t%(this.gantt.options.column_width/7),s=i-e+(e<this.gantt.options.column_width/14?0:this.gantt.options.column_width/7)):this.gantt.view_is("Month")?(e=t%(this.gantt.options.column_width/30),s=i-e+(e<this.gantt.options.column_width/60?0:this.gantt.options.column_width/30)):(e=t%this.gantt.options.column_width,s=i-e+(e<this.gantt.options.column_width/2?0:this.gantt.options.column_width)),s}update_attr(t,e,s){return s=+s,isNaN(s)||t.setAttribute(e,s),t}update_expected_progressbar_position(){this.invalid||(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(){this.invalid||this.gantt.options.readonly||(this.$bar_progress.setAttribute("x",this.$bar.getX()),this.$bar_progress.setAttribute("width",this.$bar.getWidth()*(this.task.progress/100)))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,s=this.group.querySelector(".bar-label"),i=this.group.querySelector(".bar-img");let o=this.image_size+10;const n=s.getBBox().width,a=e.getWidth();n>a?(s.classList.add("big"),i?(i.setAttribute("x",e.getX()+e.getWidth()+5),t.setAttribute("x",e.getX()+e.getWidth()+5),s.setAttribute("x",e.getX()+e.getWidth()+o)):s.setAttribute("x",e.getX()+e.getWidth()+5)):(s.classList.remove("big"),i?(i.setAttribute("x",e.getX()+5),t.setAttribute("x",e.getX()+5),s.setAttribute("x",e.getX()+a/2+o)):s.setAttribute("x",e.getX()+a/2-n/2))}update_handle_position(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar;this.handle_group.querySelector(".handle.left").setAttribute("x",t.getX()-12),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX()+4);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 c{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()<t+this.gantt.options.padding&&t>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-7,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,d=n?o+this.gantt.options.arrow_curve:o-this.gantt.options.arrow_curve;if(this.path=`\n M ${t} ${s}\n V ${d}\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()<this.from_task.$bar.getX()+this.gantt.options.padding){const e=this.gantt.options.padding/2-a,n=this.to_task.$bar.getY()+this.to_task.$bar.getHeight()/2-h,d=this.to_task.$bar.getX()-this.gantt.options.padding;this.path=`\n M ${t} ${s}\n v ${e}\n a ${a} ${a} 0 0 1 -${a} ${a}\n H ${d}\n a ${a} ${a} 0 0 ${r} -${a} ${h}\n V ${n}\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`}}draw(){this.element=p("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 u{constructor(t,e){this.parent=t,this.custom_html=e,this.make()}make(){this.parent.innerHTML='\n <div class="title"></div>\n <div class="subtitle"></div>\n <div class="pointer"></div>\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");const e=t.target_element;if(this.custom_html){let e=this.custom_html(t.task);e+='<div class="pointer"></div>',this.parent.innerHTML=e,this.pointer=this.parent.querySelector(".pointer")}else this.title.innerHTML=t.title,this.subtitle.innerHTML=t.subtitle;let s;e instanceof HTMLElement?s=e.getBoundingClientRect():e instanceof SVGElement&&(s=t.target_element.getBBox()),this.parent.style.left=t.x-this.parent.clientWidth/2+"px",this.parent.style.top=s.y+s.height+10+"px",this.pointer.style.left=this.parent.clientWidth/2+"px",this.pointer.style.top="-15px",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"]},f={header_height:65,column_width:30,step:24,view_modes:[...Object.values(m)],bar_height:30,bar_corner_radius:3,arrow_curve:5,padding:18,view_mode:"Day",date_format:"YYYY-MM-DD",popup_trigger:"click",show_expected_progress:!1,popup:null,language:"en",readonly:!1,highlight_weekend:!0,scroll_to:"start",lines:"both",auto_move_label:!0,today_button:!0,view_mode_select:!1};class b{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=p("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){this.options={...f,...t},t.view_mode_padding||(t.view_mode_padding={});for(let[e,s]of Object.entries(t.view_mode_padding))"string"==typeof s&&(t.view_mode_padding[e]=[s,s]);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")<0)throw Error("start of task can't be after end of task: in task #, "+(e+1));if(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().replaceAll(" ","_"))).filter((t=>t))),t.dependencies=e}return t.id?"string"==typeof t.id?t.id=t.id.replaceAll(" ","_"):t.id=`${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._start<this.gantt_start)&&(this.gantt_start=t._start),(!this.gantt_end||t._end>this.gantt_end)&&(this.gantt_end=t._end);let t,e,s;t=this.gantt_start?r.start_of(this.gantt_start,"day"):new Date,e=this.gantt_end?r.start_of(this.gantt_end,"day"):new Date;for(let[t,e]of Object.entries(m))e===this.options.view_mode&&(s=t);const[i,o]=this.options.view_mode_padding[s].map(r.parse_duration);let n;t=r.add(t,-i.duration,i.scale),n=this.view_is(m.YEAR)?"YYYY":this.view_is(m.MONTH)?"YYYY-MM":this.view_is(m.DAY)?"YYYY-MM-DD":"YYYY-MM-DD HH",this.gantt_start=r.parse(r.format(t,n)),this.gantt_start.setHours(0,0,0,0),this.gantt_end=r.add(e,o.duration,o.scale)}setup_date_values(){this.dates=[];let t=null;for(;null===t||t<this.gantt_end;)t=t?this.view_is(m.YEAR)?r.add(t,1,"year"):this.view_is(m.MONTH)?r.add(t,1,"month"):r.add(t,this.options.step,"hour"):r.clone(this.gantt_start),this.dates.push(t)}bind_events(){this.options.readonly||(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_grid_extras(),this.make_arrows(),this.map_arrows_on_bars(),this.set_width(),this.set_scroll_position(this.options.scroll_to)}setup_layers(){this.layers={};const t=["grid","arrow","progress","bar","details"];for(let e of t)this.layers[e]=p("g",{class:e,append_to:this.$svg})}make_grid(){this.make_grid_background(),this.make_grid_rows(),this.make_grid_header()}make_grid_extras(){this.make_grid_highlights(),this.make_grid_ticks()}make_grid_background(){const t=this.dates.length*this.options.column_width,e=this.options.header_height+this.options.padding+(this.options.bar_height+this.options.padding)*this.tasks.length;p("rect",{x:0,y:0,width:t,height:e,class:"grid-background",append_to:this.$svg}),d.attr(this.$svg,{height:e+this.options.padding+100,width:"100%"})}make_grid_rows(){const t=p("g",{append_to:this.layers.grid}),e=this.dates.length*this.options.column_width,s=this.options.bar_height+this.options.padding;let i=this.options.header_height+this.options.padding/2;for(let o of this.tasks)p("rect",{x:0,y:i,width:e,height:s,class:"grid-row",append_to:t}),"both"===this.options.lines||this.options.lines,i+=this.options.bar_height+this.options.padding}make_grid_header(){document.querySelector(".grid-header");let t=document.createElement("div");t.style.height=this.options.header_height+10+"px",t.style.width=this.dates.length*this.options.column_width+"px",t.classList.add("grid-header"),this.$header=t,this.$container.appendChild(t);let e=document.createElement("div");e.classList.add("upper-header"),this.$upper_header=e,this.$header.appendChild(e);let s=document.createElement("div");s.classList.add("lower-header"),this.$lower_header=s,this.$header.appendChild(s),this.make_side_header()}make_side_header(){let t=document.createElement("div");if(t.classList.add("side-header"),this.options.view_mode_select){const e=document.createElement("select");e.classList.add("viewmode-select");const s=document.createElement("option");s.selected=!0,s.disabled=!0,s.textContent="Mode",e.appendChild(s);for(const t in m){const s=document.createElement("option");s.value=m[t],s.textContent=m[t],e.appendChild(s)}e.addEventListener("change",function(){this.change_view_mode(e.value)}.bind(this)),t.appendChild(e)}if(this.options.today_button){let e=document.createElement("button");e.classList.add("today-button"),e.textContent="Today",e.onclick=this.scroll_today.bind(this),t.appendChild(e)}this.$header.appendChild(t);const{left:e,y:s}=this.$header.getBoundingClientRect(),i=Math.min(this.$header.clientWidth,this.$container.clientWidth);t.style.left=e+this.$container.scrollLeft+i-t.clientWidth+"px",t.style.top=s+10+"px"}make_grid_ticks(){if(!["both","vertical","horizontal"].includes(this.options.lines))return;let t=0,e=this.options.header_height+this.options.padding/2,s=(this.options.bar_height+this.options.padding)*this.tasks.length,i=p("g",{class:"lines_layer",append_to:this.layers.grid}),o=this.options.header_height+this.options.padding/2;const n=this.dates.length*this.options.column_width,a=this.options.bar_height+this.options.padding;if("vertical"!==this.options.lines)for(let t of this.tasks)p("line",{x1:0,y1:o+a,x2:n,y2:o+a,class:"row-line",append_to:i}),o+=a;if("horizontal"!==this.options.lines)for(let i of this.dates){let o="tick";this.view_is(m.DAY)&&1===i.getDate()&&(o+=" thick"),this.view_is(m.WEEK)&&i.getDate()>=1&&i.getDate()<8&&(o+=" thick"),this.view_is(m.MONTH)&&i.getMonth()%3==0&&(o+=" thick"),p("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}}highlightWeekends(){if(this.view_is("Day")||this.view_is("Half Day"))for(let t=new Date(this.gantt_start);t<=this.gantt_end;t.setDate(t.getDate()+1))if(0===t.getDay()||6===t.getDay()){const e=r.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,s=(this.options.bar_height+this.options.padding)*this.tasks.length;p("rect",{x:e,y:this.options.header_height+this.options.padding/2,width:(this.view_is("Day")?1:2)*this.options.column_width,height:s,class:"holiday-highlight",append_to:this.layers.grid})}}computeGridHighlightDimensions(t){let e=this.options.column_width/2;if(this.view_is(m.DAY)){let t=r.today();return{x:e+r.diff(t,this.gantt_start,"hour")/this.options.step*this.options.column_width,date:t}}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)return{x:e,date:o};e+=this.options.column_width}}make_grid_highlights(){if(this.options.highlight_weekend&&this.highlightWeekends(),this.view_is(m.DAY)||this.view_is(m.WEEK)||this.view_is(m.MONTH)||this.view_is(m.YEAR)){const{x:t,date:e}=this.computeGridHighlightDimensions(this.options.view_mode),s=this.options.header_height+this.options.padding/2,i=(this.options.bar_height+this.options.padding)*this.tasks.length;this.$current_highlight=this.create_el({top:s,left:t,height:i,classes:"current-highlight",append_to:this.$container});let o=document.getElementById(r.format(e).replaceAll(" ","_"));o.classList.add("current-date-highlight"),o.style.top=+o.style.top.slice(0,-2)-4+"px",o.style.left=+o.style.left.slice(0,-2)-8+"px"}}create_el({left:t,top:e,width:s,height:i,id:o,classes:n,append_to:a}){let r=document.createElement("div");return r.classList.add(n),r.style.top=e+"px",r.style.left=t+"px",o&&(r.id=o),s&&(r.style.width=i+"px"),i&&(r.style.height=i+"px"),a.appendChild(r),r}make_dates(){this.upper_texts_x={},this.get_dates_to_draw().forEach(((t,e)=>{let s=this.create_el({left:t.lower_x,top:t.lower_y,id:t.formatted_date,classes:"lower-text",append_to:this.$lower_header});if(s.innerText=t.lower_text,s.style.left=+s.style.left.slice(0,-2)-s.clientWidth/2+"px",t.upper_text){this.upper_texts_x[t.upper_text]=t.upper_x;let e=document.createElement("div");e.classList.add("upper-text"),e.style.left=t.upper_x+"px",e.style.top=t.upper_y+"px",e.innerText=t.upper_text,this.$upper_header.appendChild(e),t.upper_x>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=i,i}))}get_date_info(t,e){let s=e?e.date: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()!==s.getDate()?r.format(t,"D",this.options.language):"",Week_lower:t.getMonth()!==s.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()!==s.getDate()?r.format(t,"D MMMM",this.options.language):"","Quarter Day_upper":t.getDate()!==s.getDate()?r.format(t,"D MMM",this.options.language):"","Half Day_upper":t.getDate()!==s.getDate()?t.getMonth()!==s.getMonth()?r.format(t,"D MMM",this.options.language):r.format(t,"D",this.options.language):"",Day_upper:t.getMonth()===s.getMonth()&&e?"":r.format(t,"MMMM",this.options.language),Week_upper:t.getMonth()!==s.getMonth()?r.format(t,"MMMM",this.options.language):"",Month_upper:t.getFullYear()!==s.getFullYear()?r.format(t,"YYYY",this.options.language):"",Year_upper:t.getFullYear()!==s.getFullYear()?r.format(t,"YYYY",this.options.language):""};let o=this.view_is(m.MONTH)?r.get_days_in_month(t)*this.options.column_width/30:this.options.column_width;const n={x:e?e.base_pos_x+e.column_width:0,lower_y:this.options.header_height-20,upper_y:this.options.header_height-50},a={Hour_lower:o/2,Hour_upper:12*o,"Quarter Day_lower":o/2,"Quarter Day_upper":2*o,"Half Day_lower":o/2,"Half Day_upper":o,Day_lower:o/2,Day_upper:o/2,Week_lower:o/2,Week_upper:4*o/2,Month_lower:o/2,Month_upper:o/2,Year_lower:o/2,Year_upper:30*o/2};return{date:t,formatted_date:r.format(t).replaceAll(" ","_"),column_width:o,base_pos_x:n.x,upper_text:this.options.lower_text?this.options.upper_text(t,this.options.view_mode,i[`${this.options.view_mode}_upper`]):i[`${this.options.view_mode}_upper`],lower_text:this.options.lower_text?this.options.lower_text(t,this.options.view_mode,i[`${this.options.view_mode}_lower`]):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 g(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 c(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")?this.$svg.querySelector(".grid .grid-row").getAttribute("width"):0;t<e&&this.$svg.setAttribute("width",e)}set_scroll_position(t){if(t&&"start"!==t){if("today"===t)return this.scroll_today();"string"==typeof t&&(t=r.parse(t))}else t=this.gantt_start;const e=this.$svg.parentElement;if(!e)return;const s=(r.diff(t,this.gantt_start,"hour")+24)/this.options.step*this.options.column_width-this.options.column_width;e.scrollTo({left:s,behavior:"smooth"})}scroll_today(){this.set_scroll_position(new Date)}bind_grid_click(){d.on(this.$svg,this.options.popup_trigger,".grid-row, .grid-header",(()=>{this.unselect_all(),this.hide_popup()}))}bind_bar_events(){let t=!1,e=0,s=0,i=0,o=!1,n=!1,a=null,h=[];this.bar_being_dragged=null,d.on(this.$svg,"mousedown",".bar-wrapper, .handle",((s,r)=>{const p=d.closest(".bar-wrapper",r);h.forEach((t=>t.group.classList.remove("active"))),r.classList.contains("left")?o=!0:r.classList.contains("right")?n=!0:r.classList.contains("bar-wrapper")&&(t=!0),p.classList.add("active"),this.popup.parent.classList.add("hidden"),e=s.offsetX,i=s.offsetY,a=p.getAttribute("data-id");const l=[a,...this.get_all_dependent_tasks(a)];h=l.map((t=>this.get_bar(t))),this.bar_being_dragged=a,h.forEach((t=>{const e=t.$bar;e.ox=e.getX(),e.oy=e.getY(),e.owidth=e.getWidth(),e.finaldx=0}))})),d.on(this.$container,"scroll",(t=>{let e=document.querySelectorAll(".bar-wrapper"),i=[];const o=[];let n;s&&(n=t.currentTarget.scrollLeft-s);const a=t.currentTarget.scrollLeft/this.options.column_width*this.options.step/24;let h="D MMM";["Year","Month"].includes(this.options.view_mode)?h="YYYY":["Day","Week"].includes(this.options.view_mode)?h="MMMM":this.view_is("Half Day")?h="D":this.view_is("Hour")&&(h="D MMMM");let d=r.format(r.add(this.gantt_start,a,"day"),h);const p=Array.from(document.querySelectorAll(".upper-text")).find((t=>t.textContent===d));if(p&&!p.classList.contains("current-upper")){const t=document.querySelector(".current-upper");t&&(t.classList.remove("current-upper"),t.style.left=this.upper_texts_x[t.textContent]+"px",t.style.top=this.options.header_height-50+"px"),p.classList.add("current-upper");let e=this.$svg.getBoundingClientRect();p.style.left=e.x+this.$container.scrollLeft+10+"px",p.style.top=e.y+this.options.header_height-50+"px"}Array.prototype.forEach.call(e,(function(t,e){o.push(t.getAttribute("data-id"))})),n&&(i=o.map((t=>this.get_bar(t))),this.options.auto_move_label&&i.forEach((e=>{e.update_label_position_on_horizontal_scroll({x:n,sx:t.currentTarget.scrollLeft})}))),s=t.currentTarget.scrollLeft})),d.on(this.$svg,"mousemove",(s=>{if(!(t||o||n))return;const i=s.offsetX-e;s.offsetY,h.forEach((e=>{const s=e.$bar;s.finaldx=this.get_snap_position(i),this.hide_popup(),o?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&&!this.options.readonly&&e.update_bar_position({x:s.ox+s.finaldx})}))})),document.addEventListener("mouseup",(e=>{t=!1,o=!1,n=!1})),d.on(this.$svg,"mouseup",(t=>{this.bar_being_dragged=null,h.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;d.on(this.$svg,"mousedown",".handle.progress",((a,r)=>{s=!0,t=a.offsetX,e=a.offsetY;const h=d.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()})),d.on(this.$svg,"mousemove",(e=>{if(!s)return;let n=e.offsetX-t;e.offsetY,n>o.max_dx&&(n=o.max_dx),n<o.min_dx&&(n=o.min_dx);const a=i.$handle_progress;d.attr(o,"width",o.owidth+n),d.attr(a,"points",i.get_progress_polygon_points()),o.finaldx=n})),d.on(this.$svg,"mouseup",(()=>{s=!1,o&&o.finaldx&&(o.finaldx=0,i.progress_changed(),i.set_action_completed(),i=null,o=null,n=null)}))}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<this.options.column_width/14?0:this.options.column_width/7)):this.view_is(m.MONTH)?(e=t%(this.options.column_width/30),s=i-e+(e<this.options.column_width/60?0:this.options.column_width/30)):(e=t%this.options.column_width,s=i-e+(e<this.options.column_width/2?0:this.options.column_width)),s}unselect_all(){[...this.$svg.querySelectorAll(".bar-wrapper")].forEach((t=>{t.classList.remove("active")})),this.popup.parent.classList.remove("hidden")}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){!1!==this.options.popup&&(this.popup||(this.popup=new u(this.$popup_wrapper,this.options.popup)),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.length?this.tasks.map((t=>t._start)).reduce(((t,e)=>e<=t?e:t)):new Date}clear(){this.$svg.innerHTML="",this.$header?.remove?.(),this.$current_highlight?.remove?.(),this.popup?.hide?.()}}return b.VIEW_MODE=m,b}();
//# sourceMappingURL=frappe-gantt.min.js.map
{
"name": "@energiency/gantt",
"version": "1.0.0",
"version": "1.0.1",
"description": "A simple, modern, interactive gantt library for the web",

@@ -5,0 +5,0 @@ "repository": {

@@ -271,3 +271,2 @@ import date_utils from './date_utils';

bind() {
if (this.invalid) return;
this.setup_click_event();

@@ -283,11 +282,9 @@ }

let timeout;
$.on(
this.group,
'mouseenter',
(e) =>
(timeout = setTimeout(() => {
this.show_popup(e.offsetX);
document.querySelector(`#${task_id}-highlight`).style.display = 'block';
}, 200)),
);
$.on(this.group, 'mouseenter', (e) => {
let offsetX = e.offsetX;
timeout = setTimeout(() => {
this.show_popup(offsetX);
document.querySelector(`#${task_id}-highlight`).style.display = 'block';
}, 200);
});

@@ -294,0 +291,0 @@ $.on(this.group, 'mouseleave', () => {

@@ -9,17 +9,2 @@ const YEAR = 'year';

const SHORTENED = {
January: 'Jan',
February: 'Feb',
March: 'Mar',
April: 'Apr',
May: 'May',
June: 'Jun',
July: 'Jul',
August: 'Aug',
September: 'Sep',
October: 'Oct',
November: 'Nov',
December: 'Dec',
};
export default {

@@ -29,18 +14,16 @@ parse_duration(duration) {

const matches = regex.exec(duration);
if (matches !== null) {
const timescales = {
y: 'year',
m: 'month',
d: 'day',
h: 'hour',
min: 'minute',
s: 'second',
ms: 'millisecond',
};
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` };
const scale = timescales[matches[2]];
if (scale) {
return { duration: parseInt(matches[1]), scale };
}

@@ -98,10 +81,8 @@ }

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 monthName = new Intl.DateTimeFormat(lang, { month: 'long' }).format(date);
const shortMonthName = new Intl.DateTimeFormat(lang, { month: 'short' }).format(date);
const monthNameCapitalized = monthName.charAt(0).toUpperCase() + monthName.slice(1);
const values = this.get_date_values(date).map((d) => padStart(d, 2, 0));
const format_map = {
const formatMap = {
YYYY: values[0],

@@ -115,19 +96,19 @@ MM: padStart(+values[1] + 1, 2, 0),

D: values[2],
MMMM: month_name_capitalized,
MMM: SHORTENED[month_name_capitalized],
MMMM: monthNameCapitalized,
MMM: shortMonthName,
};
let str = format_string;
const formatted_values = [];
const formattedValues = [];
Object.keys(format_map)
Object.keys(formatMap)
.sort((a, b) => b.length - a.length) // big string first
.forEach((key) => {
if (str.includes(key)) {
str = str.replaceAll(key, `$${formatted_values.length}`);
formatted_values.push(format_map[key]);
str = str.replaceAll(key, `$${formattedValues.length}`);
formattedValues.push(formatMap[key]);
}
});
formatted_values.forEach((value, i) => {
formattedValues.forEach((value, i) => {
str = str.replaceAll(`$${i}`, value);

@@ -134,0 +115,0 @@ });

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc