1 /*---------------------------------------------------------
3 *---------------------------------------------------------*/
4 openerp.web_gantt = function (openerp) {
5 var _t = openerp.web._t;
6 var QWeb = openerp.web.qweb;
8 QWeb.add_template('/web_gantt/static/src/xml/web_gantt.xml');
9 openerp.web.views.add('gantt', 'openerp.web_gantt.GanttView');
10 openerp.web_gantt.GanttView = openerp.web.View.extend({
12 init: function(parent, dataset, view_id) {
14 this.view_manager = parent || new openerp.web.NullViewManager();
15 this.dataset = dataset;
16 this.model = dataset.model;
17 this.view_id = view_id;
18 this.domain = this.dataset.domain || [];
19 this.context = this.dataset.context || {};
20 this.has_been_loaded = $.Deferred();
25 return this.rpc("/web/view/load", {"model": this.model, "view_id": this.view_id, "view_type": "gantt"}, this.on_loaded);
28 on_loaded: function(data) {
29 this.fields_view = data,
30 this.name = this.fields_view.arch.attrs.string,
31 this.view_id = this.fields_view.view_id,
32 this.fields = this.fields_view.fields;
34 this.date_start = this.fields_view.arch.attrs.date_start,
35 this.date_delay = this.fields_view.arch.attrs.date_delay,
36 this.date_stop = this.fields_view.arch.attrs.date_stop,
37 this.day_length = this.fields_view.arch.attrs.day_length || 8;
39 this.color_field = this.fields_view.arch.attrs.color,
40 this.colors = this.fields_view.arch.attrs.colors;
42 var level = this.fields_view.arch.children[0];
43 this.parent = level.attrs.link,
44 this.text = level.children.length ? level.children[0].attrs.name : level.attrs.name;
46 if (!this.date_start) {
47 return self.do_warn(_t("date_start is not defined "))
50 this.$element.html(QWeb.render("GanttView", {'height': $('.oe-application-container').height(), 'width': $('.oe-application-container').width()}));
51 this.has_been_loaded.resolve();
54 on_project_loaded: function(projects) {
56 if(!projects.length) return;
58 started_projects = _.filter(projects, function(res) {
59 return res[self.date_start];
62 this.database_projects = started_projects;
65 var name = started_projects[0][self.parent];
66 self.name = name instanceof Array? name[name.length - 1] : name;
69 $.when(this.project_starting_date(), this.get_project_duration(), this.calculate_difference())
71 if(self.ganttChartControl) {
72 self.ganttChartControl.clearAll();
73 self.$element.find('#GanttView').empty();
76 .then(this.group_projects())
77 .then(this.generate_projects())
78 .then(this.add_tasks())
79 .done(this.init_gantt_view());
82 generate_projects : function() {
83 var projects = this.database_projects,
86 this.GanttProjects = [],
88 if(this.GroupProject) {
89 _.each(this.GroupProject, function(grp, index) {
90 self.GanttProjects.push(new GanttProjectInfo(index, grp, self.project_start_date));
91 self.GanttTasks.push(new GanttTaskInfo(index, grp, self.project_start_date, self.total_duration, 100, ""));
94 this.GanttProjects.push(new GanttProjectInfo(0, self.name, self.project_start_date));
95 this.GanttTasks.push(new GanttTaskInfo(0, self.name, self.project_start_date, self.total_duration, 100, ""));
98 return $.Deferred().resolve().promise();
101 group_projects: function() {
102 var def = $.Deferred(),
104 projects = this.database_projects;
106 if (!this.group_by.length) return def.resolve().promise();
108 var groups = _.pluck(projects, this.group_by[0]);
109 this.GroupProject = [];
110 _.each(groups, function(grp) {
111 if(grp instanceof Array) {
112 grp = grp[grp.length - 1];
114 if(!_.include(self.GroupProject,grp))
115 self.GroupProject.push(grp);
118 return def.resolve().promise();
121 get_project_duration: function() {
124 projects = this.database_projects;
126 this.project_duration = [];
128 _.each(projects, function(project, index) {
129 if (self.date_stop && project[self.date_stop]) {
131 console.log('TODO for date_stop');
132 self.project_duration.push(0);
133 } else if(self.date_delay && project[self.date_delay]) {
134 self.project_duration.push(project[self.date_delay]);
136 self.project_duration.push(0);
140 this.max_project_duration = _.max(this.project_duration);
141 return $.Deferred().resolve().promise();
144 calculate_difference: function() {
145 var extend_end_date_day = Math.floor(this.max_project_duration / this.day_length),
146 extend_end_date_hours = this.max_project_duration % this.day_length;
148 this.project_end_date = this.project_end_date.add({days: extend_end_date_day, hours: extend_end_date_hours})
150 var DAY = 1000 * 60 * 60 * 24,
151 difference = Math.abs(this.project_start_date.getTime() - this.project_end_date.getTime()),
152 day = Math.ceil(difference / DAY),
153 hour = (difference % DAY)/(1000 * 60 * 60),
154 DiffHour = (day * this.day_length) + hour;
156 this.total_duration = parseFloat(DiffHour.toFixed(2));
157 return $.Deferred().resolve().promise();
160 add_tasks: function() {
162 tasks = this.database_projects;
164 _.each(tasks, function(task, index) {
165 var name = task[self.text];
166 if(task[self.text] instanceof Array) {
167 name = task[self.text][1];
169 self.GanttTasks[0].addChildTask(
170 new GanttTaskInfo(task.id, name, self.format_date(task[self.date_start]), self.project_duration[index], 100, "")
174 return $.Deferred().resolve().promise();
177 project_starting_date : function() {
179 projects = this.database_projects,
180 min_date = _.min(projects, function(prj) {
181 return new Date(prj[self.date_start]);
183 max_date = _.max(projects, function(prj) {
184 return self.format_date(prj[self.date_start]);
187 this.project_end_date = this.format_date(max_date[self.date_start]);
188 if (min_date) this.project_start_date = this.format_date(min_date[self.date_start]);
190 this.project_start_date = Date.today();
191 return $.Deferred().resolve().promise();
194 init_gantt_view: function() {
197 this.GanttProjects[0].addTask(this.GanttTasks[0]);
200 var ganttChartControl = this.ganttChartControl = new GanttChart();
202 // Setup paths and behavior
203 ganttChartControl.setImagePath("/web_gantt/static/lib/dhtmlxGantt/codebase/imgs/");
204 ganttChartControl.setEditable(true);
205 ganttChartControl.showTreePanel(true);
206 ganttChartControl.showContextMenu(false);
207 ganttChartControl.showDescTask(true,'d,s-f');
208 ganttChartControl.showDescProject(true,'n,d');
210 // Load data structure
211 ganttChartControl.addProject(this.GanttProjects[0]);
212 // Create Gantt control
213 ganttChartControl.create('GanttView');
216 ganttChartControl.attachEvent("onTaskStartDrag", function(task) {
217 var task_date = task.getEST();
218 if(task_date.getHours()) {
219 task_date.set({hour: task_date.getHours(), minute : task_date.getMinutes(), second:0});
222 ganttChartControl.attachEvent("onTaskEndResize", function(task) {return self.ResizeTask(task);});
223 ganttChartControl.attachEvent("onTaskEndDrag", function(task) {return self.ResizeTask(task);});
224 ganttChartControl.attachEvent("onTaskDblClick", function(task) { return self.editTask(task);});
227 format_date : function(date) {
228 var datetime_regex = /^(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)(?:\.\d+)?$/,
229 date_regex = /^\d\d\d\d-\d\d-\d\d$/,
230 time_regex = /^(\d\d:\d\d:\d\d)(?:\.\d+)?$/,
232 if(date_regex.exec(date)) {
233 this.date_format = "yyyy-MM-dd";
234 } else if(time_regex.exec(date)) {
235 this.date_format = "HH:mm:ss";
237 this.date_format = "yyyy-MM-dd HH:mm:ss";
239 return openerp.web.auto_str_to_date(date);
242 ResizeTask: function(task) {
244 var event_id = task.getId();
248 return this.do_warn(_t("Project can not be resized"));
251 data[this.date_start] = task.getEST().toString(this.date_format);
254 var diff = task.getDuration() % this.day_length,
255 finished_date = task.getFinishDate().add({hours: diff});
256 data[this.date_stop] = finished_date.toString(this.date_format);
258 data[this.date_delay] = task.getDuration();
261 .write(event_id, data, {})
267 editTask: function(task) {
269 var event_id = task.getId();
273 if(event_id) event_id = parseInt(event_id, 10);
275 var action_manager = new openerp.web.ActionManager(this);
277 var dialog = new openerp.web.Dialog(this, {
281 Cancel : function() {
282 $(this).dialog('destroy');
285 var form_view = action_manager.inner_viewmanager.views.form.controller;
287 form_view.do_save(function() {
290 $(this).dialog('destroy');
294 action_manager.appendTo(dialog.$element);
295 action_manager.do_action({
296 res_model : this.dataset.model,
298 views : [[false, 'form']],
299 type : 'ir.actions.act_window',
304 views_switcher : false,
305 action_buttons : false,
311 reloadView: function() {
312 self.on_project_loaded(self.database_projects);
315 do_show: function () {
316 this.$element.show();
319 do_hide: function () {
320 this.$element.hide();
323 do_search: function (domains, contexts, groupbys) {
325 this.group_by = groupbys;
326 $.when(this.has_been_loaded).then(function() {
333 .done(function(projects) {
334 self.on_project_loaded(projects);
342 // here you may tweak globals object, if any, and play with on_* or do_* callbacks on them
345 // vim:et fdc=0 fdl=0: