This is the third article about Frappe Gantt in XPages and in this article we will add some more logic to the data feedback to Domino as well as adding a series of buttons to switch between views of the gantt chart.

For those of you who want to start reading the previous articles, here are the links:

In the meantime - Gantt in XPages
Recently, I had played around with Frappe Gantt JS and XPages. This post isabout how to make interactive Gantt Charts available through XPages.
1st Part of the series
More GANTT in XPages ...
This is the 2nd part of my series of articles around Gantt Charts in XPages. Today, we want to write changes back to Domino, so if we move Blocks around, we want to send these changes back to Domino.
2nd Part of the series.

So today, let's start with the buttons to switch between views. Here's what we want to achieve:

So at the bottom of our rendering XPage, we will add a DIV and some Buttons. The buttons will do some Client Side JavaScript actions to toggle the view in the Gantt Chart. This code looks like this it will go right under the gantt div:

<div class="container">
		<h2>
			Interactive Gantt Chart entirely made in SVG!
		</h2>
        
		<div class="gantt-target"></div>
		
        <div class="mx-auto mt-3 btn-group" role="group">
	  
      <xp:button value="Week" id="changeViewWeek"
	  	styleClass="btn btn-sm btn-light">
	  <xp:eventHandler event="onclick" submit="false">
	  	<xp:this.script><![CDATA[gantt_chart.change_view_mode('Week') // Quarter Day, Half Day, Day, Week, Month ]]></xp:this.script>
	  </xp:eventHandler></xp:button>
	  <xp:button value="Day" id="button1"
	  	styleClass="btn btn-sm btn-light">
	  	<xp:eventHandler event="onclick" submit="false">
	  		<xp:this.script><![CDATA[gantt_chart.change_view_mode('Day') // Quarter Day, Half Day, Day, Week, Month ]]></xp:this.script>
	  	</xp:eventHandler>
	  </xp:button>
	  <xp:button value="Month" id="button2"
	  	styleClass="btn btn-sm btn-light">
	  	<xp:eventHandler event="onclick" submit="false">
	  		<xp:this.script><![CDATA[gantt_chart.change_view_mode('Month') // Quarter Day, Half Day, Day, Week, Month ]]></xp:this.script>
	  	</xp:eventHandler>
	  </xp:button>
		</div>
	</div>

As you can see, we are directly calling the JavaScript object "gantt_chart". So far, this object only lives inside of our Output Script - and is therefore not available to our buttons yet. To make it available, we declare the object in the onClientLoad Event Handler of the XPage like this:

<xp:eventHandler event="onClientLoad" submit="true"
		refreshMode="norefresh">
		<xp:this.action><![CDATA[#{javascript:var gantt_chart;}]]></xp:this.action>
	</xp:eventHandler>

Now, the object is defined for the entire page and we can make use of it in our output script like this:

gantt_chart = new Gantt(".gantt-target", tasks, {.....

This should lead us to a result like in the screenshot above.

The 2nd Change I incorporated is the possibility to not only change the dates of a task but also its progress level. Basically, we want to do things like the following screenshots:

In the 2nd series, we built a saveDateChange function to save our changes back to Domino. Today, we will create a more general approach and also hook up the progress change event of the Gantt Chart.

Let's start be re-factoring our saveDateChange function to a saveChange function. This will take the task object and a body object as its variables:

function saveChange(task, body) {
	var httpRequest = create_request();
	httpRequest.open("PATCH","https://sitfp10.sit.de/rtapi_testbed_v3.nsf/tasks.xsp/savetask/unid/"+task["@unid"]);
	httpRequest.setRequestHeader("Content-Type", "application/json; charset=utf-8");
	httpRequest.setRequestHeader( "X-HTTP-Method-Override","PATCH");
	
	httpRequest.send(JSON.stringify(body));
	if (httpRequest.status == 200) // For http requests.
    {
       return({"Status":"OK"});
    }
    else
    {
       return ({"Status":"Error"});
    }
}

So again, we will do a PATCH call but we expect the calling method to hand the field list as JSON to us. Using this notation, we can use the same function to hook up our change events in our output script for both use cases:

gantt_chart = new Gantt(".gantt-target", tasks, {
	on_click: function (task) {
		console.log(task);
	},
	on_date_change: function(task, start, end) {
		console.log(task, start, end);
		var body = {"start":start,"end":end};
		var back = saveChange(task, body);
	},
	on_progress_change: function(task, progress) {
		console.log(task, progress);
		var body = {"progress":progress};
		var back = saveChange(task, body);
	},
	on_view_change: function(mode) {
		console.log(mode);
	},
	on_click: function (task) {
		console.log(task);
	},
	header_height: 50,
	column_width: 30,
  	step: 24,
	view_modes: ['Quarter Day', 'Half Day', 'Day', 'Week', 'Month'],
	bar_height: 20,
  	bar_corner_radius: 3,
  	arrow_curve: 5,
  	padding: 18,
  	view_mode: 'Day',
   	date_format: 'YYYY-MM-DD',
   	custom_popup_html: null,
	language: 'en'
});

By simply changing the JavaScript Object in the event listener, we can use the same function for both change events.

This concludes the third part of the series. Happy hacking!

Heiko.