[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
This commit is contained in:
Fabien Meghazi 2011-07-26 23:00:05 +02:00
parent 5070784ba2
commit d0234fa5dd
5 changed files with 210 additions and 154 deletions

View File

@ -1020,6 +1020,10 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
.openerp .closed-sidebar .toggle-sidebar { .openerp .closed-sidebar .toggle-sidebar {
border-left: none; 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 { .openerp.kitten-mode-activated .main_table {
background: url(http://placekitten.com/g/1500/800) repeat; background: url(http://placekitten.com/g/1500/800) repeat;

View File

@ -1,7 +1,7 @@
openerp.base.form = function (openerp) { openerp.base.form = function (openerp) {
openerp.base.views.add('form', 'openerp.base.FormView'); 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 * Indicates that this view is not searchable, and thus that no search
* view should be displayed (if there is one active). * 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) { init: function(parent, element_id, dataset, view_id, options) {
this._super(parent, element_id); this._super(parent, element_id);
this.set_default_options();
this.view_manager = parent || new openerp.base.NullViewManager(); this.view_manager = parent || new openerp.base.NullViewManager();
this.dataset = dataset; this.dataset = dataset;
this.model = dataset.model; 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); context.add(this.view_manager.action.context);
} }
return this.rpc("/base/formview/load", {"model": this.model, "view_id": this.view_id, 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() { stop: function() {
if (this.sidebar) {
this.sidebar.attachments.stop();
this.sidebar.stop();
}
_.each(this.widgets, function(w) { _.each(this.widgets, function(w) {
w.stop(); 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}); $('<xmp>' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
}); });
if(this.view_manager.sidebar) if (this.options.sidebar && this.options.sidebar_id) {
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); 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(); this.has_been_loaded.resolve();
}, },
do_show: function () { do_show: function () {
var self = this;
var promise; var promise;
if (this.dataset.index === null) { if (this.dataset.index === null) {
// null index means we should start a new record // 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 { } else {
promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); promise = this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
} }
self.$element.show(); this.$element.show();
if(this.view_manager.sidebar) if (this.sidebar) {
this.view_manager.sidebar.do_refresh(true); this.sidebar.$element.show();
}
return promise; return promise;
}, },
do_hide: function () { do_hide: function () {
this.$element.hide(); this.$element.hide();
if (this.sidebar) {
this.sidebar.$element.hide();
}
}, },
on_record_loaded: function(record) { on_record_loaded: function(record) {
if (!record) { if (!record) {
@ -144,7 +157,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
this.on_form_changed(); this.on_form_changed();
this.show_invalid = this.ready = true; this.show_invalid = this.ready = true;
this.do_update_pager(record.id == null); this.do_update_pager(record.id == null);
this.do_update_sidebar(); if (this.sidebar) {
this.sidebar.attachments.do_update();
}
if (this.default_focus_field) { if (this.default_focus_field) {
this.default_focus_field.focus(); 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.dataset.index = 0;
} }
this.do_update_pager(); 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); this.notification.notify("Record created", "The record has been created with id #" + this.datarecord.id);
if (success) { if (success) {
success(_.extend(r, {created: true})); success(_.extend(r, {created: true}));
@ -406,51 +423,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
do_cancel: function () { do_cancel: function () {
this.notification.notify("Cancelling form"); this.notification.notify("Cancelling form");
}, },
do_update_sidebar: function() {
if (this.flags.sidebar === false || this.view_manager.sidebar === undefined) {
return;
}
if (!this.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],
['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);
},
on_attachment_changed: function(e) {
window[this.element_id + '_iframe'] = this.do_update_sidebar;
var $e = $(e.target);
if ($e.val() != '') {
this.$sidebar.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();
}
},
on_attachment_delete: function(e) {
var self = this, $e = $(e.currentTarget);
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
this.rpc('/base/dataset/unlink', {
model: 'ir.attachment',
ids: [parseInt($e.attr('data-id'))]
}, function(r) {
$e.parent().remove();
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
});
}
},
reload: function() { reload: function() {
if (this.datarecord.id) { if (this.datarecord.id) {
this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded);
@ -471,6 +443,54 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV
/** @namespace */ /** @namespace */
openerp.base.form = {}; 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.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.attachments = attachments;
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;
var $e = $(e.target);
if ($e.val() != '') {
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();
}
},
on_attachment_delete: function(e) {
var self = this, $e = $(e.currentTarget);
var name = _.trim($e.parent().find('a.oe-sidebar-attachments-link').text());
if (confirm("Do you really want to delete the attachment " + name + " ?")) {
this.rpc('/base/dataset/unlink', {
model: 'ir.attachment',
ids: [parseInt($e.attr('data-id'))]
}, function(r) {
$e.parent().remove();
self.notification.notify("Delete an attachment", "The attachment '" + name + "' has been deleted");
});
}
}
});
openerp.base.form.compute_domain = function(expr, fields) { openerp.base.form.compute_domain = function(expr, fields) {
var stack = []; var stack = [];
for (var i = expr.length - 1; i >= 0; i--) { for (var i = expr.length - 1; i >= 0; i--) {

View File

@ -102,6 +102,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
*/ */
init: function(parent, element_id, dataset, view_id, options) { init: function(parent, element_id, dataset, view_id, options) {
this._super(parent, element_id); this._super(parent, element_id);
this.set_default_options();
this.view_manager = parent || new openerp.base.NullViewManager(); this.view_manager = parent || new openerp.base.NullViewManager();
this.dataset = dataset; this.dataset = dataset;
this.model = dataset.model; this.model = dataset.model;
@ -267,9 +268,11 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
}) })
.val(self._limit || 'NaN'); .val(self._limit || 'NaN');
}); });
if(this.view_manager.sidebar) if (this.options.sidebar && this.options.sidebar_id) {
this.view_manager.sidebar.set_toolbar(data.fields_view.toolbar); 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 * 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 () { do_show: function () {
this.$element.show(); this.$element.show();
if (this.sidebar) {
this.sidebar.$element.show();
}
if (this.hidden) { if (this.hidden) {
this.$element.find('.oe-listview-content').append( this.$element.find('.oe-listview-content').append(
this.groups.apoptosis().render()); this.groups.apoptosis().render());
this.hidden = false; this.hidden = false;
} }
if(this.view_manager.sidebar)
this.view_manager.sidebar.do_refresh(true);
}, },
do_hide: function () { do_hide: function () {
this.$element.hide(); this.$element.hide();
if (this.sidebar) {
this.sidebar.$element.hide();
}
this.hidden = true; this.hidden = true;
}, },
/** /**
@ -422,7 +429,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
model: this.model, model: this.model,
view_id: this.view_id, view_id: this.view_id,
context: this.dataset.get_context(), context: this.dataset.get_context(),
toolbar: !!this.flags.sidebar toolbar: this.options.sidebar
}, callback); }, callback);
} }
}, },

View File

@ -120,7 +120,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;}); {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
this.views = {}; this.views = {};
this.flags = this.flags || {}; this.flags = this.flags || {};
this.sidebar = new openerp.base.NullSidebar();
this.registry = openerp.base.views; this.registry = openerp.base.views;
}, },
/** /**
@ -134,7 +133,12 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
self.on_mode_switch($(this).data('view-type')); self.on_mode_switch($(this).data('view-type'));
}); });
_.each(this.views_src, function(view) { _.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) { if (this.flags.views_switcher === false) {
this.$element.find('.oe_vm_switch').hide(); this.$element.find('.oe_vm_switch').hide();
@ -158,7 +162,7 @@ openerp.base.ViewManager = openerp.base.Controller.extend({
if (!view.controller) { if (!view.controller) {
// Lazy loading of views // Lazy loading of views
var controllerclass = this.registry.get_object(view_type); 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); this.dataset, view.view_id, view.options);
if (view.embedded_view) { if (view.embedded_view) {
controller.set_embedded_view(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) if(parent)
this.session = parent.session; this.session = parent.session;
this.action = {flags: {}}; 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 // 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; 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() { start: function() {
var inital_view_loaded = this._super(); 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 = {}; var search_defaults = {};
_.each(this.action.context, function (value, key) { _.each(this.action.context, function (value, key) {
var match = /^search_default_(.*)$/.exec(key); var match = /^search_default_(.*)$/.exec(key);
@ -337,7 +331,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
}, },
stop: function() { stop: function() {
// should be replaced by automatic destruction implemented in BaseWidget // should be replaced by automatic destruction implemented in BaseWidget
this.sidebar.stop();
this._super(); this._super();
}, },
/** /**
@ -364,62 +357,88 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
} }
}); });
openerp.base.Sidebar = openerp.base.BaseWidget.extend({ openerp.base.Sidebar = openerp.base.Controller.extend({
template: "ViewManager.sidebar", init: function(parent, element_id) {
init: function(parent, view_manager) { this._super(parent, element_id);
this._super(parent, view_manager.session); this.items = {};
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);
},
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 }));
var self = this;
this.$element.find(".toggle-sidebar").click(function(e) {
self.$element.toggleClass('open-sidebar closed-sidebar');
e.stopPropagation();
e.preventDefault();
});
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();
});
}, },
start: function() { start: function() {
this._super(); var self = this;
this.do_refresh(false); this._super(this, arguments);
this.$element.html(QWeb.render('Sidebar'));
this.$element.find(".toggle-sidebar").click(function(e) {
self.do_toggle();
});
},
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);
}
});
},
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({ openerp.base.Export = openerp.base.Dialog.extend({
dialog_title: "Export", dialog_title: "Export",
template: 'ExportDialog', template: 'ExportDialog',
@ -440,6 +459,14 @@ openerp.base.Export = openerp.base.Dialog.extend({
}); });
openerp.base.View = openerp.base.Controller.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``. * Fetches and executes the action identified by ``action_data``.
* *

View File

@ -232,10 +232,32 @@
</t> </t>
</td> </td>
<td class="view-manager-main-sidebar" height="100%"> <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> </td>
</tr> </tr>
</table> </table>
</t> </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"> <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)"/> <t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
<thead class="ui-widget-header"> <thead class="ui-widget-header">
@ -360,21 +382,20 @@
<t t-raw="frame.render()"/> <t t-raw="frame.render()"/>
</t> </t>
<t t-name="FormView.sidebar.attachments"> <t t-name="FormView.sidebar.attachments">
<h2>Attachments</h2>
<div class="oe-sidebar-attachments-toolbar"> <div class="oe-sidebar-attachments-toolbar">
<div class="oe-binary-file-set" style="float: right"> <div class="oe-binary-file-set" style="float: right">
<form class="oe-binary-form" t-attf-target="#{element_id}_iframe" <form class="oe-binary-form" t-attf-target="#{element_id}_iframe"
method="post" enctype="multipart/form-data" action="/base/binary/upload_attachment"> 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="session_id" t-att-value="session.session_id"/>
<input type="hidden" name="callback" t-attf-value="#{element_id}_iframe"/> <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="model" t-att-value="view.dataset.model"/>
<input type="hidden" name="id" t-att-value="datarecord.id"/> <input type="hidden" name="id" t-att-value="view.datarecord.id"/>
<button class="button" type="button"> <button class="button" type="button">
<img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/> <img src="/base/static/src/img/throbber.gif" width="16" height="16" style="display: none"/>
<span>Add</span> <span>Add</span>
</button> </button>
<input type="file" class="oe-binary-file" name="ufile" title="Add attachment" <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> </form>
<iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe> <iframe t-attf-id="#{element_id}_iframe" t-attf-name="#{element_id}_iframe" style="display: none"> </iframe>
</div> </div>
@ -384,7 +405,7 @@
<li t-foreach="attachments" t-as="attachment"> <li t-foreach="attachments" t-as="attachment">
<t t-if="attachment.type == 'binary'" t-set="attachment.url" t-value="'/base/binary/saveas?session_id=' <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 + 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"> <a class="oe-sidebar-attachments-link" t-att-href="attachment.url" target="_blank">
<t t-esc="attachment.name"/> <t t-esc="attachment.name"/>
</a> </a>
@ -849,29 +870,6 @@
</t> </t>
</select> </select>
</t> </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"> <t t-name="DialogWarning">
<table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning"> <table cellspacing="0" cellpadding="0" border="0" class="oe-dialog-warning">
<tr> <tr>