@workiom/frappe-gantt 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/frappe-gantt.es.js +10 -2
- package/dist/frappe-gantt.umd.js +2 -2
- package/package.json +1 -1
- package/src/bar.js +16 -0
- package/src/defaults.js +1 -0
- package/src/index.js +8 -0
package/dist/frappe-gantt.es.js
CHANGED
|
@@ -575,6 +575,10 @@ class q {
|
|
|
575
575
|
}, 200));
|
|
576
576
|
}), u.on(this.group, "mousedown", () => {
|
|
577
577
|
this.is_dragging = !0, this.hide_add_icon();
|
|
578
|
+
}), u.on(this.group, "mouseup", () => {
|
|
579
|
+
setTimeout(() => {
|
|
580
|
+
this.gantt.bar_being_dragged !== !0 && (this.is_dragging = !1, this.$add_icon_group && this.is_hovering_bar && this.$add_icon_group.classList.remove("hide"));
|
|
581
|
+
}, 0);
|
|
578
582
|
}), u.on(this.group, "click", () => {
|
|
579
583
|
this.action_completed || this.gantt.bar_being_dragged || this.gantt.trigger_event("click", [this.task]);
|
|
580
584
|
}), u.on(this.group, "dblclick", (s) => {
|
|
@@ -892,6 +896,7 @@ const y = [
|
|
|
892
896
|
infinite_padding: !0,
|
|
893
897
|
holidays: { "var(--g-weekend-highlight-color)": "weekend" },
|
|
894
898
|
ignore: [],
|
|
899
|
+
isRTL: !1,
|
|
895
900
|
language: "en",
|
|
896
901
|
lines: "both",
|
|
897
902
|
move_dependencies: !0,
|
|
@@ -926,7 +931,7 @@ const y = [
|
|
|
926
931
|
};
|
|
927
932
|
class j {
|
|
928
933
|
constructor(t, e, i) {
|
|
929
|
-
this.setup_wrapper(t), this.setup_options(i), this.setup_tasks(e), this.change_view_mode(), this.bind_events();
|
|
934
|
+
this.setup_wrapper(t), this.setup_options(i), this.apply_rtl_direction(), this.setup_tasks(e), this.change_view_mode(), this.bind_events();
|
|
930
935
|
}
|
|
931
936
|
setup_wrapper(t) {
|
|
932
937
|
let e, i;
|
|
@@ -957,6 +962,9 @@ class j {
|
|
|
957
962
|
append_to: this.$container
|
|
958
963
|
});
|
|
959
964
|
}
|
|
965
|
+
apply_rtl_direction() {
|
|
966
|
+
this.options.isRTL && (this.$container.style.direction = "ltr");
|
|
967
|
+
}
|
|
960
968
|
setup_options(t) {
|
|
961
969
|
this.original_options = t, t != null && t.view_modes && (t.view_modes = t.view_modes.map((i) => {
|
|
962
970
|
if (typeof i == "string") {
|
|
@@ -999,7 +1007,7 @@ class j {
|
|
|
999
1007
|
this.config.ignored_function = this.options.ignore;
|
|
1000
1008
|
}
|
|
1001
1009
|
update_options(t) {
|
|
1002
|
-
this.setup_options({ ...this.original_options, ...t }), this.change_view_mode(void 0, !0);
|
|
1010
|
+
this.setup_options({ ...this.original_options, ...t }), this.apply_rtl_direction(), this.change_view_mode(void 0, !0);
|
|
1003
1011
|
}
|
|
1004
1012
|
setup_tasks(t) {
|
|
1005
1013
|
this.tasks = t.map((e, i) => {
|
package/dist/frappe-gantt.umd.js
CHANGED
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
L ${s} ${n}
|
|
17
17
|
m -5 -5
|
|
18
18
|
l 5 5
|
|
19
|
-
l -5 5`}}draw(){this.element=f("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:this.is_critical?"arrow-critical":""})}update(){this.calculate_path(),this.element.setAttribute("d",this.path)}}class q{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=f("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=f("g",{class:"bar-group",append_to:this.group}),this.handle_group=f("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}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(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon()}draw_bar(){this.$bar=f("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.task.color&&(this.$bar.style.fill=this.task.color),E(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=f("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}),E(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=f("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=c.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${this.task.id}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),E(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<e),0)*this.gantt.config.column_width;let s=(t-i)*this.task.progress/100;const n=this.x+s,o=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<n),0)*this.gantt.config.column_width;s+=o;let a=this.gantt.get_ignored_region(this.x+s);for(;a.length;)s+=this.gantt.config.column_width,a=this.gantt.get_ignored_region(this.x+s);return this.progress_width=s,s}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),this.$bar_label=f("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,s;i=f("defs",{append_to:this.bar_group}),f("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),s=f("clipPath",{id:"clip_"+this.task.id,append_to:i}),f("use",{href:"#rect_"+this.task.id,append_to:s}),f("image",{x:this.x+t,y:this.y+e,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_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const s=this.y+(this.height-20)/2;this.$add_icon_group=f("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=f("circle",{cx:i+20/2,cy:s+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=f("line",{x1:i+20/2,y1:s+5,x2:i+20/2,y2:s+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=f("line",{x1:i+5,y1:s+20/2,x2:i+20-5,y2:s+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"click",n=>{n.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",n=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),n.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=3;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(f("rect",{x:t.getEndX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(f("rect",{x:t.getX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=f("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}bind(){this.invalid||this.setup_click_event()}setup_click_event(){let t=this.task.id;u.on(this.group,"mouseover",s=>{this.gantt.trigger_event("hover",[this.task,s.screenX,s.screenY,s])}),this.gantt.options.popup_on==="click"&&u.on(this.group,"mouseup",s=>{const n=s.offsetX||s.layerX;if(this.$handle_progress){const o=+this.$handle_progress.getAttribute("cx");if(o>n-1&&o<n+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:s.offsetX||s.layerX,y:s.offsetY||s.layerY,task:this.task,target:this.$bar})});let e;u.on(this.group,"mouseenter",s=>{e=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:s.offsetX||s.layerX,y:s.offsetY||s.layerY,task:this.task,target:this.$bar}),this.gantt.$container.querySelector(`.highlight-${t}`).classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))}),u.on(this.group,"mouseleave",()=>{var s,n;clearTimeout(e),this.gantt.options.popup_on==="hover"&&((n=(s=this.gantt.popup)==null?void 0:s.hide)==null||n.call(s)),this.gantt.$container.querySelector(`.highlight-${t}`).classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))}),u.on(this.group,"mousedown",()=>{this.is_dragging=!0,this.hide_add_icon()}),u.on(this.group,"click",()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])}),u.on(this.group,"dblclick",s=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))});let i=!1;u.on(this.group,"touchstart",s=>{if(!i)return i=!0,setTimeout(function(){i=!1},300),!1;s.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;if(t){if(!this.validate_dependency_constraints(t,e))return;this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"}e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position()}validate_dependency_constraints(t,e=null){const i=this.task.dependencies_type||this.gantt.options.dependencies_type;if(i==="fixed")return this.task.dependencies.map(_=>this.gantt.get_bar(_).$bar.getX()).reduce((_,l)=>_&&t>=l,!0);const s=t/this.gantt.config.column_width,n=c.add(this.gantt.gantt_start,s*this.gantt.config.step,this.gantt.config.unit),a=(e||this.$bar.getWidth())/this.gantt.config.column_width,h=c.add(n,a*this.gantt.config.step,this.gantt.config.unit);for(const d of this.task.dependencies){const _=this.gantt.get_bar(d);if(!_)continue;const l=_.task;switch(i){case"finish-to-start":if(n<l._end)return!1;break;case"start-to-start":if(n<l._start)return!1;break;case"finish-to-finish":if(h<l._end)return!1;break;case"start-to-finish":if(h<l._start)return!1;break}}return!0}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,s=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img")||"",o=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),h=s.getX()+t,d=n&&n.getX()+t||0,_=n&&n.getBBox().width+7||7,l=h+s.getBBox().width+7,p=e+i.clientWidth/2;s.classList.contains("big")||(l<a&&t>0&&l<p||h-_>this.$bar.getX()&&t<0&&l>p)&&(s.setAttribute("x",h),n&&(n.setAttribute("x",d),o.setAttribute("x",d)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,c.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,1e3),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=c.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const s=t.getWidth()/this.gantt.config.column_width,n=c.add(i,s*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:n}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((s,n)=>s+(n>=this.x&&n<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=c.diff(c.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let n=c.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=n}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(s=>s.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=c.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=c.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),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.config.column_width*this.actual_duration_raw*(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.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img");let n=5,o=this.image_size+10;const a=i.getBBox().width,h=e.getWidth();a>h?(i.classList.add("big"),s?(s.setAttribute("x",e.getEndX()+n),t.setAttribute("x",e.getEndX()+n),i.setAttribute("x",e.getEndX()+o)):i.setAttribute("x",e.getEndX()+n)):(i.classList.remove("big"),s?(s.setAttribute("x",e.getX()+n),t.setAttribute("x",e.getX()+n),i.setAttribute("x",e.getX()+h/2+o)):i.setAttribute("x",e.getX()+h/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()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const s=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",s+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",s+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",s+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",s+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",s+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class F{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
|
|
19
|
+
l -5 5`}}draw(){this.element=f("path",{d:this.path,"data-from":this.from_task.task.id,"data-to":this.to_task.task.id,class:this.is_critical?"arrow-critical":""})}update(){this.calculate_path(),this.element.setAttribute("d",this.path)}}class q{constructor(t,e){this.set_defaults(t,e),this.prepare_wrappers(),this.prepare_helpers(),this.refresh()}refresh(){this.bar_group.innerHTML="",this.handle_group.innerHTML="",this.task.custom_class?this.group.classList.add(this.task.custom_class):this.group.classList=["bar-wrapper"],this.prepare_values(),this.draw(),this.bind()}set_defaults(t,e){this.action_completed=!1,this.gantt=t,this.task=e,this.name=this.name||"",this.is_dragging=!1,this.is_hovering_bar=!1,this.is_hovering_icon=!1,this.add_icon_hide_timeout=null}prepare_wrappers(){this.group=f("g",{class:"bar-wrapper"+(this.task.custom_class?" "+this.task.custom_class:""),"data-id":this.task.id}),this.bar_group=f("g",{class:"bar-group",append_to:this.group}),this.handle_group=f("g",{class:"handle-group",append_to:this.group})}prepare_values(){this.invalid=this.task.invalid,this.height=this.gantt.options.bar_height,this.image_size=this.height-5,(!this.task._start||!(this.task._start instanceof Date))&&(this.task._start=new Date(this.task.start)),(!this.task._end||!(this.task._end instanceof Date))&&(this.task._end=new Date(this.task.end)),this.compute_x(),this.compute_y(),this.compute_duration(),this.corner_radius=this.gantt.options.bar_corner_radius,this.width=this.gantt.config.column_width*this.duration,(!this.task.progress||this.task.progress<0)&&(this.task.progress=0),this.task.progress>100&&(this.task.progress=100)}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(),this.gantt.options.task_add_icon_position&&this.draw_add_task_icon()}draw_bar(){this.$bar=f("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.task.color&&(this.$bar.style.fill=this.task.color),E(this.$bar,"width",0,this.width),this.invalid&&this.$bar.classList.add("bar-invalid")}draw_expected_progress_bar(){this.invalid||(this.$expected_bar_progress=f("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}),E(this.$expected_bar_progress,"width",0,this.expected_progress_width))}draw_progress_bar(){if(this.invalid)return;this.progress_width=this.calculate_progress_width();let t=this.corner_radius;/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(t=this.corner_radius+2),this.$bar_progress=f("rect",{x:this.x,y:this.y,width:this.progress_width,height:this.height,rx:t,ry:t,class:"bar-progress",append_to:this.bar_group}),this.task.color_progress&&(this.$bar_progress.style.fill=this.task.color_progress);const e=c.diff(this.task._start,this.gantt.gantt_start,this.gantt.config.unit)/this.gantt.config.step*this.gantt.config.column_width;let i=this.gantt.create_el({classes:`date-range-highlight hide highlight-${this.task.id}`,width:this.width,left:e});this.$date_highlight=i,this.gantt.$lower_header.prepend(this.$date_highlight),E(this.$bar_progress,"width",0,this.progress_width)}calculate_progress_width(){const t=this.$bar.getWidth(),e=this.x+t,i=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<e),0)*this.gantt.config.column_width;let s=(t-i)*this.task.progress/100;const n=this.x+s,o=this.gantt.config.ignored_positions.reduce((h,d)=>h+(d>=this.x&&d<n),0)*this.gantt.config.column_width;s+=o;let a=this.gantt.get_ignored_region(this.x+s);for(;a.length;)s+=this.gantt.config.column_width,a=this.gantt.get_ignored_region(this.x+s);return this.progress_width=s,s}draw_label(){let t=this.x+this.$bar.getWidth()/2;this.task.thumbnail&&(t=this.x+this.image_size+5),this.$bar_label=f("text",{x:t,y:this.y+this.height/2,innerHTML:this.task.name,class:"bar-label",append_to:this.bar_group}),this.task.color_text&&(this.$bar_label.style.fill=this.task.color_text),requestAnimationFrame(()=>this.update_label_position())}draw_thumbnail(){let t=10,e=2,i,s;i=f("defs",{append_to:this.bar_group}),f("rect",{id:"rect_"+this.task.id,x:this.x+t,y:this.y+e,width:this.image_size,height:this.image_size,rx:"15",class:"img_mask",append_to:i}),s=f("clipPath",{id:"clip_"+this.task.id,append_to:i}),f("use",{href:"#rect_"+this.task.id,append_to:s}),f("image",{x:this.x+t,y:this.y+e,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_add_task_icon(){this.icon_size=20,this.icon_padding=5;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-20-5;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+5;else return;const s=this.y+(this.height-20)/2;this.$add_icon_group=f("g",{class:"add-task-icon hide",append_to:this.handle_group}),this.$add_icon_circle=f("circle",{cx:i+20/2,cy:s+20/2,r:20/2,class:"add-task-icon-bg",append_to:this.$add_icon_group}),this.$add_icon_vertical=f("line",{x1:i+20/2,y1:s+5,x2:i+20/2,y2:s+20-5,class:"add-task-icon-plus",append_to:this.$add_icon_group}),this.$add_icon_horizontal=f("line",{x1:i+5,y1:s+20/2,x2:i+20-5,y2:s+20/2,class:"add-task-icon-plus",append_to:this.$add_icon_group}),u.on(this.$add_icon_group,"mousedown",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"mouseup",n=>{n.stopPropagation()}),u.on(this.$add_icon_group,"click",n=>{n.stopPropagation(),this.gantt.trigger_event("task_add",[this.task])}),u.on(this.$add_icon_group,"mouseenter",n=>{this.is_hovering_icon=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.$add_icon_group.classList.add("active"),this.$add_icon_group.classList.remove("hide"),n.stopPropagation()}),u.on(this.$add_icon_group,"mouseleave",()=>{this.is_hovering_icon=!1,this.$add_icon_group.classList.remove("active"),this.is_hovering_bar||this.$add_icon_group.classList.add("hide")})}draw_resize_handles(){if(this.invalid||this.gantt.options.readonly)return;const t=this.$bar,e=3;if(this.handles=[],this.gantt.options.readonly_dates||(this.handles.push(f("rect",{x:t.getEndX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle right",append_to:this.handle_group})),this.handles.push(f("rect",{x:t.getX()-e/2,y:t.getY()+this.height/4,width:e,height:this.height/2,rx:2,ry:2,class:"handle left",append_to:this.handle_group}))),!this.gantt.options.readonly_progress){const i=this.$bar_progress;this.$handle_progress=f("circle",{cx:i.getEndX(),cy:i.getY()+i.getHeight()/2,r:4.5,class:"handle progress",append_to:this.handle_group}),this.handles.push(this.$handle_progress)}for(let i of this.handles)u.on(i,"mouseenter",()=>i.classList.add("active")),u.on(i,"mouseleave",()=>i.classList.remove("active"))}bind(){this.invalid||this.setup_click_event()}setup_click_event(){let t=this.task.id;u.on(this.group,"mouseover",s=>{this.gantt.trigger_event("hover",[this.task,s.screenX,s.screenY,s])}),this.gantt.options.popup_on==="click"&&u.on(this.group,"mouseup",s=>{const n=s.offsetX||s.layerX;if(this.$handle_progress){const o=+this.$handle_progress.getAttribute("cx");if(o>n-1&&o<n+1||this.gantt.bar_being_dragged)return}this.gantt.show_popup({x:s.offsetX||s.layerX,y:s.offsetY||s.layerY,task:this.task,target:this.$bar})});let e;u.on(this.group,"mouseenter",s=>{e=setTimeout(()=>{this.gantt.options.popup_on==="hover"&&this.gantt.show_popup({x:s.offsetX||s.layerX,y:s.offsetY||s.layerY,task:this.task,target:this.$bar}),this.gantt.$container.querySelector(`.highlight-${t}`).classList.remove("hide")},200),this.$add_icon_group&&(this.is_hovering_bar=!0,this.add_icon_hide_timeout&&(clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=null),this.is_dragging||this.$add_icon_group.classList.remove("hide"))}),u.on(this.group,"mouseleave",()=>{var s,n;clearTimeout(e),this.gantt.options.popup_on==="hover"&&((n=(s=this.gantt.popup)==null?void 0:s.hide)==null||n.call(s)),this.gantt.$container.querySelector(`.highlight-${t}`).classList.add("hide"),this.$add_icon_group&&(this.is_hovering_bar=!1,this.add_icon_hide_timeout&&clearTimeout(this.add_icon_hide_timeout),this.add_icon_hide_timeout=setTimeout(()=>{this.is_hovering_icon||this.$add_icon_group.classList.add("hide")},200))}),u.on(this.group,"mousedown",()=>{this.is_dragging=!0,this.hide_add_icon()}),u.on(this.group,"mouseup",()=>{setTimeout(()=>{this.gantt.bar_being_dragged!==!0&&(this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide"))},0)}),u.on(this.group,"click",()=>{this.action_completed||this.gantt.bar_being_dragged||this.gantt.trigger_event("click",[this.task])}),u.on(this.group,"dblclick",s=>{this.action_completed||(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))});let i=!1;u.on(this.group,"touchstart",s=>{if(!i)return i=!0,setTimeout(function(){i=!1},300),!1;s.preventDefault(),!this.action_completed&&(this.group.classList.remove("active"),this.gantt.popup&&this.gantt.popup.parent.classList.remove("hide"),this.gantt.trigger_event("double_click",[this.task]))})}update_bar_position({x:t=null,width:e=null}){const i=this.$bar;if(t){if(!this.validate_dependency_constraints(t,e))return;this.update_attr(i,"x",t),this.x=t,this.$date_highlight.style.left=t+"px"}e>0&&(this.update_attr(i,"width",e),this.$date_highlight.style.width=e+"px"),this.update_label_position(),this.update_handle_position(),this.update_add_icon_position(),this.date_changed(),this.compute_duration(),this.gantt.options.show_expected_progress&&this.update_expected_progressbar_position(),this.update_progressbar_position(),this.update_arrow_position()}validate_dependency_constraints(t,e=null){const i=this.task.dependencies_type||this.gantt.options.dependencies_type;if(i==="fixed")return this.task.dependencies.map(_=>this.gantt.get_bar(_).$bar.getX()).reduce((_,l)=>_&&t>=l,!0);const s=t/this.gantt.config.column_width,n=c.add(this.gantt.gantt_start,s*this.gantt.config.step,this.gantt.config.unit),a=(e||this.$bar.getWidth())/this.gantt.config.column_width,h=c.add(n,a*this.gantt.config.step,this.gantt.config.unit);for(const d of this.task.dependencies){const _=this.gantt.get_bar(d);if(!_)continue;const l=_.task;switch(i){case"finish-to-start":if(n<l._end)return!1;break;case"start-to-start":if(n<l._start)return!1;break;case"finish-to-finish":if(h<l._end)return!1;break;case"start-to-finish":if(h<l._start)return!1;break}}return!0}update_label_position_on_horizontal_scroll({x:t,sx:e}){const i=this.gantt.$container,s=this.group.querySelector(".bar-label"),n=this.group.querySelector(".bar-img")||"",o=this.bar_group.querySelector(".img_mask")||"";let a=this.$bar.getX()+this.$bar.getWidth(),h=s.getX()+t,d=n&&n.getX()+t||0,_=n&&n.getBBox().width+7||7,l=h+s.getBBox().width+7,p=e+i.clientWidth/2;s.classList.contains("big")||(l<a&&t>0&&l<p||h-_>this.$bar.getX()&&t<0&&l>p)&&(s.setAttribute("x",h),n&&(n.setAttribute("x",d),o.setAttribute("x",d)))}date_changed(){let t=!1;const{new_start_date:e,new_end_date:i}=this.compute_start_end_date();Number(this.task._start)!==Number(e)&&(t=!0,this.task._start=e),Number(this.task._end)!==Number(i)&&(t=!0,this.task._end=i),t&&this.gantt.trigger_event("date_change",[this.task,e,c.add(i,-1,"second")])}progress_changed(){this.task.progress=this.compute_progress(),this.gantt.trigger_event("progress_change",[this.task,this.task.progress])}set_action_completed(){this.action_completed=!0,setTimeout(()=>this.action_completed=!1,1e3),this.is_dragging=!1,this.$add_icon_group&&this.is_hovering_bar&&this.$add_icon_group.classList.remove("hide")}compute_start_end_date(){const t=this.$bar,e=t.getX()/this.gantt.config.column_width;let i=c.add(this.gantt.gantt_start,e*this.gantt.config.step,this.gantt.config.unit);const s=t.getWidth()/this.gantt.config.column_width,n=c.add(i,s*this.gantt.config.step,this.gantt.config.unit);return{new_start_date:i,new_end_date:n}}compute_progress(){this.progress_width=this.$bar_progress.getWidth(),this.x=this.$bar_progress.getBBox().x;const t=this.x+this.progress_width,e=this.progress_width-this.gantt.config.ignored_positions.reduce((s,n)=>s+(n>=this.x&&n<=t),0)*this.gantt.config.column_width;if(e<0)return 0;const i=this.$bar.getWidth()-this.ignored_duration_raw*this.gantt.config.column_width;return parseInt(e/i*100,10)}compute_expected_progress(){this.expected_progress=c.diff(c.today(),this.task._start,"hour")/this.gantt.config.step,this.expected_progress=(this.expected_progress<this.duration?this.expected_progress:this.duration)*100/this.duration}compute_x(){const{column_width:t}=this.gantt.config,e=this.task._start,i=this.gantt.gantt_start;let n=c.diff(e,i,this.gantt.config.unit)/this.gantt.config.step*t;this.x=n}compute_y(){this.y=this.gantt.config.header_height+this.gantt.options.padding/2+this.task._index*(this.height+this.gantt.options.padding)}compute_duration(){let t=0,e=0;for(let i=new Date(this.task._start);i<this.task._end;i.setDate(i.getDate()+1))e++,!this.gantt.config.ignored_dates.find(s=>s.getTime()===i.getTime())&&(!this.gantt.config.ignored_function||!this.gantt.config.ignored_function(i))&&t++;this.task.actual_duration=t,this.task.ignored_duration=e-t,this.duration=c.convert_scales(e+"d",this.gantt.config.unit)/this.gantt.config.step,this.actual_duration_raw=c.convert_scales(t+"d",this.gantt.config.unit)/this.gantt.config.step,this.ignored_duration_raw=this.duration-this.actual_duration_raw}update_attr(t,e,i){return i=+i,isNaN(i)||t.setAttribute(e,i),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.config.column_width*this.actual_duration_raw*(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.calculate_progress_width()))}update_label_position(){const t=this.bar_group.querySelector(".img_mask")||"",e=this.$bar,i=this.group.querySelector(".bar-label"),s=this.group.querySelector(".bar-img");let n=5,o=this.image_size+10;const a=i.getBBox().width,h=e.getWidth();a>h?(i.classList.add("big"),s?(s.setAttribute("x",e.getEndX()+n),t.setAttribute("x",e.getEndX()+n),i.setAttribute("x",e.getEndX()+o)):i.setAttribute("x",e.getEndX()+n)):(i.classList.remove("big"),s?(s.setAttribute("x",e.getX()+n),t.setAttribute("x",e.getX()+n),i.setAttribute("x",e.getX()+h/2+o)):i.setAttribute("x",e.getX()+h/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()),this.handle_group.querySelector(".handle.right").setAttribute("x",t.getEndX());const e=this.group.querySelector(".handle.progress");e&&e.setAttribute("cx",this.$bar_progress.getEndX())}update_add_icon_position(){if(!this.$add_icon_group)return;const t=this.icon_size,e=this.icon_padding;let i;if(this.gantt.options.task_add_icon_position==="before")i=this.x-t-e;else if(this.gantt.options.task_add_icon_position==="after")i=this.x+this.$bar.getWidth()+e;else return;const s=this.y+(this.height-t)/2;this.$add_icon_circle.setAttribute("cx",i+t/2),this.$add_icon_circle.setAttribute("cy",s+t/2),this.$add_icon_vertical.setAttribute("x1",i+t/2),this.$add_icon_vertical.setAttribute("y1",s+5),this.$add_icon_vertical.setAttribute("x2",i+t/2),this.$add_icon_vertical.setAttribute("y2",s+t-5),this.$add_icon_horizontal.setAttribute("x1",i+5),this.$add_icon_horizontal.setAttribute("y1",s+t/2),this.$add_icon_horizontal.setAttribute("x2",i+t-5),this.$add_icon_horizontal.setAttribute("y2",s+t/2)}hide_add_icon(){this.$add_icon_group&&this.$add_icon_group.classList.add("hide")}update_arrow_position(){this.arrows=this.arrows||[];for(let t of this.arrows)t.update()}}class F{constructor(t,e,i){this.parent=t,this.popup_func=e,this.gantt=i,this.make()}make(){this.parent.innerHTML=`
|
|
20
20
|
<div class="title"></div>
|
|
21
21
|
<div class="subtitle"></div>
|
|
22
22
|
<div class="details"></div>
|
|
23
23
|
<div class="actions"></div>
|
|
24
|
-
`,this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.details=this.parent.querySelector(".details"),this.actions=this.parent.querySelector(".actions")}show({x:t,y:e,task:i,target:s}){this.actions.innerHTML="";let n=this.popup_func({task:i,chart:this.gantt,get_title:()=>this.title,set_title:o=>this.title.innerHTML=o,get_subtitle:()=>this.subtitle,set_subtitle:o=>this.subtitle.innerHTML=o,get_details:()=>this.details,set_details:o=>this.details.innerHTML=o,add_action:(o,a)=>{let h=this.gantt.create_el({classes:"action-btn",type:"button",append_to:this.actions});typeof o=="function"&&(o=o(i)),h.innerHTML=o,h.onclick=d=>a(i,this.gantt,d)}});n!==!1&&(n&&(this.parent.innerHTML=n),this.actions.innerHTML===""?this.actions.remove():this.parent.appendChild(this.actions),this.parent.style.left=t+10+"px",this.parent.style.top=e-10+"px",this.parent.classList.remove("hide"))}hide(){this.parent.classList.add("hide")}}function S(r){const t=r.getFullYear();return t-t%10+""}function O(r,t,e){let i=c.add(r,6,"day"),s=i.getMonth()!==r.getMonth()?"D MMM":"D",n=!t||r.getMonth()!==t.getMonth()?"D MMM":"D";return`${c.format(r,n,e)} - ${c.format(i,s,e)}`}const w=[{name:"Hour",padding:"7d",step:"1h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D MMMM",e):"",upper_text_frequency:24},{name:"Quarter Day",padding:"7d",step:"6h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D MMM",e):"",upper_text_frequency:4},{name:"Half Day",padding:"14d",step:"12h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?r.getMonth()!==r.getMonth()?c.format(r,"D MMM",e):c.format(r,"D",e):"",upper_text_frequency:2},{name:"Day",padding:"7d",date_format:"YYYY-MM-DD",step:"1d",lower_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D",e):"",upper_text:(r,t,e)=>!t||r.getMonth()!==t.getMonth()?c.format(r,"MMMM",e):"",thick_line:r=>r.getDay()===1},{name:"Week",padding:"1m",step:"7d",date_format:"YYYY-MM-DD",column_width:140,lower_text:O,upper_text:(r,t,e)=>!t||r.getMonth()!==t.getMonth()?c.format(r,"MMMM",e):"",thick_line:r=>r.getDate()>=1&&r.getDate()<=7,upper_text_frequency:4},{name:"Month",padding:"2m",step:"1m",column_width:120,date_format:"YYYY-MM",lower_text:"MMMM",upper_text:(r,t,e)=>!t||r.getFullYear()!==t.getFullYear()?c.format(r,"YYYY",e):"",thick_line:r=>r.getMonth()%3===0,snap_at:"7d"},{name:"Year",padding:"2y",step:"1y",column_width:120,date_format:"YYYY",upper_text:(r,t,e)=>!t||S(r)!==S(t)?S(r):"",lower_text:"YYYY",snap_at:"30d"}],I={arrow_curve:5,auto_move_label:!1,bar_corner_radius:3,bar_height:30,container_height:"auto",column_width:null,critical_path:!1,date_format:"YYYY-MM-DD HH:mm",dependencies_type:"fixed",upper_header_height:45,lower_header_height:30,snap_at:null,infinite_padding:!0,holidays:{"var(--g-weekend-highlight-color)":"weekend"},ignore:[],language:"en",lines:"both",move_dependencies:!0,padding:18,popup:r=>{r.set_title(r.task.name),r.task.description?r.set_subtitle(r.task.description):r.set_subtitle("");const t=c.format(r.task._start,"MMM D",r.chart.options.language),e=c.format(c.add(r.task._end,-1,"second"),"MMM D",r.chart.options.language);r.set_details(`${t} - ${e} (${r.task.actual_duration} days${r.task.ignored_duration?" + "+r.task.ignored_duration+" excluded":""})<br/>Progress: ${Math.floor(r.task.progress*100)/100}%`)},popup_on:"click",readonly_progress:!1,readonly_dates:!1,readonly:!1,scroll_to:"today",show_expected_progress:!1,task_add_icon_position:null,today_button:!0,view_mode:"Day",view_mode_select:!1,view_modes:w,is_weekend:r=>r.getDay()===0||r.getDay()===6};class X{constructor(t,e,i){this.setup_wrapper(t),this.setup_options(i),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,i;if(typeof t=="string"){let s=document.querySelector(t);if(!s)throw new ReferenceError(`CSS selector "${t}" could not be found in DOM`);t=s}if(t instanceof HTMLElement)i=t,e=t.querySelector("svg");else if(t instanceof SVGElement)e=t;else throw new TypeError("Frappe Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=f("svg",{append_to:i,class:"gantt"}),this.$container=this.create_el({classes:"gantt-container",append_to:this.$svg.parentElement}),this.$container.appendChild(this.$svg),this.$popup_wrapper=this.create_el({classes:"popup-wrapper",append_to:this.$container})}setup_options(t){this.original_options=t,t!=null&&t.view_modes&&(t.view_modes=t.view_modes.map(i=>{if(typeof i=="string"){const s=w.find(n=>n.name===i);return s||console.error(`The view mode "${i}" is not predefined in Frappe Gantt. Please define the view mode object instead.`),s}return i}),t.view_mode=t.view_modes[0]),this.options={...I,...t};const e={"grid-height":"container_height","bar-height":"bar_height","lower-header-height":"lower_header_height","upper-header-height":"upper_header_height"};for(let i in e){let s=this.options[e[i]];s!=="auto"&&this.$container.style.setProperty("--gv-"+i,s+"px")}if(this.config={ignored_dates:[],ignored_positions:[],extend_by_units:10},typeof this.options.ignore!="function"){typeof this.options.ignore=="string"&&(this.options.ignore=[this.options.ignore]);for(let i of this.options.ignore){if(typeof i=="function"){this.config.ignored_function=i;continue}typeof i=="string"&&(i==="weekend"?this.config.ignored_function=s=>s.getDay()==6||s.getDay()==0:this.config.ignored_dates.push(new Date(i+" ")))}}else this.config.ignored_function=this.options.ignore}update_options(t){this.setup_options({...this.original_options,...t}),this.change_view_mode(void 0,!0)}setup_tasks(t){this.tasks=t.map((e,i)=>{if(!e.start)return console.error(`task "${e.id}" doesn't have a start date`),!1;if(e._start=c.parse(e.start),e.end===void 0&&e.duration!==void 0&&(e.end=e._start,e.duration.split(" ").forEach(a=>{let{duration:h,scale:d}=c.parse_duration(a);e.end=c.add(e.end,h,d)})),!e.end)return console.error(`task "${e.id}" doesn't have an end date`),!1;if(e._end=c.parse(e.end),c.diff(e._end,e._start,"year")<0)return console.error(`start of task can't be after end of task: in task "${e.id}"`),!1;if(c.diff(e._end,e._start,"year")>10)return console.error(`the duration of task "${e.id}" is too long (above ten years)`),!1;if(e._index=i,c.get_date_values(e._end).slice(3).every(o=>o===0)&&(e._end=c.add(e._end,24,"hour")),typeof e.dependencies=="string"||!e.dependencies){let o=[];e.dependencies&&(o=e.dependencies.split(",").map(a=>a.trim().replaceAll(" ","_")).filter(a=>a)),e.dependencies=o}return e.id?typeof e.id=="string"?e.id=e.id.replaceAll(" ","_"):e.id=`${e.id}`:e.id=j(e),e}).filter(e=>e),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()}update_task(t,e){let i=this.tasks.find(n=>n.id===t),s=this.bars[i._index];Object.assign(i,e),s.refresh()}change_view_mode(t=this.options.view_mode,e=!1){typeof t=="string"&&(t=this.options.view_modes.find(n=>n.name===t));let i,s;e&&(i=this.$container.scrollLeft,s=this.options.scroll_to,this.options.scroll_to=null),this.options.view_mode=t.name,this.config.view_mode=t,this.update_view_scale(t),this.setup_dates(e),this.render(),e&&(this.$container.scrollLeft=i,this.options.scroll_to=s),this.trigger_event("view_change",[t])}update_view_scale(t){let{duration:e,scale:i}=c.parse_duration(t.step);this.config.step=e,this.config.unit=i,this.config.column_width=this.options.column_width||t.column_width||45,this.$container.style.setProperty("--gv-column-width",this.config.column_width+"px"),this.config.header_height=this.options.lower_header_height+this.options.upper_header_height+10}setup_dates(t=!1){this.setup_gantt_dates(t),this.setup_date_values()}setup_gantt_dates(t){let e,i;this.tasks.length||(e=new Date,i=new Date);for(let s of this.tasks)(!e||s._start<e)&&(e=s._start),(!i||s._end>i)&&(i=s._end);if(e=c.start_of(e,this.config.unit),i=c.start_of(i,this.config.unit),!t)if(this.options.infinite_padding)this.gantt_start=c.add(e,-this.config.extend_by_units*3,this.config.unit),this.gantt_end=c.add(i,this.config.extend_by_units*3,this.config.unit);else{typeof this.config.view_mode.padding=="string"&&(this.config.view_mode.padding=[this.config.view_mode.padding,this.config.view_mode.padding]);let[s,n]=this.config.view_mode.padding.map(c.parse_duration);this.gantt_start=c.add(e,-s.duration,s.scale),this.gantt_end=c.add(i,n.duration,n.scale)}this.config.date_format=this.config.view_mode.date_format||this.options.date_format,this.gantt_start.setHours(0,0,0,0)}setup_date_values(){let t=this.gantt_start;for(this.dates=[t];t<this.gantt_end;)t=c.add(t,this.config.step,this.config.unit),this.dates.push(t)}bind_events(){this.bind_grid_click(),this.bind_holiday_labels(),this.bind_bar_events()}render(){this.clear(),this.setup_layers(),this.make_grid(),this.make_dates(),this.make_grid_extras(),this.make_bars(),this.make_arrows(),this.map_arrows_on_bars(),this.set_dimensions(),this.set_scroll_position(this.options.scroll_to)}setup_layers(){this.layers={};const t=["grid","arrow","progress","bar"];for(let e of t)this.layers[e]=f("g",{class:e,append_to:this.$svg});this.$extras=this.create_el({classes:"extras",append_to:this.$container}),this.$adjust=this.create_el({classes:"adjust hide",append_to:this.$extras,type:"button"}),this.$adjust.innerHTML="←"}make_grid(){this.make_grid_background(),this.make_grid_rows(),this.make_grid_header(),this.make_side_header()}make_grid_extras(){this.make_grid_highlights(),this.make_grid_ticks()}make_grid_background(){const t=this.dates.length*this.config.column_width,e=Math.max(this.config.header_height+this.options.padding+(this.options.bar_height+this.options.padding)*this.tasks.length-10,this.options.container_height!=="auto"?this.options.container_height:0);f("rect",{x:0,y:0,width:t,height:e,class:"grid-background",append_to:this.$svg}),u.attr(this.$svg,{height:e,width:"100%"}),this.grid_height=e,this.options.container_height==="auto"&&(this.$container.style.height=e+"px")}make_grid_rows(){const t=f("g",{append_to:this.layers.grid}),e=this.dates.length*this.config.column_width,i=this.options.bar_height+this.options.padding;this.config.header_height;for(let s=this.config.header_height;s<this.grid_height;s+=i)f("rect",{x:0,y:s,width:e,height:i,class:"grid-row",append_to:t})}make_grid_header(){this.$header=this.create_el({width:this.dates.length*this.config.column_width,classes:"grid-header",append_to:this.$container}),this.$upper_header=this.create_el({classes:"upper-header",append_to:this.$header}),this.$lower_header=this.create_el({classes:"lower-header",append_to:this.$header})}make_side_header(){if(this.$side_header=this.create_el({classes:"side-header"}),this.$upper_header.prepend(this.$side_header),this.options.view_mode_select){const t=document.createElement("select");t.classList.add("viewmode-select");const e=document.createElement("option");e.selected=!0,e.disabled=!0,e.textContent="Mode",t.appendChild(e);for(const i of this.options.view_modes){const s=document.createElement("option");s.value=i.name,s.textContent=i.name,i.name===this.config.view_mode.name&&(s.selected=!0),t.appendChild(s)}t.addEventListener("change",(function(){this.change_view_mode(t.value,!0)}).bind(this)),this.$side_header.appendChild(t)}if(this.options.today_button){let t=document.createElement("button");t.classList.add("today-button"),t.textContent="Today",t.onclick=this.scroll_current.bind(this),this.$side_header.prepend(t),this.$today_button=t}}make_grid_ticks(){if(this.options.lines==="none")return;let t=0,e=this.config.header_height,i=this.grid_height-this.config.header_height,s=f("g",{class:"lines_layer",append_to:this.layers.grid}),n=this.config.header_height;const o=this.dates.length*this.config.column_width,a=this.options.bar_height+this.options.padding;if(this.options.lines!=="vertical")for(let h=this.config.header_height;h<this.grid_height;h+=a)f("line",{x1:0,y1:n+a,x2:o,y2:n+a,class:"row-line",append_to:s}),n+=a;if(this.options.lines!=="horizontal")for(let h of this.dates){let d="tick";this.config.view_mode.thick_line&&this.config.view_mode.thick_line(h)&&(d+=" thick"),f("path",{d:`M ${t} ${e} v ${i}`,class:d,append_to:this.layers.grid}),this.view_is("month")?t+=c.get_days_in_month(h)*this.config.column_width/30:this.view_is("year")?t+=c.get_days_in_year(h)*this.config.column_width/365:t+=this.config.column_width}}highlight_holidays(){let t={};if(this.options.holidays)for(let e in this.options.holidays){let i=this.options.holidays[e];i==="weekend"&&(i=this.options.is_weekend);let s;if(typeof i=="object"){let n=i.find(o=>typeof o=="function");if(n&&(s=n),this.options.holidays.name){let o=new Date(i.date+" ");i=a=>o.getTime()===a.getTime(),t[o]=i.name}else i=o=>this.options.holidays[e].filter(a=>typeof a!="function").map(a=>{if(a.name){let h=new Date(a.date+" ");return t[h]=a.name,h.getTime()}return new Date(a+" ").getTime()}).includes(o.getTime())}for(let n=new Date(this.gantt_start);n<=this.gantt_end;n.setDate(n.getDate()+1))if(!(this.config.ignored_dates.find(o=>o.getTime()==n.getTime())||this.config.ignored_function&&this.config.ignored_function(n))&&(i(n)||s&&s(n))){const o=c.diff(n,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width,a=this.grid_height-this.config.header_height,h=c.format(n,"YYYY-MM-DD",this.options.language).replace(" ","_");if(t[n]){let d=this.create_el({classes:"holiday-label label_"+h,append_to:this.$extras});d.textContent=t[n]}f("rect",{x:Math.round(o),y:this.config.header_height,width:this.config.column_width/c.convert_scales(this.config.view_mode.step,"day"),height:a,class:"holiday-highlight "+h,style:`fill: ${e};`,append_to:this.layers.grid})}}}highlight_current(){const t=this.get_closest_date();if(!t)return;const[e,i]=t;i.classList.add("current-date-highlight");const n=c.diff(new Date,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width;this.$current_highlight=this.create_el({top:this.config.header_height,left:n,height:this.grid_height-this.config.header_height,classes:"current-highlight",append_to:this.$container}),this.$current_ball_highlight=this.create_el({top:this.config.header_height-6,left:n-2.5,width:6,height:6,classes:"current-ball-highlight",append_to:this.$header})}make_grid_highlights(){this.highlight_holidays(),this.config.ignored_positions=[];const t=(this.options.bar_height+this.options.padding)*this.tasks.length;this.layers.grid.innerHTML+=`<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
|
|
24
|
+
`,this.hide(),this.title=this.parent.querySelector(".title"),this.subtitle=this.parent.querySelector(".subtitle"),this.details=this.parent.querySelector(".details"),this.actions=this.parent.querySelector(".actions")}show({x:t,y:e,task:i,target:s}){this.actions.innerHTML="";let n=this.popup_func({task:i,chart:this.gantt,get_title:()=>this.title,set_title:o=>this.title.innerHTML=o,get_subtitle:()=>this.subtitle,set_subtitle:o=>this.subtitle.innerHTML=o,get_details:()=>this.details,set_details:o=>this.details.innerHTML=o,add_action:(o,a)=>{let h=this.gantt.create_el({classes:"action-btn",type:"button",append_to:this.actions});typeof o=="function"&&(o=o(i)),h.innerHTML=o,h.onclick=d=>a(i,this.gantt,d)}});n!==!1&&(n&&(this.parent.innerHTML=n),this.actions.innerHTML===""?this.actions.remove():this.parent.appendChild(this.actions),this.parent.style.left=t+10+"px",this.parent.style.top=e-10+"px",this.parent.classList.remove("hide"))}hide(){this.parent.classList.add("hide")}}function S(r){const t=r.getFullYear();return t-t%10+""}function O(r,t,e){let i=c.add(r,6,"day"),s=i.getMonth()!==r.getMonth()?"D MMM":"D",n=!t||r.getMonth()!==t.getMonth()?"D MMM":"D";return`${c.format(r,n,e)} - ${c.format(i,s,e)}`}const w=[{name:"Hour",padding:"7d",step:"1h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D MMMM",e):"",upper_text_frequency:24},{name:"Quarter Day",padding:"7d",step:"6h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D MMM",e):"",upper_text_frequency:4},{name:"Half Day",padding:"14d",step:"12h",date_format:"YYYY-MM-DD HH:",lower_text:"HH",upper_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?r.getMonth()!==r.getMonth()?c.format(r,"D MMM",e):c.format(r,"D",e):"",upper_text_frequency:2},{name:"Day",padding:"7d",date_format:"YYYY-MM-DD",step:"1d",lower_text:(r,t,e)=>!t||r.getDate()!==t.getDate()?c.format(r,"D",e):"",upper_text:(r,t,e)=>!t||r.getMonth()!==t.getMonth()?c.format(r,"MMMM",e):"",thick_line:r=>r.getDay()===1},{name:"Week",padding:"1m",step:"7d",date_format:"YYYY-MM-DD",column_width:140,lower_text:O,upper_text:(r,t,e)=>!t||r.getMonth()!==t.getMonth()?c.format(r,"MMMM",e):"",thick_line:r=>r.getDate()>=1&&r.getDate()<=7,upper_text_frequency:4},{name:"Month",padding:"2m",step:"1m",column_width:120,date_format:"YYYY-MM",lower_text:"MMMM",upper_text:(r,t,e)=>!t||r.getFullYear()!==t.getFullYear()?c.format(r,"YYYY",e):"",thick_line:r=>r.getMonth()%3===0,snap_at:"7d"},{name:"Year",padding:"2y",step:"1y",column_width:120,date_format:"YYYY",upper_text:(r,t,e)=>!t||S(r)!==S(t)?S(r):"",lower_text:"YYYY",snap_at:"30d"}],I={arrow_curve:5,auto_move_label:!1,bar_corner_radius:3,bar_height:30,container_height:"auto",column_width:null,critical_path:!1,date_format:"YYYY-MM-DD HH:mm",dependencies_type:"fixed",upper_header_height:45,lower_header_height:30,snap_at:null,infinite_padding:!0,holidays:{"var(--g-weekend-highlight-color)":"weekend"},ignore:[],isRTL:!1,language:"en",lines:"both",move_dependencies:!0,padding:18,popup:r=>{r.set_title(r.task.name),r.task.description?r.set_subtitle(r.task.description):r.set_subtitle("");const t=c.format(r.task._start,"MMM D",r.chart.options.language),e=c.format(c.add(r.task._end,-1,"second"),"MMM D",r.chart.options.language);r.set_details(`${t} - ${e} (${r.task.actual_duration} days${r.task.ignored_duration?" + "+r.task.ignored_duration+" excluded":""})<br/>Progress: ${Math.floor(r.task.progress*100)/100}%`)},popup_on:"click",readonly_progress:!1,readonly_dates:!1,readonly:!1,scroll_to:"today",show_expected_progress:!1,task_add_icon_position:null,today_button:!0,view_mode:"Day",view_mode_select:!1,view_modes:w,is_weekend:r=>r.getDay()===0||r.getDay()===6};class X{constructor(t,e,i){this.setup_wrapper(t),this.setup_options(i),this.apply_rtl_direction(),this.setup_tasks(e),this.change_view_mode(),this.bind_events()}setup_wrapper(t){let e,i;if(typeof t=="string"){let s=document.querySelector(t);if(!s)throw new ReferenceError(`CSS selector "${t}" could not be found in DOM`);t=s}if(t instanceof HTMLElement)i=t,e=t.querySelector("svg");else if(t instanceof SVGElement)e=t;else throw new TypeError("Frappe Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");e?(this.$svg=e,this.$svg.classList.add("gantt")):this.$svg=f("svg",{append_to:i,class:"gantt"}),this.$container=this.create_el({classes:"gantt-container",append_to:this.$svg.parentElement}),this.$container.appendChild(this.$svg),this.$popup_wrapper=this.create_el({classes:"popup-wrapper",append_to:this.$container})}apply_rtl_direction(){this.options.isRTL&&(this.$container.style.direction="ltr")}setup_options(t){this.original_options=t,t!=null&&t.view_modes&&(t.view_modes=t.view_modes.map(i=>{if(typeof i=="string"){const s=w.find(n=>n.name===i);return s||console.error(`The view mode "${i}" is not predefined in Frappe Gantt. Please define the view mode object instead.`),s}return i}),t.view_mode=t.view_modes[0]),this.options={...I,...t};const e={"grid-height":"container_height","bar-height":"bar_height","lower-header-height":"lower_header_height","upper-header-height":"upper_header_height"};for(let i in e){let s=this.options[e[i]];s!=="auto"&&this.$container.style.setProperty("--gv-"+i,s+"px")}if(this.config={ignored_dates:[],ignored_positions:[],extend_by_units:10},typeof this.options.ignore!="function"){typeof this.options.ignore=="string"&&(this.options.ignore=[this.options.ignore]);for(let i of this.options.ignore){if(typeof i=="function"){this.config.ignored_function=i;continue}typeof i=="string"&&(i==="weekend"?this.config.ignored_function=s=>s.getDay()==6||s.getDay()==0:this.config.ignored_dates.push(new Date(i+" ")))}}else this.config.ignored_function=this.options.ignore}update_options(t){this.setup_options({...this.original_options,...t}),this.apply_rtl_direction(),this.change_view_mode(void 0,!0)}setup_tasks(t){this.tasks=t.map((e,i)=>{if(!e.start)return console.error(`task "${e.id}" doesn't have a start date`),!1;if(e._start=c.parse(e.start),e.end===void 0&&e.duration!==void 0&&(e.end=e._start,e.duration.split(" ").forEach(a=>{let{duration:h,scale:d}=c.parse_duration(a);e.end=c.add(e.end,h,d)})),!e.end)return console.error(`task "${e.id}" doesn't have an end date`),!1;if(e._end=c.parse(e.end),c.diff(e._end,e._start,"year")<0)return console.error(`start of task can't be after end of task: in task "${e.id}"`),!1;if(c.diff(e._end,e._start,"year")>10)return console.error(`the duration of task "${e.id}" is too long (above ten years)`),!1;if(e._index=i,c.get_date_values(e._end).slice(3).every(o=>o===0)&&(e._end=c.add(e._end,24,"hour")),typeof e.dependencies=="string"||!e.dependencies){let o=[];e.dependencies&&(o=e.dependencies.split(",").map(a=>a.trim().replaceAll(" ","_")).filter(a=>a)),e.dependencies=o}return e.id?typeof e.id=="string"?e.id=e.id.replaceAll(" ","_"):e.id=`${e.id}`:e.id=j(e),e}).filter(e=>e),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()}update_task(t,e){let i=this.tasks.find(n=>n.id===t),s=this.bars[i._index];Object.assign(i,e),s.refresh()}change_view_mode(t=this.options.view_mode,e=!1){typeof t=="string"&&(t=this.options.view_modes.find(n=>n.name===t));let i,s;e&&(i=this.$container.scrollLeft,s=this.options.scroll_to,this.options.scroll_to=null),this.options.view_mode=t.name,this.config.view_mode=t,this.update_view_scale(t),this.setup_dates(e),this.render(),e&&(this.$container.scrollLeft=i,this.options.scroll_to=s),this.trigger_event("view_change",[t])}update_view_scale(t){let{duration:e,scale:i}=c.parse_duration(t.step);this.config.step=e,this.config.unit=i,this.config.column_width=this.options.column_width||t.column_width||45,this.$container.style.setProperty("--gv-column-width",this.config.column_width+"px"),this.config.header_height=this.options.lower_header_height+this.options.upper_header_height+10}setup_dates(t=!1){this.setup_gantt_dates(t),this.setup_date_values()}setup_gantt_dates(t){let e,i;this.tasks.length||(e=new Date,i=new Date);for(let s of this.tasks)(!e||s._start<e)&&(e=s._start),(!i||s._end>i)&&(i=s._end);if(e=c.start_of(e,this.config.unit),i=c.start_of(i,this.config.unit),!t)if(this.options.infinite_padding)this.gantt_start=c.add(e,-this.config.extend_by_units*3,this.config.unit),this.gantt_end=c.add(i,this.config.extend_by_units*3,this.config.unit);else{typeof this.config.view_mode.padding=="string"&&(this.config.view_mode.padding=[this.config.view_mode.padding,this.config.view_mode.padding]);let[s,n]=this.config.view_mode.padding.map(c.parse_duration);this.gantt_start=c.add(e,-s.duration,s.scale),this.gantt_end=c.add(i,n.duration,n.scale)}this.config.date_format=this.config.view_mode.date_format||this.options.date_format,this.gantt_start.setHours(0,0,0,0)}setup_date_values(){let t=this.gantt_start;for(this.dates=[t];t<this.gantt_end;)t=c.add(t,this.config.step,this.config.unit),this.dates.push(t)}bind_events(){this.bind_grid_click(),this.bind_holiday_labels(),this.bind_bar_events()}render(){this.clear(),this.setup_layers(),this.make_grid(),this.make_dates(),this.make_grid_extras(),this.make_bars(),this.make_arrows(),this.map_arrows_on_bars(),this.set_dimensions(),this.set_scroll_position(this.options.scroll_to)}setup_layers(){this.layers={};const t=["grid","arrow","progress","bar"];for(let e of t)this.layers[e]=f("g",{class:e,append_to:this.$svg});this.$extras=this.create_el({classes:"extras",append_to:this.$container}),this.$adjust=this.create_el({classes:"adjust hide",append_to:this.$extras,type:"button"}),this.$adjust.innerHTML="←"}make_grid(){this.make_grid_background(),this.make_grid_rows(),this.make_grid_header(),this.make_side_header()}make_grid_extras(){this.make_grid_highlights(),this.make_grid_ticks()}make_grid_background(){const t=this.dates.length*this.config.column_width,e=Math.max(this.config.header_height+this.options.padding+(this.options.bar_height+this.options.padding)*this.tasks.length-10,this.options.container_height!=="auto"?this.options.container_height:0);f("rect",{x:0,y:0,width:t,height:e,class:"grid-background",append_to:this.$svg}),u.attr(this.$svg,{height:e,width:"100%"}),this.grid_height=e,this.options.container_height==="auto"&&(this.$container.style.height=e+"px")}make_grid_rows(){const t=f("g",{append_to:this.layers.grid}),e=this.dates.length*this.config.column_width,i=this.options.bar_height+this.options.padding;this.config.header_height;for(let s=this.config.header_height;s<this.grid_height;s+=i)f("rect",{x:0,y:s,width:e,height:i,class:"grid-row",append_to:t})}make_grid_header(){this.$header=this.create_el({width:this.dates.length*this.config.column_width,classes:"grid-header",append_to:this.$container}),this.$upper_header=this.create_el({classes:"upper-header",append_to:this.$header}),this.$lower_header=this.create_el({classes:"lower-header",append_to:this.$header})}make_side_header(){if(this.$side_header=this.create_el({classes:"side-header"}),this.$upper_header.prepend(this.$side_header),this.options.view_mode_select){const t=document.createElement("select");t.classList.add("viewmode-select");const e=document.createElement("option");e.selected=!0,e.disabled=!0,e.textContent="Mode",t.appendChild(e);for(const i of this.options.view_modes){const s=document.createElement("option");s.value=i.name,s.textContent=i.name,i.name===this.config.view_mode.name&&(s.selected=!0),t.appendChild(s)}t.addEventListener("change",(function(){this.change_view_mode(t.value,!0)}).bind(this)),this.$side_header.appendChild(t)}if(this.options.today_button){let t=document.createElement("button");t.classList.add("today-button"),t.textContent="Today",t.onclick=this.scroll_current.bind(this),this.$side_header.prepend(t),this.$today_button=t}}make_grid_ticks(){if(this.options.lines==="none")return;let t=0,e=this.config.header_height,i=this.grid_height-this.config.header_height,s=f("g",{class:"lines_layer",append_to:this.layers.grid}),n=this.config.header_height;const o=this.dates.length*this.config.column_width,a=this.options.bar_height+this.options.padding;if(this.options.lines!=="vertical")for(let h=this.config.header_height;h<this.grid_height;h+=a)f("line",{x1:0,y1:n+a,x2:o,y2:n+a,class:"row-line",append_to:s}),n+=a;if(this.options.lines!=="horizontal")for(let h of this.dates){let d="tick";this.config.view_mode.thick_line&&this.config.view_mode.thick_line(h)&&(d+=" thick"),f("path",{d:`M ${t} ${e} v ${i}`,class:d,append_to:this.layers.grid}),this.view_is("month")?t+=c.get_days_in_month(h)*this.config.column_width/30:this.view_is("year")?t+=c.get_days_in_year(h)*this.config.column_width/365:t+=this.config.column_width}}highlight_holidays(){let t={};if(this.options.holidays)for(let e in this.options.holidays){let i=this.options.holidays[e];i==="weekend"&&(i=this.options.is_weekend);let s;if(typeof i=="object"){let n=i.find(o=>typeof o=="function");if(n&&(s=n),this.options.holidays.name){let o=new Date(i.date+" ");i=a=>o.getTime()===a.getTime(),t[o]=i.name}else i=o=>this.options.holidays[e].filter(a=>typeof a!="function").map(a=>{if(a.name){let h=new Date(a.date+" ");return t[h]=a.name,h.getTime()}return new Date(a+" ").getTime()}).includes(o.getTime())}for(let n=new Date(this.gantt_start);n<=this.gantt_end;n.setDate(n.getDate()+1))if(!(this.config.ignored_dates.find(o=>o.getTime()==n.getTime())||this.config.ignored_function&&this.config.ignored_function(n))&&(i(n)||s&&s(n))){const o=c.diff(n,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width,a=this.grid_height-this.config.header_height,h=c.format(n,"YYYY-MM-DD",this.options.language).replace(" ","_");if(t[n]){let d=this.create_el({classes:"holiday-label label_"+h,append_to:this.$extras});d.textContent=t[n]}f("rect",{x:Math.round(o),y:this.config.header_height,width:this.config.column_width/c.convert_scales(this.config.view_mode.step,"day"),height:a,class:"holiday-highlight "+h,style:`fill: ${e};`,append_to:this.layers.grid})}}}highlight_current(){const t=this.get_closest_date();if(!t)return;const[e,i]=t;i.classList.add("current-date-highlight");const n=c.diff(new Date,this.gantt_start,this.config.unit)/this.config.step*this.config.column_width;this.$current_highlight=this.create_el({top:this.config.header_height,left:n,height:this.grid_height-this.config.header_height,classes:"current-highlight",append_to:this.$container}),this.$current_ball_highlight=this.create_el({top:this.config.header_height-6,left:n-2.5,width:6,height:6,classes:"current-ball-highlight",append_to:this.$header})}make_grid_highlights(){this.highlight_holidays(),this.config.ignored_positions=[];const t=(this.options.bar_height+this.options.padding)*this.tasks.length;this.layers.grid.innerHTML+=`<pattern id="diagonalHatch" patternUnits="userSpaceOnUse" width="4" height="4">
|
|
25
25
|
<path d="M-1,1 l2,-2
|
|
26
26
|
M0,4 l4,-4
|
|
27
27
|
M3,5 l2,-2"
|
package/package.json
CHANGED
package/src/bar.js
CHANGED
|
@@ -521,6 +521,22 @@ export default class Bar {
|
|
|
521
521
|
this.hide_add_icon();
|
|
522
522
|
});
|
|
523
523
|
|
|
524
|
+
$.on(this.group, 'mouseup', () => {
|
|
525
|
+
// Use setTimeout to allow gantt's mouseup to fire first
|
|
526
|
+
// This ensures bar_being_dragged gets updated before we check it
|
|
527
|
+
setTimeout(() => {
|
|
528
|
+
// Reset dragging flag on mouseup if not actually dragging
|
|
529
|
+
// bar_being_dragged will be true if actual drag occurred
|
|
530
|
+
if (this.gantt.bar_being_dragged !== true) {
|
|
531
|
+
this.is_dragging = false;
|
|
532
|
+
// Show add icon if hovering
|
|
533
|
+
if (this.$add_icon_group && this.is_hovering_bar) {
|
|
534
|
+
this.$add_icon_group.classList.remove('hide');
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}, 0);
|
|
538
|
+
});
|
|
539
|
+
|
|
524
540
|
$.on(this.group, 'click', () => {
|
|
525
541
|
// Don't trigger click if we just finished dragging
|
|
526
542
|
if (this.action_completed || this.gantt.bar_being_dragged) return;
|
package/src/defaults.js
CHANGED
package/src/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export default class Gantt {
|
|
|
13
13
|
constructor(wrapper, tasks, options) {
|
|
14
14
|
this.setup_wrapper(wrapper);
|
|
15
15
|
this.setup_options(options);
|
|
16
|
+
this.apply_rtl_direction();
|
|
16
17
|
this.setup_tasks(tasks);
|
|
17
18
|
this.change_view_mode();
|
|
18
19
|
this.bind_events();
|
|
@@ -70,6 +71,12 @@ export default class Gantt {
|
|
|
70
71
|
});
|
|
71
72
|
}
|
|
72
73
|
|
|
74
|
+
apply_rtl_direction() {
|
|
75
|
+
if (this.options.isRTL) {
|
|
76
|
+
this.$container.style.direction = 'ltr';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
73
80
|
setup_options(options) {
|
|
74
81
|
this.original_options = options;
|
|
75
82
|
if (options?.view_modes) {
|
|
@@ -134,6 +141,7 @@ export default class Gantt {
|
|
|
134
141
|
|
|
135
142
|
update_options(options) {
|
|
136
143
|
this.setup_options({ ...this.original_options, ...options });
|
|
144
|
+
this.apply_rtl_direction();
|
|
137
145
|
this.change_view_mode(undefined, true);
|
|
138
146
|
}
|
|
139
147
|
|