2011-04-07 12:13:31 +00:00
|
|
|
/*---------------------------------------------------------
|
2011-09-05 12:28:15 +00:00
|
|
|
* OpenERP web_gantt
|
2011-04-07 12:13:31 +00:00
|
|
|
*---------------------------------------------------------*/
|
2012-04-17 12:48:30 +00:00
|
|
|
openerp.web_gantt = function (instance) {
|
|
|
|
var _t = instance.web._t,
|
|
|
|
_lt = instance.web._lt;
|
|
|
|
var QWeb = instance.web.qweb;
|
|
|
|
instance.web.views.add('gantt', 'instance.web_gantt.GanttView');
|
2012-01-18 13:06:52 +00:00
|
|
|
|
2012-04-17 12:48:30 +00:00
|
|
|
instance.web_gantt.GanttView = instance.web.View.extend({
|
2011-12-16 13:00:00 +00:00
|
|
|
display_name: _lt('Gantt'),
|
2012-01-18 13:06:52 +00:00
|
|
|
template: "GanttView",
|
2012-04-05 16:21:31 +00:00
|
|
|
view_type: "gantt",
|
2012-01-20 14:58:12 +00:00
|
|
|
init: function() {
|
2012-10-18 11:49:50 +00:00
|
|
|
var self = this;
|
2012-01-20 14:58:12 +00:00
|
|
|
this._super.apply(this, arguments);
|
|
|
|
this.has_been_loaded = $.Deferred();
|
|
|
|
this.chart_id = _.uniqueId();
|
2012-12-13 14:09:14 +00:00
|
|
|
},
|
|
|
|
view_loading: function(r) {
|
|
|
|
return this.load_gantt(r);
|
2012-01-20 14:58:12 +00:00
|
|
|
},
|
2012-10-18 11:49:50 +00:00
|
|
|
load_gantt: function(fields_view_get, fields_get) {
|
2012-04-05 16:21:31 +00:00
|
|
|
var self = this;
|
|
|
|
this.fields_view = fields_view_get;
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.addClass(this.fields_view.arch.attrs['class']);
|
2012-11-26 10:46:55 +00:00
|
|
|
return new instance.web.Model(this.dataset.model)
|
|
|
|
.call('fields_get').then(function (fields) {
|
|
|
|
self.fields = fields;
|
|
|
|
self.has_been_loaded.resolve();
|
|
|
|
});
|
2012-01-18 13:06:52 +00:00
|
|
|
},
|
2012-01-20 14:58:12 +00:00
|
|
|
do_search: function (domains, contexts, group_bys) {
|
2012-01-20 13:06:48 +00:00
|
|
|
var self = this;
|
2012-01-25 12:39:33 +00:00
|
|
|
self.last_domains = domains;
|
|
|
|
self.last_contexts = contexts;
|
|
|
|
self.last_group_bys = group_bys;
|
2012-01-20 14:58:12 +00:00
|
|
|
// select the group by
|
|
|
|
var n_group_bys = [];
|
2012-01-20 13:06:48 +00:00
|
|
|
if (this.fields_view.arch.attrs.default_group_by) {
|
2012-01-20 14:58:12 +00:00
|
|
|
n_group_bys = this.fields_view.arch.attrs.default_group_by.split(',');
|
|
|
|
}
|
|
|
|
if (group_bys.length) {
|
2012-01-20 15:52:54 +00:00
|
|
|
n_group_bys = group_bys;
|
2012-01-20 13:06:48 +00:00
|
|
|
}
|
2012-01-20 14:58:12 +00:00
|
|
|
// gather the fields to get
|
2012-01-27 16:06:45 +00:00
|
|
|
var fields = _.compact(_.map(["date_start", "date_delay", "date_stop"], function(key) {
|
2012-01-20 14:58:12 +00:00
|
|
|
return self.fields_view.arch.attrs[key] || '';
|
|
|
|
}));
|
2012-01-27 16:06:45 +00:00
|
|
|
fields = _.uniq(fields.concat(n_group_bys));
|
2012-01-20 13:06:48 +00:00
|
|
|
|
2012-10-30 14:06:30 +00:00
|
|
|
return $.when(this.has_been_loaded).then(function() {
|
2012-01-20 14:58:12 +00:00
|
|
|
return self.dataset.read_slice(fields, {
|
|
|
|
domain: domains,
|
|
|
|
context: contexts
|
2012-10-30 14:06:30 +00:00
|
|
|
}).then(function(data) {
|
2012-01-20 14:58:12 +00:00
|
|
|
return self.on_data_loaded(data, n_group_bys);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
2012-01-25 12:39:33 +00:00
|
|
|
reload: function() {
|
2012-01-25 12:55:49 +00:00
|
|
|
if (this.last_domains !== undefined)
|
|
|
|
return this.do_search(this.last_domains, this.last_contexts, this.last_group_bys);
|
2012-01-25 12:39:33 +00:00
|
|
|
},
|
2012-01-20 14:58:12 +00:00
|
|
|
on_data_loaded: function(tasks, group_bys) {
|
2012-01-27 16:06:45 +00:00
|
|
|
var self = this;
|
|
|
|
var ids = _.pluck(tasks, "id");
|
2012-10-30 14:06:30 +00:00
|
|
|
return this.dataset.name_get(ids).then(function(names) {
|
2012-01-27 16:06:45 +00:00
|
|
|
var ntasks = _.map(tasks, function(task) {
|
|
|
|
return _.extend({__name: _.detect(names, function(name) { return name[0] == task.id; })[1]}, task);
|
|
|
|
});
|
|
|
|
return self.on_data_loaded_2(ntasks, group_bys);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
on_data_loaded_2: function(tasks, group_bys) {
|
2012-01-20 14:58:12 +00:00
|
|
|
var self = this;
|
2012-08-24 18:27:07 +00:00
|
|
|
$(".oe_gantt", this.$el).html("");
|
2012-01-20 14:58:12 +00:00
|
|
|
|
|
|
|
//prevent more that 1 group by
|
|
|
|
if (group_bys.length > 0) {
|
|
|
|
group_bys = [group_bys[0]];
|
|
|
|
}
|
|
|
|
// if there is no group by, simulate it
|
|
|
|
if (group_bys.length == 0) {
|
|
|
|
group_bys = ["_pseudo_group_by"];
|
|
|
|
_.each(tasks, function(el) {
|
|
|
|
el._pseudo_group_by = "Gantt View";
|
|
|
|
});
|
2012-01-20 15:26:11 +00:00
|
|
|
this.fields._pseudo_group_by = {type: "string"};
|
2012-01-20 13:06:48 +00:00
|
|
|
}
|
2012-01-20 14:58:12 +00:00
|
|
|
|
|
|
|
// get the groups
|
2012-01-20 17:19:20 +00:00
|
|
|
var split_groups = function(tasks, group_bys) {
|
|
|
|
if (group_bys.length === 0)
|
|
|
|
return tasks;
|
|
|
|
var groups = [];
|
|
|
|
_.each(tasks, function(task) {
|
|
|
|
var group_name = task[_.first(group_bys)];
|
|
|
|
var group = _.find(groups, function(group) { return _.isEqual(group.name, group_name); });
|
|
|
|
if (group === undefined) {
|
|
|
|
group = {name:group_name, tasks: [], __is_group: true};
|
|
|
|
groups.push(group);
|
|
|
|
}
|
|
|
|
group.tasks.push(task);
|
|
|
|
});
|
|
|
|
_.each(groups, function(group) {
|
|
|
|
group.tasks = split_groups(group.tasks, _.rest(group_bys));
|
|
|
|
});
|
|
|
|
return groups;
|
|
|
|
}
|
|
|
|
var groups = split_groups(tasks, group_bys);
|
2012-01-20 14:58:12 +00:00
|
|
|
|
2012-01-25 12:18:18 +00:00
|
|
|
// track ids of task items for context menu
|
|
|
|
var task_ids = {};
|
2012-01-20 14:58:12 +00:00
|
|
|
// creation of the chart
|
2012-01-23 17:58:05 +00:00
|
|
|
var generate_task_info = function(task, plevel) {
|
|
|
|
var level = plevel || 0;
|
|
|
|
if (task.__is_group) {
|
|
|
|
var task_infos = _.compact(_.map(task.tasks, function(sub_task) {
|
|
|
|
return generate_task_info(sub_task, level + 1);
|
|
|
|
}));
|
|
|
|
if (task_infos.length == 0)
|
|
|
|
return;
|
|
|
|
var task_start = _.reduce(_.pluck(task_infos, "task_start"), function(date, memo) {
|
|
|
|
return memo === undefined || date < memo ? date : memo;
|
|
|
|
}, undefined);
|
|
|
|
var task_stop = _.reduce(_.pluck(task_infos, "task_stop"), function(date, memo) {
|
|
|
|
return memo === undefined || date > memo ? date : memo;
|
|
|
|
}, undefined);
|
|
|
|
var duration = (task_stop.getTime() - task_start.getTime()) / (1000 * 60 * 60);
|
2012-04-17 12:48:30 +00:00
|
|
|
var group_name = instance.web.format_value(task.name, self.fields[group_bys[level]]);
|
2012-01-23 17:58:05 +00:00
|
|
|
if (level == 0) {
|
2012-01-25 12:18:18 +00:00
|
|
|
var group = new GanttProjectInfo(_.uniqueId("gantt_project_"), group_name, task_start);
|
2012-01-23 17:58:05 +00:00
|
|
|
_.each(task_infos, function(el) {
|
|
|
|
group.addTask(el.task_info);
|
|
|
|
});
|
|
|
|
return group;
|
|
|
|
} else {
|
2012-01-25 12:18:18 +00:00
|
|
|
var group = new GanttTaskInfo(_.uniqueId("gantt_project_task_"), group_name, task_start, duration, 100);
|
2012-01-23 17:58:05 +00:00
|
|
|
_.each(task_infos, function(el) {
|
|
|
|
group.addChildTask(el.task_info);
|
|
|
|
});
|
|
|
|
return {task_info: group, task_start: task_start, task_stop: task_stop};
|
|
|
|
}
|
|
|
|
} else {
|
2012-01-27 16:06:45 +00:00
|
|
|
var task_name = task.__name;
|
2012-04-17 12:48:30 +00:00
|
|
|
var task_start = instance.web.auto_str_to_date(task[self.fields_view.arch.attrs.date_start]);
|
2012-01-20 15:26:11 +00:00
|
|
|
if (!task_start)
|
|
|
|
return;
|
2012-01-23 17:58:05 +00:00
|
|
|
var task_stop;
|
|
|
|
if (self.fields_view.arch.attrs.date_stop) {
|
2012-04-17 12:48:30 +00:00
|
|
|
task_stop = instance.web.auto_str_to_date(task[self.fields_view.arch.attrs.date_stop]);
|
2012-01-20 15:52:54 +00:00
|
|
|
if (!task_stop)
|
|
|
|
return;
|
2012-01-23 17:58:05 +00:00
|
|
|
} else { // we assume date_duration is defined
|
2012-04-17 12:48:30 +00:00
|
|
|
var tmp = instance.web.format_value(task[self.fields_view.arch.attrs.date_delay],
|
2012-01-23 17:58:05 +00:00
|
|
|
self.fields[self.fields_view.arch.attrs.date_delay]);
|
|
|
|
if (!tmp)
|
|
|
|
return;
|
|
|
|
task_stop = task_start.clone().addMilliseconds(tmp * 60 * 60 * 1000);
|
2012-01-20 15:52:54 +00:00
|
|
|
}
|
2012-01-23 17:58:05 +00:00
|
|
|
var duration = (task_stop.getTime() - task_start.getTime()) / (1000 * 60 * 60);
|
2012-01-25 12:18:18 +00:00
|
|
|
var id = _.uniqueId("gantt_task_");
|
|
|
|
var task_info = new GanttTaskInfo(id, task_name, task_start, ((duration / 24) * 8), 100);
|
2012-01-24 16:32:01 +00:00
|
|
|
task_info.internal_task = task;
|
2012-01-25 12:18:18 +00:00
|
|
|
task_ids[id] = task_info;
|
2012-01-23 17:58:05 +00:00
|
|
|
return {task_info: task_info, task_start: task_start, task_stop: task_stop};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var gantt = new GanttChart();
|
|
|
|
_.each(_.compact(_.map(groups, function(e) {return generate_task_info(e, 0);})), function(project) {
|
2012-01-24 16:32:01 +00:00
|
|
|
gantt.addProject(project);
|
2012-01-23 17:58:05 +00:00
|
|
|
});
|
2012-01-24 16:32:01 +00:00
|
|
|
gantt.setEditable(true);
|
2012-01-23 17:58:05 +00:00
|
|
|
gantt.setImagePath("/web_gantt/static/lib/dhtmlxGantt/codebase/imgs/");
|
2012-01-24 16:32:01 +00:00
|
|
|
gantt.attachEvent("onTaskEndDrag", function(task) {
|
|
|
|
self.on_task_changed(task);
|
|
|
|
});
|
|
|
|
gantt.attachEvent("onTaskEndResize", function(task) {
|
|
|
|
self.on_task_changed(task);
|
|
|
|
});
|
2012-01-25 12:18:18 +00:00
|
|
|
gantt.create(this.chart_id);
|
|
|
|
|
|
|
|
// bind event to display task when we click the item in the tree
|
2012-08-24 18:27:07 +00:00
|
|
|
$(".taskNameItem", self.$el).click(function(event) {
|
2012-01-25 12:18:18 +00:00
|
|
|
var task_info = task_ids[event.target.id];
|
|
|
|
if (task_info) {
|
|
|
|
self.on_task_display(task_info.internal_task);
|
|
|
|
}
|
2012-01-25 11:08:49 +00:00
|
|
|
});
|
2012-09-04 14:11:55 +00:00
|
|
|
if (this.is_action_enabled('create')) {
|
2012-08-27 04:42:56 +00:00
|
|
|
// insertion of create button
|
|
|
|
var td = $($("table td", self.$el)[0]);
|
2012-08-16 11:02:43 +00:00
|
|
|
var rendered = QWeb.render("GanttView-create-button");
|
|
|
|
$(rendered).prependTo(td);
|
2012-08-27 04:42:56 +00:00
|
|
|
$(".oe_gantt_button_create", this.$el).click(this.on_task_create);
|
2012-08-16 11:02:43 +00:00
|
|
|
}
|
2012-01-24 16:32:01 +00:00
|
|
|
},
|
|
|
|
on_task_changed: function(task_obj) {
|
|
|
|
var self = this;
|
|
|
|
var itask = task_obj.TaskInfo.internal_task;
|
|
|
|
var start = task_obj.getEST();
|
2012-01-24 16:52:25 +00:00
|
|
|
var duration = (task_obj.getDuration() / 8) * 24;
|
|
|
|
var end = start.clone().addMilliseconds(duration * 60 * 60 * 1000);
|
2012-01-24 16:32:01 +00:00
|
|
|
var data = {};
|
|
|
|
data[self.fields_view.arch.attrs.date_start] =
|
2012-04-17 12:48:30 +00:00
|
|
|
instance.web.auto_date_to_str(start, self.fields[self.fields_view.arch.attrs.date_start].type);
|
2012-01-24 16:32:01 +00:00
|
|
|
if (self.fields_view.arch.attrs.date_stop) {
|
|
|
|
data[self.fields_view.arch.attrs.date_stop] =
|
2012-04-17 12:48:30 +00:00
|
|
|
instance.web.auto_date_to_str(end, self.fields[self.fields_view.arch.attrs.date_stop].type);
|
2012-01-24 16:32:01 +00:00
|
|
|
} else { // we assume date_duration is defined
|
|
|
|
data[self.fields_view.arch.attrs.date_delay] = duration;
|
|
|
|
}
|
2012-10-01 08:56:09 +00:00
|
|
|
this.dataset.write(itask.id, data);
|
2012-01-20 13:06:48 +00:00
|
|
|
},
|
2012-01-25 12:18:18 +00:00
|
|
|
on_task_display: function(task) {
|
2012-01-25 12:39:33 +00:00
|
|
|
var self = this;
|
2012-04-17 12:48:30 +00:00
|
|
|
var pop = new instance.web.form.FormOpenPopup(self);
|
2012-10-10 10:12:46 +00:00
|
|
|
pop.on('write_completed',self,self.reload);
|
2012-01-25 12:39:33 +00:00
|
|
|
pop.show_element(
|
|
|
|
self.dataset.model,
|
|
|
|
task.id,
|
|
|
|
null,
|
|
|
|
{}
|
|
|
|
);
|
2012-01-25 12:18:18 +00:00
|
|
|
},
|
2012-01-25 12:55:49 +00:00
|
|
|
on_task_create: function() {
|
|
|
|
var self = this;
|
2012-04-17 12:48:30 +00:00
|
|
|
var pop = new instance.web.form.SelectCreatePopup(this);
|
2012-10-12 13:10:44 +00:00
|
|
|
pop.on("elements_selected", self, function() {
|
2012-01-25 12:55:49 +00:00
|
|
|
self.reload();
|
|
|
|
});
|
|
|
|
pop.select_element(
|
|
|
|
self.dataset.model,
|
|
|
|
{
|
|
|
|
initial_view: "form",
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
2012-01-18 13:06:52 +00:00
|
|
|
});
|
|
|
|
|
2011-04-07 12:13:31 +00:00
|
|
|
};
|