summaryrefslogtreecommitdiff
path: root/addons/base/static/src
diff options
context:
space:
mode:
authorFabien Meghazi <fme@openerp.com>2011-07-26 23:00:05 +0200
committerFabien Meghazi <fme@openerp.com>2011-07-26 23:00:05 +0200
commitd0234fa5dd424e7722443fda7e41f955d857027a (patch)
treec5fef3f26566633ef0847217bc469f23fc446852 /addons/base/static/src
parent5070784ba2b04d7ffb8935c9cf01dacfd7f03b26 (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.css4
-rw-r--r--addons/base/static/src/js/form.js102
-rw-r--r--addons/base/static/src/js/list.js19
-rw-r--r--addons/base/static/src/js/views.js149
-rw-r--r--addons/base/static/src/xml/base.xml54
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 + '&amp;model=ir.attachment&amp;id=' + attachment.id
- + '&amp;field=datas' + '&amp;fieldname=name' + '&amp;t=' + (new Date().getTime())"/>
+ + '&amp;field=datas&amp;fieldname=name&amp;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>