odoo/addons/board/static/src/js/dashboard.js

434 lines
16 KiB
JavaScript

openerp.board = function(instance) {
var QWeb = instance.web.qweb,
_t = instance.web._t;
if (!instance.board) {
/** @namespace */
instance.board = {};
}
instance.web.form.DashBoard = instance.web.form.FormWidget.extend({
init: function(view, node) {
this._super(view, node);
this.form_template = 'DashBoard';
this.actions_attrs = {};
this.action_managers = [];
},
start: function() {
var self = this;
this._super.apply(this, arguments);
this.$el.find('.oe_dashboard_column').sortable({
connectWith: '.oe_dashboard_column',
handle: '.oe_header',
scroll: false
}).bind('sortstop', self.do_save_dashboard);
var old_title = this.__parentedParent.get('title');
this.__parentedParent.on('load_record', self, function(){
self.__parentedParent.set({ 'title': old_title});
})
// Events
this.$el.find('.oe_dashboard_link_reset').click(this.on_reset);
this.$el.find('.oe_dashboard_link_change_layout').click(this.on_change_layout);
this.$el.find('h2.oe_header span.oe_header_txt').click(function(ev){
if(ev.target === ev.currentTarget)
self.on_header_string($(ev.target).parent());
});
this.$el.delegate('.oe_dashboard_column .oe_fold', 'click', this.on_fold_action);
this.$el.delegate('.oe_dashboard_column .oe_close', 'click', this.on_close_action);
// Init actions
_.each(this.node.children, function(column, column_index) {
_.each(column.children, function(action, action_index) {
delete(action.attrs.width);
delete(action.attrs.height);
delete(action.attrs.colspan);
var action_id = _.str.toNumber(action.attrs.name);
if (!_.isNaN(action_id)) {
self.rpc('/web/action/load', {action_id: action_id}).done(function(result) {
self.on_load_action(result, column_index + '_' + action_index, action.attrs);
});
}
});
});
},
on_header_string:function(h2){
var self = this;
var span = h2.find('span:first').hide();
var input = h2.find('.oe_header_text').css('visibility','visible');
var attr = h2.closest(".oe_action").data('action_attrs');
var change_string = function(new_name){
attr['string'] = new_name;
span.text(new_name).show();
input.css('visibility','hidden');
self.do_save_dashboard();
}
input.unbind()
.val(span.text())
.change(function(event){
change_string($(this).val());
})
.keyup(function(event){
if(event.keyCode == 27){
//esc key to cancel changes
input.css('visibility','hidden');
span.show();
}
});
},
on_reset: function() {
this.rpc('/web/view/undo_custom', {
view_id: this.view.fields_view.view_id,
reset: true
}).done(this.do_reload);
},
on_change_layout: function() {
var self = this;
var qdict = {
current_layout : this.$el.find('.oe_dashboard').attr('data-layout')
};
var $dialog = instance.web.dialog($('<div>'), {
modal: true,
title: _t("Edit Layout"),
width: 'auto',
height: 'auto'
}).html(QWeb.render('DashBoard.layouts', qdict));
$dialog.find('li').click(function() {
var layout = $(this).attr('data-layout');
$dialog.dialog('destroy');
self.do_change_layout(layout);
});
},
do_change_layout: function(new_layout) {
var $dashboard = this.$el.find('.oe_dashboard');
var current_layout = $dashboard.attr('data-layout');
if (current_layout != new_layout) {
var clayout = current_layout.split('-').length,
nlayout = new_layout.split('-').length,
column_diff = clayout - nlayout;
if (column_diff > 0) {
var $last_column = $();
$dashboard.find('.oe_dashboard_column').each(function(k, v) {
if (k >= nlayout) {
$(v).find('.oe_action').appendTo($last_column);
} else {
$last_column = $(v);
}
});
}
$dashboard.toggleClass('oe_dashboard_layout_' + current_layout + ' oe_dashboard_layout_' + new_layout);
$dashboard.attr('data-layout', new_layout);
this.do_save_dashboard();
}
},
on_fold_action: function(e) {
var $e = $(e.currentTarget),
$action = $e.parents('.oe_action:first'),
id = parseInt($action.attr('data-id'), 10);
if ($e.is('.oe_minimize')) {
$action.data('action_attrs').fold = '1';
} else {
delete($action.data('action_attrs').fold);
}
$e.toggleClass('oe_minimize oe_maximize');
$action.find('.oe_content').toggle();
this.do_save_dashboard();
},
on_close_action: function(e) {
if (confirm(_t("Are you sure you want to remove this item ?"))) {
$(e.currentTarget).parents('.oe_action:first').remove();
this.do_save_dashboard();
}
},
do_save_dashboard: function() {
var self = this;
var board = {
form_title : this.view.fields_view.arch.attrs.string,
style : this.$el.find('.oe_dashboard').attr('data-layout'),
columns : []
};
this.$el.find('.oe_dashboard_column').each(function() {
var actions = [];
$(this).find('.oe_action').each(function() {
var action_id = $(this).attr('data-id'),
new_attrs = _.clone($(this).data('action_attrs'));
if (new_attrs.domain) {
new_attrs.domain = new_attrs.domain_string;
delete(new_attrs.domain_string);
}
if (new_attrs.context) {
new_attrs.context = new_attrs.context_string;
delete(new_attrs.context_string);
}
actions.push(new_attrs);
});
board.columns.push(actions);
});
var arch = QWeb.render('DashBoard.xml', board);
this.rpc('/web/view/add_custom', {
view_id: this.view.fields_view.view_id,
arch: arch
});
},
on_load_action: function(result, index, action_attrs) {
var self = this,
action = result,
view_mode = action_attrs.view_mode;
// evaluate action_attrs context and domain
action_attrs.context_string = action_attrs.context;
action_attrs.context = instance.web.pyeval.eval(
'context', action_attrs.context || {});
action_attrs.domain_string = action_attrs.domain;
action_attrs.domain = instance.web.pyeval.eval(
'domain', action_attrs.domain || [], action_attrs.context);
if (action_attrs.context['dashboard_merge_domains_contexts'] === false) {
// TODO: replace this 6.1 workaround by attribute on <action/>
action.context = action_attrs.context || {};
action.domain = action_attrs.domain || [];
} else {
action.context = instance.web.pyeval.eval(
'contexts', [action.context || {}, action_attrs.context]);
action.domain = instance.web.pyeval.eval(
'domains', [action_attrs.domain, action.domain || []],
action.context)
}
var action_orig = _.extend({ flags : {} }, action);
if (view_mode && view_mode != action.view_mode) {
action.views = _.map(view_mode.split(','), function(mode) {
mode = mode === 'tree' ? 'list' : mode;
return _(action.views).find(function(view) { return view[1] == mode; })
|| [false, mode];
});
}
action.flags = {
search_view : false,
sidebar : false,
views_switcher : false,
action_buttons : false,
pager: false,
low_profile: true,
display_title: false,
list: {
selectable: false
}
};
var am = new instance.web.ActionManager(this),
// FIXME: ideally the dashboard view shall be refactored like kanban.
$action = $('#' + this.view.element_id + '_action_' + index);
$action.parent().data('action_attrs', action_attrs);
this.action_managers.push(am);
am.appendTo($action);
am.do_action(action);
am.do_action = function (action) {
self.do_action(action);
};
if (am.inner_widget) {
var new_form_action = function(id, editable) {
var new_views = [];
_.each(action_orig.views, function(view) {
new_views[view[1] === 'form' ? 'unshift' : 'push'](view);
});
if (!new_views.length || new_views[0][1] !== 'form') {
new_views.unshift([false, 'form']);
}
action_orig.views = new_views;
action_orig.res_id = id;
action_orig.flags = {
form: {
"initial_mode": editable ? "edit" : "view",
}
};
self.do_action(action_orig);
};
var list = am.inner_widget.views.list;
if (list) {
list.deferred.done(function() {
$(list.controller.groups).off('row_link').on('row_link', function(e, id) {
new_form_action(id);
});
});
}
var kanban = am.inner_widget.views.kanban;
if (kanban) {
kanban.deferred.done(function() {
kanban.controller.open_record = function(id, editable) {
new_form_action(id, editable);
};
});
}
}
},
renderElement: function() {
this._super();
var check = _.detect(this.node.children, function(column, column_index) {
return _.detect(column.children,function(element){
return element.tag === "action"? element: false;
});
});
if (!check) {
return this.no_result();
}
// We should start with three columns available
for (var i = this.node.children.length; i < 3; i++) {
this.node.children.push({
tag: 'column',
attrs: {},
children: []
});
}
var rendered = QWeb.render(this.form_template, this);
this.$el.html(rendered);
},
no_result: function() {
if (this.view.options.action.help) {
this.$el.append(
$('<div class="oe_view_nocontent">')
.append($('<div>').html(this.view.options.action.help || " "))
);
}
},
do_reload: function() {
var view_manager = this.view.getParent(),
action_manager = view_manager.getParent();
this.view.destroy();
action_manager.do_action(view_manager.action);
}
});
instance.web.form.DashBoardLegacy = instance.web.form.DashBoard.extend({
renderElement: function() {
if (this.node.tag == 'hpaned') {
this.node.attrs.layout = '2-1';
} else if (this.node.tag == 'vpaned') {
this.node.attrs.layout = '1';
}
this.node.tag = 'board';
_.each(this.node.children, function(child) {
if (child.tag.indexOf('child') == 0) {
child.tag = 'column';
var actions = [], first_child = child.children[0];
if (first_child && first_child.tag == 'vpaned') {
_.each(first_child.children, function(subchild) {
actions.push.apply(actions, subchild.children);
});
child.children = actions;
}
}
});
this._super(this);
}
});
instance.web.form.tags.add('hpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('vpaned', 'instance.web.form.DashBoardLegacy');
instance.web.form.tags.add('board', 'instance.web.form.DashBoard');
instance.board.AddToDashboard = instance.web.search.Input.extend({
template: 'SearchView.addtodashboard',
_in_drawer: true,
start: function () {
var self = this;
this.$el
.on('click', 'h4', this.proxy('show_option'))
.on('submit', 'form', function (e) {
e.preventDefault();
self.add_dashboard();
});
return this.load_data().done(this.proxy("render_data"));
},
load_data:function(){
var board = new instance.web.Model('board.board');
return board.call('list', [board.context()]);
},
_x:function() {
if (!instance.webclient) { return $.Deferred().reject(); }
var dashboard_menu = instance.webclient.menu.data.data.children;
return new instance.web.Model('ir.model.data')
.query(['res_id'])
.filter([['name','=','menu_reporting_dashboard']])
.first().then(function (result) {
var menu = _(dashboard_menu).chain()
.pluck('children')
.flatten(true)
.find(function (child) { return child.id === result.res_id; })
.value();
return menu ? menu.children : [];
});
},
render_data: function(dashboard_choices){
var selection = instance.web.qweb.render(
"SearchView.addtodashboard.selection", {
selections: dashboard_choices});
this.$("input").before(selection)
},
add_dashboard: function(){
var self = this;
var getParent = this.getParent();
var view_parent = this.getParent().getParent();
if (! view_parent.action || ! this.$el.find("select").val()) {
this.do_warn("Can't find dashboard action");
return;
}
var data = getParent.build_search_data();
var context = new instance.web.CompoundContext(getParent.dataset.get_context() || []);
var domain = new instance.web.CompoundDomain(getParent.dataset.get_domain() || []);
_.each(data.contexts, context.add, context);
_.each(data.domains, domain.add, domain);
context.add({
group_by: instance.web.pyeval.eval('groupbys', data.groupbys || [])
});
var c = instance.web.pyeval.eval('context', context);
for(var k in c) {
if (c.hasOwnProperty(k) && /^search_default_/.test(k)) {
delete c[k];
}
}
// TODO: replace this 6.1 workaround by attribute on <action/>
c.dashboard_merge_domains_contexts = false;
var d = instance.web.pyeval.eval('domain', domain);
this.rpc('/board/add_to_dashboard', {
menu_id: this.$el.find("select").val(),
action_id: view_parent.action.id,
context_to_save: c,
domain: d,
view_mode: view_parent.active_view,
name: this.$el.find("input").val()
}).done(function(r) {
if (r === false) {
self.do_warn("Could not add filter to dashboard");
} else {
self.$el.toggleClass('oe_opened');
self.do_notify("Filter added to dashboard", '');
}
});
},
show_option:function(){
this.$el.toggleClass('oe_opened');
if (! this.$el.hasClass('oe_opened'))
return;
this.$("input").val(this.getParent().fields_view.name || "" );
}
});
instance.web.SearchView.include({
add_common_inputs: function() {
this._super();
var vm = this.getParent().getParent();
if (vm.inner_action && vm.inner_action.id && vm.inner_action.views) {
(new instance.board.AddToDashboard(this));
}
}
});
};