[MERGE] tiles style
[odoo/odoo.git] / addons / web_dashboard / static / src / js / dashboard.js
1 openerp.web_dashboard = function(openerp) {
2 var QWeb = openerp.web.qweb;
3
4 if (!openerp.web_dashboard) {
5     /** @namespace */
6     openerp.web_dashboard = {};
7 }
8
9 openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
10     init: function(view, node) {
11         this._super(view, node);
12         this.template = 'DashBoard';
13         this.actions_attrs = {};
14         this.action_managers = [];
15     },
16     start: function() {
17         var self = this;
18         this._super.apply(this, arguments);
19
20         this.$element.find('.oe-dashboard-column').sortable({
21             connectWith: '.oe-dashboard-column',
22             handle: '.oe-dashboard-action-header',
23             scroll: false
24         }).disableSelection().bind('sortstop', self.do_save_dashboard);
25
26         // Events
27         this.$element.find('.oe-dashboard-link-reset').click(this.on_reset);
28         this.$element.find('.oe-dashboard-link-change_layout').click(this.on_change_layout);
29
30         this.$element.delegate('.oe-dashboard-column .oe-dashboard-fold', 'click', this.on_fold_action);
31         this.$element.delegate('.oe-dashboard-column .ui-icon-closethick', 'click', this.on_close_action);
32
33         this.actions_attrs = {};
34         // Init actions
35         _.each(this.node.children, function(column, column_index) {
36             _.each(column.children, function(action, action_index) {
37                 delete(action.attrs.width);
38                 delete(action.attrs.height);
39                 delete(action.attrs.colspan);
40                 self.actions_attrs[action.attrs.name] = action.attrs;
41                 self.rpc('/web/action/load', {
42                     action_id: parseInt(action.attrs.name, 10)
43                 }, function(result) {
44                     self.on_load_action(result, column_index + '_' + action_index);
45                 });
46             });
47         });
48     },
49     on_reset: function() {
50         this.rpc('/web/view/undo_custom', {
51             view_id: this.view.fields_view.view_id,
52             reset: true
53         }, this.do_reload);
54     },
55     on_change_layout: function() {
56         var self = this;
57         var qdict = {
58             current_layout : this.$element.find('.oe-dashboard').attr('data-layout')
59         };
60         var $dialog = $('<div>').dialog({
61                             modal: true,
62                             title: 'Edit Layout',
63                             width: 'auto',
64                             height: 'auto'
65                         }).html(QWeb.render('DashBoard.layouts', qdict));
66         $dialog.find('li').click(function() {
67             var layout = $(this).attr('data-layout');
68             $dialog.dialog('destroy');
69             self.do_change_layout(layout);
70         });
71     },
72     do_change_layout: function(new_layout) {
73         var $dashboard = this.$element.find('.oe-dashboard');
74         var current_layout = $dashboard.attr('data-layout');
75         if (current_layout != new_layout) {
76             var clayout = current_layout.split('-').length,
77                 nlayout = new_layout.split('-').length,
78                 column_diff = clayout - nlayout;
79             if (column_diff > 0) {
80                 var $last_column = $();
81                 $dashboard.find('.oe-dashboard-column').each(function(k, v) {
82                     if (k >= nlayout) {
83                         $(v).find('.oe-dashboard-action').appendTo($last_column);
84                     } else {
85                         $last_column = $(v);
86                     }
87                 });
88             }
89             $dashboard.toggleClass('oe-dashboard-layout_' + current_layout + ' oe-dashboard-layout_' + new_layout);
90             $dashboard.attr('data-layout', new_layout);
91             this.do_save_dashboard();
92         }
93     },
94     on_fold_action: function(e) {
95         var $e = $(e.currentTarget),
96             $action = $e.parents('.oe-dashboard-action:first'),
97             id = parseInt($action.attr('data-id'), 10);
98         if ($e.is('.ui-icon-minusthick')) {
99             this.actions_attrs[id].fold = '1';
100         } else {
101             delete(this.actions_attrs[id].fold);
102         }
103         $e.toggleClass('ui-icon-minusthick ui-icon-plusthick');
104         $action.find('.oe-dashboard-action-content').toggle();
105         this.do_save_dashboard();
106     },
107     on_close_action: function(e) {
108         if (confirm("Are you sure you want to remove this item ?")) {
109             $(e.currentTarget).parents('.oe-dashboard-action:first').remove();
110             this.do_save_dashboard();
111         }
112     },
113     do_save_dashboard: function() {
114         var self = this;
115         var board = {
116                 form_title : this.view.fields_view.arch.attrs.string,
117                 style : this.$element.find('.oe-dashboard').attr('data-layout'),
118                 columns : []
119             };
120         this.$element.find('.oe-dashboard-column').each(function() {
121             var actions = [];
122             $(this).find('.oe-dashboard-action').each(function() {
123                 var action_id = $(this).attr('data-id'),
124                     new_attrs = _.clone(self.actions_attrs[action_id]);
125                 if (new_attrs.domain) {
126                     new_attrs.domain = new_attrs.domain_string;
127                     delete(new_attrs.domain_string);
128                 }
129                 if (new_attrs.context) {
130                     new_attrs.context = new_attrs.context_string;
131                     delete(new_attrs.context_string);
132                 }
133                 actions.push(new_attrs);
134             });
135             board.columns.push(actions);
136         });
137         var arch = QWeb.render('DashBoard.xml', board);
138         this.rpc('/web/view/add_custom', {
139             view_id: this.view.fields_view.view_id,
140             arch: arch
141         }, function() {
142             self.$element.find('.oe-dashboard-link-reset').show();
143         });
144     },
145     on_load_action: function(result, index) {
146         var self = this,
147             action = result.result,
148             action_attrs = this.actions_attrs[action.id],
149             view_mode = action_attrs.view_mode;
150
151         if (action_attrs.context) {
152             action.context = action_attrs.context;
153         }
154         if (action_attrs.domain) {
155             action.domain = action_attrs.domain;
156         }
157         var action_orig = _.extend({}, action);
158
159         if (view_mode && view_mode != action.view_mode) {
160             var action_view_mode = action.view_mode.split(',');
161             action.views = _.map(view_mode.split(','), function(mode) {
162                 if (_.indexOf(action_view_mode, mode) < 0) {
163                     return [false, mode == 'tree' ? 'list': mode];
164                 } else {
165                     mode = mode === 'tree' ? 'list' : mode;
166                     return _.find(action.views, function(view) {
167                         return view[1] == mode;
168                     });
169                 }
170             });
171         }
172
173         action.flags = {
174             search_view : false,
175             sidebar : false,
176             views_switcher : false,
177             action_buttons : false,
178             pager: false,
179             low_profile: true,
180             display_title: false,
181             list: {
182                 selectable: false
183             }
184         };
185         var am = new openerp.web.ActionManager(this);
186         this.action_managers.push(am);
187         am.appendTo($('#' + this.view.element_id + '_action_' + index));
188         am.do_action(action);
189         am.do_action = function(action) {
190             self.do_action(action);
191         }
192         if (am.inner_viewmanager) {
193             am.inner_viewmanager.on_mode_switch.add(function(mode) {
194                 var new_views = [];
195                 _.each(action_orig.views, function(view) {
196                     new_views[view[1] === mode ? 'unshift' : 'push'](view);
197                 });
198                 if (!new_views.length || new_views[0][1] !== mode) {
199                     new_views.unshift([false, mode]);
200                 }
201                 action_orig.views = new_views;
202                 action_orig.res_id = am.inner_viewmanager.dataset.ids[am.inner_viewmanager.dataset.index];
203                 self.do_action(action_orig);
204             });
205         }
206     },
207     render: function() {
208         // We should start with three columns available
209         for (var i = this.node.children.length; i < 3; i++) {
210             this.node.children.push({
211                 tag: 'column',
212                 attrs: {},
213                 children: []
214             });
215         }
216         return QWeb.render(this.template, this);
217     },
218     do_reload: function() {
219         var view_manager = this.view.widget_parent,
220             action_manager = view_manager.widget_parent;
221         this.view.stop();
222         action_manager.do_action(view_manager.action);
223     }
224 });
225 openerp.web.form.DashBoardLegacy = openerp.web.form.DashBoard.extend({
226     render: function() {
227         if (this.node.tag == 'hpaned') {
228             this.node.attrs.style = '2-1';
229         } else if (this.node.tag == 'vpaned') {
230             this.node.attrs.style = '1';
231         }
232         this.node.tag = 'board';
233         _.each(this.node.children, function(child) {
234             if (child.tag.indexOf('child') == 0) {
235                 child.tag = 'column';
236                 var actions = [], first_child = child.children[0];
237                 if (first_child && first_child.tag == 'vpaned') {
238                     _.each(first_child.children, function(subchild) {
239                         actions.push.apply(actions, subchild.children);
240                     });
241                     child.children = actions;
242                 }
243             }
244         });
245         return this._super(this, arguments);
246     }
247 });
248
249 openerp.web.form.widgets.add('hpaned', 'openerp.web.form.DashBoardLegacy');
250 openerp.web.form.widgets.add('vpaned', 'openerp.web.form.DashBoardLegacy');
251 openerp.web.form.widgets.add('board', 'openerp.web.form.DashBoard');
252
253 /*
254  * ConfigOverview
255  * This client action designed to be used as a dashboard widget display
256  * ir.actions.todo in a fancy way
257  */
258 openerp.web.client_actions.add( 'board.config.overview', 'openerp.web_dashboard.ConfigOverview');
259 openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
260     template: 'ConfigOverview',
261     init: function (parent) {
262         this._super(parent);
263         this.dataset = new openerp.web.DataSetSearch(
264                 this, 'ir.actions.todo');
265         this.dataset.domain = [['type', '!=', 'automatic']];
266     },
267     start: function () {
268         this._super();
269         $.when(this.dataset.read_slice(['state', 'action_id', 'category_id']),
270                this.dataset.call('progress'))
271             .then(this.on_records_loaded);
272     },
273     on_records_loaded: function (read_response, progress_response) {
274         var records = read_response,
275            progress = progress_response[0];
276
277         var grouped_todos = _(records).chain()
278             .map(function (record) {
279                 return {
280                     id: record.id,
281                     name: record.action_id[1],
282                     done: record.state !== 'open',
283                     to_do: record.state === 'open',
284                     category: record['category_id'][1] || "Uncategorized"
285                 }
286             })
287             .groupBy(function (record) {return record.category})
288             .value();
289         this.$element.html(QWeb.render('ConfigOverview.content', {
290             completion: 100 * progress.done / progress.total,
291             groups: grouped_todos
292         }));
293         var $progress = this.$element.find('div.oe-config-progress-bar');
294         $progress.progressbar({value: $progress.data('completion')});
295
296         var self = this;
297         this.$element.find('dl')
298             .delegate('input', 'click', function (e) {
299                 // switch todo status
300                 e.stopImmediatePropagation();
301                 var new_state = this.checked ? 'done' : 'open',
302                       todo_id = parseInt($(this).val(), 10);
303                 self.dataset.write(todo_id, {state: new_state}, {}, function () {
304                     self.start();
305                 });
306             })
307             .delegate('li:not(.oe-done)', 'click', function () {
308                 self.widget_parent.widget_parent.widget_parent.do_execute_action({
309                         type: 'object',
310                         name: 'action_launch'
311                     }, self.dataset,
312                     $(this).data('id'), function () {
313                         // after action popup closed, refresh configuration
314                         // thingie
315                         self.start();
316                     });
317             });
318     }
319 });
320
321 /*
322  * Widgets
323  * This client action designed to be used as a dashboard widget display
324  * the html content of a res_widget given as argument
325  */
326 openerp.web.client_actions.add( 'board.home.widgets', 'openerp.web_dashboard.Widget');
327 openerp.web_dashboard.Widget = openerp.web.View.extend(/** @lends openerp.web_dashboard.Widgets# */{
328     template: 'HomeWidget',
329     /**
330      * Initializes a "HomeWidget" client widget: handles the display of a given
331      * res.widget objects in an OpenERP view (mainly a dashboard).
332      *
333      * @constructs openerp.web_dashboard.Widget
334      * @extends openerp.web.View
335      *
336      * @param {Object} parent
337      * @param {Object} options
338      * @param {Number} options.widget_id
339      */
340     init: function (parent, options) {
341         this._super(parent);
342         this.widget_id = options.widget_id;
343     },
344     start: function () {
345         this._super();
346         return new openerp.web.DataSet(this, 'res.widget').read_ids(
347                 [this.widget_id], ['title'], this.on_widget_loaded);
348     },
349     on_widget_loaded: function (widgets) {
350         var widget = widgets[0];
351         var url = _.str.sprintf(
352             '/web_dashboard/widgets/content?session_id=%s&widget_id=%d',
353             this.session.session_id, widget.id);
354         this.$element.html(QWeb.render('HomeWidget.content', {
355             widget: widget,
356             url: url
357         }));
358     }
359 });
360
361 /*
362  * HomeTiles this client action display either the list of application to
363  * install (if none is installed yet) or a list of root menu items
364  */
365 openerp.web.client_actions.add('default_home', 'session.web_dashboard.ApplicationTiles');
366 openerp.web_dashboard.ApplicationTiles = openerp.web.Widget.extend({
367     template: 'web_dashboard.ApplicationTiles',
368     init: function(parent) {
369         this._super(parent);
370     },
371     start: function() {
372         var self = this;
373         var applications = [
374             {module: 'crm', name: 'CRM', menu: 'Sales', help: "Acquire leads, follow opportunities, manage prospects and phone calls, \u2026"},
375         ];
376         var domain = [['core','=',true],['state','=','installed']];
377         var ds = new openerp.web.DataSetSearch(this, 'ir.module.module',{},domain);
378         ds.read_slice(['id'], {}, function(result) {
379             if(result.length) {
380                 self.on_installed_database();
381             } else {
382                 self.on_uninstalled_database();
383             }
384         });
385     },
386     on_uninstalled_database: function() {
387         console.log("UNINSTALLED");
388         this.$element.html("ApplicationInstaller");
389         installer = new openerp.web_dashboard.ApplicationInstaller(this);
390         installer.appendTo(this.$element);
391     },
392     on_installed_database: function() {
393         console.log("INSTALLED");
394         this.$element.html("ApplicationTiles");
395         var self = this;
396         var ds = new openerp.web.DataSetSearch( this, 'ir.ui.menu', null, [['parent_id', '=', false]]);
397         var r = ds.read_slice( ['name', 'web_icon_data', 'web_icon_hover_data'], {}, function (applications) {
398             // Create a matrix of 3*x applications
399             var rows = [];
400             while (applications.length) {
401                 rows.push(applications.splice(0, 3));
402             }
403             var tiles = QWeb.render( 'ApplicationTiles.content', {rows: rows});
404             self.$element.append(tiles).find('.oe-dashboard-home-tile').click(function () {
405                 openerp.webclient.menu.on_menu_click(null, $(this).data('menuid'))
406             });
407         });
408     }
409 });
410
411 /**
412  * ApplicationInstaller
413  * This client action  display a list of applications to install.
414  */
415 openerp.web.client_actions.add( 'board.application.installer', 'openerp.web_dashboard.ApplicationInstaller');
416 openerp.web_dashboard.ApplicationInstaller = openerp.web.View.extend({
417     template: 'web_dashboard.ApplicationInstaller',
418     start: function () {
419         this._super();
420         $('.secondary_menu', this.$element.closest('.openerp')).hide();
421         this.$element.append("Display ir module module kanban view");
422     },
423     /* currenlt unused */
424     on_install_clicked: function() {
425         var Installer = new openerp.web.DataSet(this, 'base.setup.installer');
426         Installer.call('default_get', [], function (installed_modules) {
427             console.log(installed_modules);
428             self.$element.html(QWeb.render('Welcome-Page', {'applications': applications}));
429             self.$element.find('.install-module-link').click(function () {
430                 self.install_module($(this).data('module'), $(this).data('menu'));
431                 return false;
432             });
433         });
434     },
435     install_module: function (module_name, menu_name) {
436         var self = this;
437         var Modules = new openerp.web.DataSetSearch(
438             this, 'ir.module.module', null,
439             [['name', '=', module_name], ['state', '=', 'uninstalled']]);
440         var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade');
441
442         $.blockUI();
443         Modules.read_slice(['id'], {}, function (records) {
444             if (!(records.length === 1)) { $.unblockUI(); return; }
445             Modules.call('state_update',
446                 [_.pluck(records, 'id'), 'to install', ['uninstalled']],
447                 function () {
448                     Upgrade.call('upgrade_module', [[]], function () {
449                         self.run_configuration_wizards(menu_name);
450                     });
451                 }
452             )
453         });
454     },
455     run_configuration_wizards: function (menu_name) {
456         var self = this;
457         new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) {
458             self.widget_parent.widget_parent.do_action(action, function () {
459                 openerp.webclient.do_reload();
460             });
461             self.$element.empty();
462             var dss = new openerp.web.DataSetSearch(this, 'ir.ui.menu', null, [['parent_id', '=', false], ['name', '=', menu_name]]);
463             dss.read_slice(['id'], {}, function(menus) {
464                 if(!(menus.length === 1)) { $.unblockUI(); return; }
465                 $.when(openerp.webclient.menu.on_menu_click(null, menus[0].id)).then($.unblockUI);
466             });
467         });
468     }
469 });
470
471
472 };