@workiom/frappe-gantt 1.0.10 → 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.
@@ -896,6 +896,7 @@ const y = [
896
896
  infinite_padding: !0,
897
897
  holidays: { "var(--g-weekend-highlight-color)": "weekend" },
898
898
  ignore: [],
899
+ isRTL: !1,
899
900
  language: "en",
900
901
  lines: "both",
901
902
  move_dependencies: !0,
@@ -930,7 +931,7 @@ const y = [
930
931
  };
931
932
  class j {
932
933
  constructor(t, e, i) {
933
- 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();
934
935
  }
935
936
  setup_wrapper(t) {
936
937
  let e, i;
@@ -961,6 +962,9 @@ class j {
961
962
  append_to: this.$container
962
963
  });
963
964
  }
965
+ apply_rtl_direction() {
966
+ this.options.isRTL && (this.$container.style.direction = "ltr");
967
+ }
964
968
  setup_options(t) {
965
969
  this.original_options = t, t != null && t.view_modes && (t.view_modes = t.view_modes.map((i) => {
966
970
  if (typeof i == "string") {
@@ -1003,7 +1007,7 @@ class j {
1003
1007
  this.config.ignored_function = this.options.ignore;
1004
1008
  }
1005
1009
  update_options(t) {
1006
- 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);
1007
1011
  }
1008
1012
  setup_tasks(t) {
1009
1013
  this.tasks = t.map((e, i) => {
@@ -21,7 +21,7 @@
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="&larr;"}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="&larr;"}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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workiom/frappe-gantt",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "A simple, modern, interactive gantt library for the web",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/defaults.js CHANGED
@@ -123,6 +123,7 @@ const DEFAULT_OPTIONS = {
123
123
  infinite_padding: true,
124
124
  holidays: { 'var(--g-weekend-highlight-color)': 'weekend' },
125
125
  ignore: [],
126
+ isRTL: false,
126
127
  language: 'en',
127
128
  lines: 'both',
128
129
  move_dependencies: true,
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