1 openerp.web_dashboard = function(openerp) {
2 var QWeb = openerp.web.qweb,
5 if (!openerp.web_dashboard) {
7 openerp.web_dashboard = {};
10 openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
11 init: function(view, node) {
12 this._super(view, node);
13 this.template = 'DashBoard';
14 this.actions_attrs = {};
15 this.action_managers = [];
19 this._super.apply(this, arguments);
21 this.$element.find('.oe-dashboard-column').sortable({
22 connectWith: '.oe-dashboard-column',
23 handle: '.oe-dashboard-action-header',
25 }).disableSelection().bind('sortstop', self.do_save_dashboard);
28 this.$element.find('.oe-dashboard-link-reset').click(this.on_reset);
29 this.$element.find('.oe-dashboard-link-change_layout').click(this.on_change_layout);
31 this.$element.delegate('.oe-dashboard-column .oe-dashboard-fold', 'click', this.on_fold_action);
32 this.$element.delegate('.oe-dashboard-column .ui-icon-closethick', 'click', this.on_close_action);
34 this.actions_attrs = {};
36 _.each(this.node.children, function(column, column_index) {
37 _.each(column.children, function(action, action_index) {
38 delete(action.attrs.width);
39 delete(action.attrs.height);
40 delete(action.attrs.colspan);
41 self.actions_attrs[action.attrs.name] = action.attrs;
42 self.rpc('/web/action/load', {
43 action_id: parseInt(action.attrs.name, 10)
45 self.on_load_action(result, column_index + '_' + action_index);
50 on_reset: function() {
51 this.rpc('/web/view/undo_custom', {
52 view_id: this.view.fields_view.view_id,
56 on_change_layout: function() {
59 current_layout : this.$element.find('.oe-dashboard').attr('data-layout')
61 var $dialog = $('<div>').dialog({
63 title: _t("Edit Layout"),
66 }).html(QWeb.render('DashBoard.layouts', qdict));
67 $dialog.find('li').click(function() {
68 var layout = $(this).attr('data-layout');
69 $dialog.dialog('destroy');
70 self.do_change_layout(layout);
73 do_change_layout: function(new_layout) {
74 var $dashboard = this.$element.find('.oe-dashboard');
75 var current_layout = $dashboard.attr('data-layout');
76 if (current_layout != new_layout) {
77 var clayout = current_layout.split('-').length,
78 nlayout = new_layout.split('-').length,
79 column_diff = clayout - nlayout;
80 if (column_diff > 0) {
81 var $last_column = $();
82 $dashboard.find('.oe-dashboard-column').each(function(k, v) {
84 $(v).find('.oe-dashboard-action').appendTo($last_column);
90 $dashboard.toggleClass('oe-dashboard-layout_' + current_layout + ' oe-dashboard-layout_' + new_layout);
91 $dashboard.attr('data-layout', new_layout);
92 this.do_save_dashboard();
95 on_fold_action: function(e) {
96 var $e = $(e.currentTarget),
97 $action = $e.parents('.oe-dashboard-action:first'),
98 id = parseInt($action.attr('data-id'), 10);
99 if ($e.is('.ui-icon-minusthick')) {
100 this.actions_attrs[id].fold = '1';
102 delete(this.actions_attrs[id].fold);
104 $e.toggleClass('ui-icon-minusthick ui-icon-plusthick');
105 $action.find('.oe-dashboard-action-content').toggle();
106 this.do_save_dashboard();
108 on_close_action: function(e) {
109 if (confirm(_t("Are you sure you want to remove this item ?"))) {
110 $(e.currentTarget).parents('.oe-dashboard-action:first').remove();
111 this.do_save_dashboard();
114 do_save_dashboard: function() {
117 form_title : this.view.fields_view.arch.attrs.string,
118 style : this.$element.find('.oe-dashboard').attr('data-layout'),
121 this.$element.find('.oe-dashboard-column').each(function() {
123 $(this).find('.oe-dashboard-action').each(function() {
124 var action_id = $(this).attr('data-id'),
125 new_attrs = _.clone(self.actions_attrs[action_id]);
126 if (new_attrs.domain) {
127 new_attrs.domain = new_attrs.domain_string;
128 delete(new_attrs.domain_string);
130 if (new_attrs.context) {
131 new_attrs.context = new_attrs.context_string;
132 delete(new_attrs.context_string);
134 actions.push(new_attrs);
136 board.columns.push(actions);
138 var arch = QWeb.render('DashBoard.xml', board);
139 this.rpc('/web/view/add_custom', {
140 view_id: this.view.fields_view.view_id,
143 self.$element.find('.oe-dashboard-link-reset').show();
146 on_load_action: function(result, index) {
148 action = result.result,
149 action_attrs = this.actions_attrs[action.id],
150 view_mode = action_attrs.view_mode;
152 if (action_attrs.context) {
153 action.context = _.extend((action.context || {}), action_attrs.context);
155 if (action_attrs.domain) {
156 action.domain = action.domain || [];
157 action.domain.unshift.apply(action.domain, action_attrs.domain);
159 var action_orig = _.extend({ flags : {} }, action);
161 if (view_mode && view_mode != action.view_mode) {
162 var action_view_mode = action.view_mode.split(',');
163 action.views = _.map(view_mode.split(','), function(mode) {
164 if (_.indexOf(action_view_mode, mode) < 0) {
165 return [false, mode == 'tree' ? 'list': mode];
167 mode = mode === 'tree' ? 'list' : mode;
168 return _.find(action.views, function(view) {
169 return view[1] == mode;
178 views_switcher : false,
179 action_buttons : false,
182 display_title: false,
187 var am = new openerp.web.ActionManager(this),
188 // FIXME: ideally the dashboard view shall be refactored like kanban.
189 $action = $('#' + this.view.element_id + '_action_' + index);
190 this.action_managers.push(am);
191 am.appendTo($action);
192 am.do_action(action);
193 am.do_action = function (action) {
194 self.do_action(action);
196 if (action_attrs.creatable && action_attrs.creatable !== 'false') {
197 var action_id = parseInt(action_attrs.creatable, 10);
198 $action.parent().find('button.oe_dashboard_button_create').click(function() {
199 if (isNaN(action_id)) {
200 action_orig.flags.default_view = 'form';
201 self.do_action(action_orig);
203 self.rpc('/web/action/load', {
205 }, function(result) {
206 result.result.flags = result.result.flags || {};
207 result.result.flags.default_view = 'form';
208 self.do_action(result.result);
213 if (am.inner_viewmanager) {
214 am.inner_viewmanager.on_mode_switch.add(function(mode) {
216 _.each(action_orig.views, function(view) {
217 new_views[view[1] === mode ? 'unshift' : 'push'](view);
219 if (!new_views.length || new_views[0][1] !== mode) {
220 new_views.unshift([false, mode]);
222 action_orig.views = new_views;
223 action_orig.res_id = am.inner_viewmanager.dataset.ids[am.inner_viewmanager.dataset.index];
224 self.do_action(action_orig);
229 // We should start with three columns available
230 for (var i = this.node.children.length; i < 3; i++) {
231 this.node.children.push({
237 return QWeb.render(this.template, this);
239 do_reload: function() {
240 var view_manager = this.view.widget_parent,
241 action_manager = view_manager.widget_parent;
243 action_manager.do_action(view_manager.action);
246 openerp.web.form.DashBoardLegacy = openerp.web.form.DashBoard.extend({
248 if (this.node.tag == 'hpaned') {
249 this.node.attrs.style = '2-1';
250 } else if (this.node.tag == 'vpaned') {
251 this.node.attrs.style = '1';
253 this.node.tag = 'board';
254 _.each(this.node.children, function(child) {
255 if (child.tag.indexOf('child') == 0) {
256 child.tag = 'column';
257 var actions = [], first_child = child.children[0];
258 if (first_child && first_child.tag == 'vpaned') {
259 _.each(first_child.children, function(subchild) {
260 actions.push.apply(actions, subchild.children);
262 child.children = actions;
266 return this._super(this, arguments);
270 openerp.web.form.widgets.add('hpaned', 'openerp.web.form.DashBoardLegacy');
271 openerp.web.form.widgets.add('vpaned', 'openerp.web.form.DashBoardLegacy');
272 openerp.web.form.widgets.add('board', 'openerp.web.form.DashBoard');
276 * This client action designed to be used as a dashboard widget display
277 * ir.actions.todo in a fancy way
279 openerp.web.client_actions.add( 'board.config.overview', 'openerp.web_dashboard.ConfigOverview');
280 openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
281 template: 'ConfigOverview',
282 init: function (parent) {
284 this.user = _.extend(new openerp.web.DataSet(this, 'res.users'), {
286 ids: [this.session.uid]
288 this.dataset = new openerp.web.DataSetSearch(this, 'ir.actions.todo');
293 return this.user.read_index(['groups_id']).pipe(function(record) {
295 ['type', '!=', 'automatic'],
296 '|', ['groups_id', '=', false],
297 ['groups_id', 'in', record['groups_id']]];
299 self.dataset.read_slice(
300 ['state', 'action_id', 'category_id'],
301 { domain: todos_filter }
303 self.dataset.call('progress').pipe(
304 function (arg) { return arg; }, null))
305 }, null).then(this.on_records_loaded);
308 on_records_loaded: function (records, progress) {
309 var grouped_todos = _(records).chain()
310 .map(function (record) {
313 name: record.action_id[1],
314 done: record.state !== 'open',
315 to_do: record.state === 'open',
316 category: record['category_id'][1] || _t("Uncategorized")
319 .groupBy(function (record) {return record.category})
321 this.$element.html(QWeb.render('ConfigOverview.content', {
322 completion: 100 * progress.done / progress.total,
323 groups: grouped_todos,
324 task_title: _t("Execute task \"%s\""),
325 checkbox_title: _t("Mark this task as done"),
328 var $progress = this.$element.find('div.oe-config-progress-bar');
329 $progress.progressbar({value: $progress.data('completion')});
332 this.$element.find('dl')
333 .delegate('input', 'click', function (e) {
334 // switch todo status
335 e.stopImmediatePropagation();
336 var new_state = this.checked ? 'done' : 'open',
337 todo_id = parseInt($(this).val(), 10);
338 self.dataset.write(todo_id, {state: new_state}, {}, function () {
342 .delegate('li:not(.oe-done)', 'click', function () {
343 self.widget_parent.widget_parent.widget_parent.do_execute_action({
345 name: 'action_launch'
347 $(this).data('id'), function () {
348 // after action popup closed, refresh configuration
358 * This client action designed to be used as a dashboard widget display
359 * the html content of a res_widget given as argument
361 openerp.web.client_actions.add( 'board.home.widgets', 'openerp.web_dashboard.Widget');
362 openerp.web_dashboard.Widget = openerp.web.View.extend(/** @lends openerp.web_dashboard.Widgets# */{
363 template: 'HomeWidget',
365 * Initializes a "HomeWidget" client widget: handles the display of a given
366 * res.widget objects in an OpenERP view (mainly a dashboard).
368 * @constructs openerp.web_dashboard.Widget
369 * @extends openerp.web.View
371 * @param {Object} parent
372 * @param {Object} options
373 * @param {Number} options.widget_id
375 init: function (parent, options) {
377 this.widget_id = options.widget_id;
381 var ds = new openerp.web.DataSet(this, 'res.widget');
382 return ds.read_ids([this.widget_id], ['title']).then(this.on_widget_loaded);
384 on_widget_loaded: function (widgets) {
385 var widget = widgets[0];
386 var url = _.str.sprintf(
387 '/web_dashboard/widgets/content?session_id=%s&widget_id=%d',
388 this.session.session_id, widget.id);
389 this.$element.html(QWeb.render('HomeWidget.content', {
397 * HomeTiles this client action display either the list of application to
398 * install (if none is installed yet) or a list of root menu items
400 openerp.web.client_actions.add('default_home', 'session.web_dashboard.ApplicationTiles');
401 openerp.web_dashboard.ApplicationTiles = openerp.web.OldWidget.extend({
402 template: 'web_dashboard.ApplicationTiles',
403 init: function(parent) {
408 openerp.webclient.menu.do_hide_secondary();
409 var domain = [['application','=',true], ['state','=','installed'], ['name', '!=', 'base']];
410 var ds = new openerp.web.DataSetSearch(this, 'ir.module.module',{},domain);
411 ds.read_slice(['id']).then(function(result) {
413 self.on_installed_database();
415 self.on_uninstalled_database();
419 on_uninstalled_database: function() {
420 installer = new openerp.web_dashboard.ApplicationInstaller(this);
421 installer.appendTo(this.$element);
423 on_installed_database: function() {
425 self.rpc('/web/menu/get_user_roots', {}).then(function (menu_ids) {
426 var menuds = new openerp.web.DataSet(this, 'ir.ui.menu',{})
427 .read_ids(menu_ids, ['name', 'web_icon_data', 'web_icon_hover_data', 'module']).then(function (applications) {
428 var tiles = QWeb.render('ApplicationTiles.content', {applications: applications});
429 $(tiles).appendTo(self.$element).find('.oe_install-module-link').click(function () {
430 openerp.webclient.menu.on_menu_click(null, $(this).data('menu'))
438 * ApplicationInstaller
439 * This client action display a list of applications to install.
441 openerp.web.client_actions.add( 'board.application.installer', 'openerp.web_dashboard.ApplicationInstaller');
442 openerp.web_dashboard.ApplicationInstaller = openerp.web.OldWidget.extend({
443 template: 'web_dashboard.ApplicationInstaller',
446 var r = this._super();
447 this.action_manager = new openerp.web.ActionManager(this);
448 this.action_manager.appendTo(this.$element.find('.oe_installer'));
449 this.action_manager.do_action({
450 type: 'ir.actions.act_window',
451 res_model: 'ir.module.module',
452 domain: [['application','=',true]],
453 views: [[false, 'kanban']],
457 views_switcher: false,
458 action_buttons: false,
466 this.action_manager.stop();
467 return this._super();