diff options
| author | Fabien Meghazi <fme@openerp.com> | 2011-07-26 23:00:05 +0200 |
|---|---|---|
| committer | Fabien Meghazi <fme@openerp.com> | 2011-07-26 23:00:05 +0200 |
| commit | d0234fa5dd424e7722443fda7e41f955d857027a (patch) | |
| tree | c5fef3f26566633ef0847217bc469f23fc446852 /addons/base/static/src | |
| parent | 5070784ba2b04d7ffb8935c9cf01dacfd7f03b26 (diff) | |
[IMP] new Sidebar controller
Now, the views are responsible of the management of their own sidebar.
There is one sidebar per view.
The viewmanager creates the divs for each sidebar (as it does for each view).
The new Sidebar controller allows custom section with their own controller.
bzr revid: fme@openerp.com-20110726210005-xyalvw764y2xhvte
Diffstat (limited to 'addons/base/static/src')
| -rw-r--r-- | addons/base/static/src/css/base.css | 4 | ||||
| -rw-r--r-- | addons/base/static/src/js/form.js | 102 | ||||
| -rw-r--r-- | addons/base/static/src/js/list.js | 19 | ||||
| -rw-r--r-- | addons/base/static/src/js/views.js | 149 | ||||
| -rw-r--r-- | addons/base/static/src/xml/base.xml | 54 |
5 files changed, 192 insertions, 136 deletions
diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index dbb7d101f96..bbf8cba0fe7 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -1020,6 +1020,10 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */ .openerp .closed-sidebar .toggle-sidebar { border-left: none; } +.openerp li.oe_sidebar_print { + padding-left: 20px; + background: 1px 3px url(../img/icons/gtk-print.png) no-repeat; +} .openerp.kitten-mode-activated .main_table { background: url(http://placekitten.com/g/1500/800) repeat; diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 25dcca611bd..e66a073643c 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -1,7 +1,7 @@ openerp.base.form = function (openerp) { openerp.base.views.add('form', 'openerp.base.FormView'); -openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{ +openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormView# */{ /** * Indicates that this view is not searchable, and thus that no search * view should be displayed (if there is one active). @@ -19,6 +19,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV */ init: function(parent, element_id, dataset, view_id, options) { this._super(parent, element_id); + this.set_default_options(); this.view_manager = parent || new openerp.base.NullViewManager(); this.dataset = dataset; this.model = dataset.model; @@ -53,10 +54,14 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV context.add(this.view_manager.action.context); } return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id, - toolbar:!!this.flags.sidebar, context: context}, this.on_loaded); + toolbar: this.options.sidebar, context: context}, this.on_loaded); } }, stop: function() { + if (this.sidebar) { + this.sidebar.attachments.stop(); + this.sidebar.stop(); + } _.each(this.widgets, function(w) { w.stop(); }); @@ -85,12 +90,16 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV $('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600}); }); - if(this.view_manager.sidebar) - this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); + if (this.options.sidebar && this.options.sidebar_id) { + this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id); + this.sidebar.start(); + this.sidebar.attachments = new openerp.base.form.SidebarAttachments(this.sidebar, this.sidebar.add_section("Attachments"), this); + this.sidebar.add_toolbar(data.fields_view.toolbar); + this.sidebar.do_unfold(); + } this.has_been_loaded.resolve(); }, do_show: function () { - var self = this; var promise; if (this.dataset.index === null) { // null index means we should start a new record @@ -98,13 +107,17 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV } else { promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); } - self.$element.show(); - if(this.view_manager.sidebar) - this.view_manager.sidebar.do_refresh(true); + this.$element.show(); + if (this.sidebar) { + this.sidebar.$element.show(); + } return promise; }, do_hide: function () { this.$element.hide(); + if (this.sidebar) { + this.sidebar.$element.hide(); + } }, on_record_loaded: function(record) { if (!record) { @@ -144,7 +157,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.on_form_changed(); this.show_invalid = this.ready = true; this.do_update_pager(record.id == null); - this.do_update_sidebar(); + if (this.sidebar) { + this.sidebar.attachments.do_update(); + } if (this.default_focus_field) { this.default_focus_field.focus(); } @@ -389,7 +404,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.dataset.index = 0; } this.do_update_pager(); - this.do_update_sidebar(); + if (this.sidebar) { + this.sidebar.attachments.do_update(); + } this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id); if (success) { success(_.extend(r, {created: true})); @@ -406,34 +423,55 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV do_cancel: function () { this.notification.notify("Cancelling form"); }, - do_update_sidebar: function() { - if (this.flags.sidebar === false || this.view_manager.sidebar === undefined) { - return; + reload: function() { + if (this.datarecord.id) { + this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); + } else { + this.on_button_new(); } - if (!this.datarecord.id) { + }, + get_fields_values: function() { + var values = {}; + _.each(this.fields, function(value, key) { + var val = value.get_value(); + values[key] = val; + }); + return values; + } +}); + +/** @namespace */ +openerp.base.form = {}; + +openerp.base.form.SidebarAttachments = openerp.base.Controller.extend({ + init: function(parent, element_id, form_view) { + this._super(parent, element_id); + this.view = form_view; + }, + do_update: function() { + if (!this.view.datarecord.id) { this.on_attachments_loaded([]); } else { (new openerp.base.DataSetSearch( - this, 'ir.attachment', this.dataset.get_context(), - [['res_model', '=', this.dataset.model], - ['res_id', '=', this.datarecord.id], + this, 'ir.attachment', this.view.dataset.get_context(), + [['res_model', '=', this.view.dataset.model], + ['res_id', '=', this.view.datarecord.id], ['type', 'in', ['binary', 'url']]])).read_slice( ['name', 'url', 'type'], false, false, this.on_attachments_loaded); } }, on_attachments_loaded: function(attachments) { - this.$sidebar = this.view_manager.sidebar.$element.find('.sidebar-attachments'); this.attachments = attachments; - this.$sidebar.html(QWeb.render('FormView.sidebar.attachments', this)); - this.$sidebar.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete); - this.$sidebar.find('.oe-binary-file').change(this.on_attachment_changed); + this.$element.html(QWeb.render('FormView.sidebar.attachments', this)); + this.$element.find('.oe-binary-file').change(this.on_attachment_changed); + this.$element.find('.oe-sidebar-attachment-delete').click(this.on_attachment_delete); }, on_attachment_changed: function(e) { - window[this.element_id + '_iframe'] = this.do_update_sidebar; + window[this.element_id + '_iframe'] = this.do_update; var $e = $(e.target); if ($e.val() != '') { - this.$sidebar.find('form.oe-binary-form').submit(); + this.$element.find('form.oe-binary-form').submit(); $e.parent().find('input[type=file]').attr('disabled', 'true'); $e.parent().find('button').attr('disabled', 'true').find('img, span').toggle(); } @@ -450,27 +488,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted"); }); } - }, - reload: function() { - if (this.datarecord.id) { - this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); - } else { - this.on_button_new(); - } - }, - get_fields_values: function() { - var values = {}; - _.each(this.fields, function(value, key) { - var val = value.get_value(); - values[key] = val; - }); - return values; } }); -/** @namespace */ -openerp.base.form = {}; - openerp.base.form.compute_domain = function(expr, fields) { var stack = []; for (var i = expr.length - 1; i >= 0; i--) { diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index a2fca3aa89e..a4e516721ca 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -102,6 +102,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi */ init: function(parent, element_id, dataset, view_id, options) { this._super(parent, element_id); + this.set_default_options(); this.view_manager = parent || new openerp.base.NullViewManager(); this.dataset = dataset; this.model = dataset.model; @@ -267,9 +268,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi }) .val(self._limit || 'NaN'); }); - if(this.view_manager.sidebar) - this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); - + if (this.options.sidebar && this.options.sidebar_id) { + this.sidebar = new openerp.base.Sidebar(this, this.options.sidebar_id); + this.sidebar.start(); + this.sidebar.add_toolbar(data.fields_view.toolbar); + } }, /** * Configures the ListView pager based on the provided dataset's information @@ -393,16 +396,20 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi }, do_show: function () { this.$element.show(); + if (this.sidebar) { + this.sidebar.$element.show(); + } if (this.hidden) { this.$element.find('.oe-listview-content').append( this.groups.apoptosis().render()); this.hidden = false; } - if(this.view_manager.sidebar) - this.view_manager.sidebar.do_refresh(true); }, do_hide: function () { this.$element.hide(); + if (this.sidebar) { + this.sidebar.$element.hide(); + } this.hidden = true; }, /** @@ -422,7 +429,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi model: this.model, view_id: this.view_id, context: this.dataset.get_context(), - toolbar: !!this.flags.sidebar + toolbar: this.options.sidebar }, callback); } }, diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index 1b5452bb5a3..b98b0bc637f 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -120,7 +120,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;}); this.views = {}; this.flags = this.flags || {}; - this.sidebar = new openerp.base.NullSidebar(); this.registry = openerp.base.views; }, /** @@ -134,7 +133,12 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ self.on_mode_switch($(this).data('view-type')); }); _.each(this.views_src, function(view) { - self.views[view.view_type] = $.extend({}, view, {controller: null}); + self.views[view.view_type] = $.extend({}, view, { + controller : null, + options : _.extend({ + sidebar_id : self.element_id + '_sidebar_' + view.view_type + }, self.flags) + }); }); if (this.flags.views_switcher === false) { this.$element.find('.oe_vm_switch').hide(); @@ -158,7 +162,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ if (!view.controller) { // Lazy loading of views var controllerclass = this.registry.get_object(view_type); - var controller = new controllerclass( this, this.element_id + "_view_" + view_type, + var controller = new controllerclass(this, this.element_id + '_view_' + view_type, this.dataset, view.view_id, view.options); if (view.embedded_view) { controller.set_embedded_view(view.embedded_view); @@ -275,7 +279,6 @@ openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.b if(parent) this.session = parent.session; this.action = {flags: {}}; - this.sidebar = new openerp.base.NullSidebar(); } }); @@ -300,19 +303,10 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ // Not elegant but allows to avoid flickering of SearchView#do_hide this.flags.search_view = this.flags.pager = this.flags.sidebar = this.flags.action_buttons = false; } - if (this.flags.sidebar) { - this.sidebar = new openerp.base.Sidebar(null, this); - } }, start: function() { var inital_view_loaded = this._super(); - // init sidebar - if (this.flags.sidebar) { - this.$element.find('.view-manager-main-sidebar').html(this.sidebar.render()); - this.sidebar.start(); - } - var search_defaults = {}; _.each(this.action.context, function (value, key) { var match = /^search_default_(.*)$/.exec(key); @@ -337,7 +331,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ }, stop: function() { // should be replaced by automatic destruction implemented in BaseWidget - this.sidebar.stop(); this._super(); }, /** @@ -364,62 +357,88 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ } }); -openerp.base.Sidebar = openerp.base.BaseWidget.extend({ - template: "ViewManager.sidebar", - init: function(parent, view_manager) { - this._super(parent, view_manager.session); - this.view_manager = view_manager; - this.sections = []; - }, - set_toolbar: function(toolbar) { - this.sections = []; - var self = this; - _.each([["print", "Reports"], ["action", "Actions"], ["relate", "Links"]], function(type) { - if (toolbar[type[0]].length == 0) - return; - var section = {elements:toolbar[type[0]], label:type[1]}; - self.sections.push(section); - }); - this.do_refresh(true); +openerp.base.Sidebar = openerp.base.Controller.extend({ + init: function(parent, element_id) { + this._super(parent, element_id); + this.items = {}; }, - do_refresh: function(new_view) { - var view = this.view_manager.active_view; - var the_condition = this.sections.length > 0 && _.detect(this.sections, - function(x) {return x.elements.length > 0;}) != undefined - && (!new_view || view != 'list'); - - this.$element.toggleClass('open-sidebar', the_condition) - .toggleClass('closed-sidebar', !the_condition); - - this.$element.html(QWeb.render("ViewManager.sidebar.internal", { sidebar: this, view: view })); - + start: function() { var self = this; + this._super(this, arguments); + this.$element.html(QWeb.render('Sidebar')); this.$element.find(".toggle-sidebar").click(function(e) { - self.$element.toggleClass('open-sidebar closed-sidebar'); - e.stopPropagation(); - e.preventDefault(); + self.do_toggle(); }); - - this.$element.find("a.oe_sidebar_action_a").click(function(e) { - var $this = jQuery(this); - var index = $this.attr("data-index").split('-'); - var action = self.sections[index[0]].elements[index[1]]; - action.flags = { - new_window : true - }; - self.session.action_manager.do_action(action); - e.stopPropagation(); - e.preventDefault(); + }, + add_toolbar: function(toolbar) { + var self = this; + _.each([['print', "Reports"], ['action', "Actions"], ['relate', "Links"]], function(type) { + var items = toolbar[type[0]]; + if (items.length) { + for (var i = 0; i < items.length; i++) { + items[i] = { + label: items[i]['name'], + action: items[i], + classname: 'oe_sidebar_' + type[0] + } + } + self.add_section(type[1], items); + } }); }, - start: function() { - this._super(); - this.do_refresh(false); + add_section: function(name, items) { + // For each section, we pass a name/label and optionally an array of items. + // If no items are passed, then the section will be created as a custom section + // returning back an element_id to be used by a custom controller. + // Else, the section is a standard section with items displayed as links. + // An item is a dictonary : { + // label: label to be displayed for the link, + // action: action to be launch when the link is clicked, + // callback: a function to be executed when the link is clicked, + // classname: optionnal dom class name for the line, + // } + // Note: The item should have one action or/and a callback + var self = this, + section_id = _.uniqueId(this.element_id + '_section_'); + if (items) { + for (var i = 0; i < items.length; i++) { + items[i].element_id = _.uniqueId(section_id + '_item_'); + this.items[items[i].element_id] = items[i]; + } + } + var $section = $(QWeb.render("Sidebar.section", { + section_id: section_id, + name: name, + items: items + })); + if (items) { + $section.find('a.oe_sidebar_action_a').click(function() { + var item = self.items[$(this).attr('id')]; + if (item.callback) { + item.callback(); + } + if (item.action) { + item.action.flags = item.action.flags || {}; + item.action.flags.new_window = true; + self.do_action(item.action); + } + return false; + }); + } + $section.appendTo(this.$element.find('div.sidebar-actions')); + return section_id; + }, + do_fold: function() { + this.$element.addClass('closed-sidebar').removeClass('open-sidebar'); + }, + do_unfold: function() { + this.$element.addClass('open-sidebar').removeClass('closed-sidebar'); + }, + do_toggle: function() { + this.$element.toggleClass('open-sidebar closed-sidebar'); } }); -openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar); - openerp.base.Export = openerp.base.Dialog.extend({ dialog_title: "Export", template: 'ExportDialog', @@ -440,6 +459,14 @@ openerp.base.Export = openerp.base.Dialog.extend({ }); openerp.base.View = openerp.base.Controller.extend({ + set_default_options: function(options) { + this.options = options || {}; + _.defaults(this.options, { + // All possible views options should be defaulted here + sidebar_id: null, + sidebar: true + }); + }, /** * Fetches and executes the action identified by ``action_data``. * diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index 0f7c3f3d51f..10d1539cde1 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -232,10 +232,32 @@ </t> </td> <td class="view-manager-main-sidebar" height="100%"> + <t t-foreach="views" t-as="view"> + <div t-attf-id="#{prefix}_sidebar_#{view.view_type}" class="sidebar-main-div closed-sidebar" style="display: none"/> + </t> </td> </tr> </table> </t> +<t t-name="Sidebar"> + <a class="toggle-sidebar"></a> + <div class="sidebar-content"> + <div class="sidebar-actions"> + </div> + </div> +</t> +<t t-name="Sidebar.section"> + <h2><t t-esc="name"/></h2> + <div t-att-id="section_id"> + <ul t-if="items"> + <li t-foreach="items" t-as="item" t-att-class="item.classname"> + <a class="oe_sidebar_action_a" t-att-id="item.element_id" href="#"> + <t t-esc="item.label"/> + </a> + </li> + </ul> + </div> +</t> <table t-name="ListView" class="oe-listview-content"> <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/> <thead class="ui-widget-header"> @@ -360,21 +382,20 @@ <t t-raw="frame.render()"/> </t> <t t-name="FormView.sidebar.attachments"> - <h2>Attachments</h2> <div class="oe-sidebar-attachments-toolbar"> <div class="oe-binary-file-set" style="float: right"> <form class="oe-binary-form" t-attf-target="#{element_id}_iframe" method="post" enctype="multipart/form-data" action="/base/binary/upload_attachment"> <input type="hidden" name="session_id" t-att-value="session.session_id"/> <input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/> - <input type="hidden" name="model" t-att-value="dataset.model"/> - <input type="hidden" name="id" t-att-value="datarecord.id"/> + <input type="hidden" name="model" t-att-value="view.dataset.model"/> + <input type="hidden" name="id" t-att-value="view.datarecord.id"/> <button class="button" type="button"> <img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/> <span>Add</span> </button> <input type="file" class="oe-binary-file" name="ufile" title="Add attachment" - t-att-onclick="datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/> + t-att-onclick="view.datarecord.id ? null : 'alert(\'No record selected ! You can only attach to existing record.\'); return false;'"/> </form> <iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe> </div> @@ -384,7 +405,7 @@ <li t-foreach="attachments" t-as="attachment"> <t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/base/binary/saveas?session_id=' + session.session_id + '&model=ir.attachment&id=' + attachment.id - + '&field=datas' + '&fieldname=name' + '&t=' + (new Date().getTime())"/> + + '&field=datas&fieldname=name&t=' + (new Date().getTime())"/> <a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank"> <t t-esc="attachment.name"/> </a> @@ -849,29 +870,6 @@ </t> </select> </t> -<t t-name="ViewManager.sidebar"> - <div t-att-id="element_id" class="sidebar-main-div closed-sidebar"> - - </div> -</t> -<t t-name="ViewManager.sidebar.internal"> - <a class="toggle-sidebar"></a> - <div class="sidebar-content"> - <div class="sidebar-attachments" t-if="view == 'form'"> </div> - <div class="sidebar-actions"> - <t t-foreach="sidebar.sections" t-as="section" t-if="section.elements.length"> - <h2><t t-esc="section.label"/></h2> - <ul> - <li t-foreach="section.elements" t-as="element"> - <a class="oe_sidebar_action_a" t-attf-data-index="#{section_index}-#{element_index}" href="#"> - <t t-esc="element.name"/> - </a> - </li> - </ul> - </t> - </div> - </div> -</t> <t t-name="DialogWarning"> <table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning"> <tr> |
