[FIX] attempt to make editability handling more logical and simpler to manage.

Also less buggy, with a bit o' luck

bzr revid: xmo@openerp.com-20120724170550-150vimuk6bvzh8y8
This commit is contained in:
Xavier Morel 2012-07-24 19:05:50 +02:00
parent da361d1042
commit 38cb3de518
4 changed files with 63 additions and 46 deletions

View File

@ -3027,8 +3027,11 @@ instance.web.form.FieldOne2Many = instance.web.form.AbstractField.extend({
this.viewmanager.on_controller_inited.add_last(function(view_type, controller) {
controller.o2m = self;
if (view_type == "list") {
if (self.get("effective_readonly"))
controller.set_editable(false);
if (self.get("effective_readonly")) {
controller.on('edit:before', self, function (e) {
e.cancel = true;
});
}
} else if (view_type === "form") {
if (self.get("effective_readonly")) {
$(".oe_form_buttons", controller.$element).children().remove();
@ -3301,7 +3304,7 @@ instance.web.form.One2ManyListView = instance.web.ListView.extend({
.value();
},
do_add_record: function () {
if (this.options.editable) {
if (this.editable()) {
this._super.apply(this, arguments);
} else {
var self = this;
@ -4108,10 +4111,12 @@ instance.web.form.SelectCreatePopup = instance.web.form.AbstractFormPopup.extend
self.dataset, false,
_.extend({'deletable': false,
'selectable': !self.options.disable_multiple_selection,
'read_only': true,
'import_enabled': false,
'$buttons': self.$buttonpane,
}, self.options.list_view_options || {}));
self.view_list.on('edit:before', self, function (e) {
e.cancel = true;
});
self.view_list.popup = self;
self.view_list.appendTo($(".oe_popup_list", self.$element)).pipe(function() {
self.view_list.do_show();

View File

@ -21,9 +21,6 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
// whether the view rows can be reordered (via vertical drag & drop)
'reorderable': true,
'action_buttons': true,
// if true, the view can't be editable, ignoring the view's and the context's
// instructions
'read_only': false,
// if true, the 'Import', 'Export', etc... buttons will be shown
'import_enabled': true,
},

View File

@ -12,6 +12,8 @@ openerp.web.list_editable = function (instance) {
var self = this;
this._super.apply(this, arguments);
this._force_editability = null;
this._context_editable = false;
this.editor = this.make_editor();
// Stores records of {field, cell}, allows for re-rendering fields
// depending on cell state during and after resize events
@ -37,6 +39,11 @@ openerp.web.list_editable = function (instance) {
}
});
this.on('edit:before', this, function (event) {
if (!self.editable() || self.editor.is_editing()) {
event.cancel = true;
}
});
this.on('edit:after', this, function () {
self.$element.add(self.$buttons).addClass('oe_editing');
});
@ -62,26 +69,18 @@ openerp.web.list_editable = function (instance) {
do_edit: function (index, id, dataset) {
_.extend(this.dataset, dataset);
},
/**
* Sets editability status for the list, based on defaults, view
* architecture and the provided flag, if any.
*
* @param {Boolean} [force] forces the list to editability. Sets new row edition status to "bottom".
*/
set_editable: function (force) {
// TODO: fix handling of editability status to be simpler & clearer & more coherent
// If ``force``, set editability to bottom
// otherwise rely on view default
// view' @editable is handled separately as we have not yet
// fetched and processed the view at this point.
this.options.editable = (
! this.options.read_only && ((force && "bottom") || this.defaults.editable));
editable: function () {
if (this.fields_view.arch.attrs.editable || this._context_editable) {
return true;
}
return this.options.editable;
},
/**
* Replace do_search to handle editability process
*/
do_search: function(domain, context, group_by) {
this.set_editable(context['set_editable']);
this._context_editable = !!context.set_editable;
this._super.apply(this, arguments);
},
/**
@ -89,7 +88,7 @@ openerp.web.list_editable = function (instance) {
* as an editable row at the top or bottom of the list)
*/
do_add_record: function () {
if (this.options.editable) {
if (this.editable()) {
this.$element.find('table:first').show();
this.$element.find('.oe_view_nocontent').remove();
this.start_edition();
@ -103,9 +102,8 @@ openerp.web.list_editable = function (instance) {
this.editor.destroy();
}
// tree/@editable takes priority on everything else if present.
this.options.editable = ! this.options.read_only && (data.arch.attrs.editable || this.options.editable);
var result = this._super(data, grouped);
if (this.options.editable) {
if (this.editable()) {
// FIXME: any hook available to ensure this is only done once?
this.$buttons
.off('click', '.oe_list_save')
@ -210,6 +208,12 @@ openerp.web.list_editable = function (instance) {
self.resize_fields();
return record.attributes;
});
}).fail(function () {
// if the start_edition event is cancelled and it was a
// creation, remove the newly-created empty record
if (!record.get('id')) {
self.records.remove(record);
}
});
});
},
@ -379,7 +383,7 @@ openerp.web.list_editable = function (instance) {
return this.reload_record(record);
},
prepends_on_create: function () {
return this.options.editable === 'top';
return this.editable() === 'top';
},
setup_events: function () {
var self = this;
@ -701,7 +705,7 @@ openerp.web.list_editable = function (instance) {
instance.web.ListView.List.include(/** @lends instance.web.ListView.List# */{
row_clicked: function (event) {
if (!this.options.editable) {
if (!this.view.editable()) {
return this._super.apply(this, arguments);
}
var record_id = $(event.currentTarget).data('id');

View File

@ -87,34 +87,37 @@ List view edition is an extension to the base listview providing the
capability of inline record edition by delegating to an embedded form
view.
.. todo::
Editability status
++++++++++++++++++
cleanup options and settings for editability configuration. Right
now there are:
The editability status of a list view can be queried through the
:js:func:`~openerp.web.ListView.editable` method, will return a falsy
value if the listview is not currently editable.
``defaults.editable``
The editability status is based on three flags:
``null``, ``"top"`` or ``"bottom"``, generally broken and
useless
``tree/@editable``
``context.set_editable``
If present, can be either ``"top"`` or ``"bottom"``. Either will
make the list view editable, with new records being respectively
created at the top or at the bottom of the view.
forces ``options.editable`` to ``"bottom"``
``context.set_editable``
``view.arch.attrs.editable``
Boolean flag extracted from a search context (during the
:js:func:`~openerp.web.ListView.do_search`` handler), ``true``
will make the view editable (from the top), ``false`` or the
absence of the flag is a noop.
same as ``defaults.editable``, but applied separately (after
reloading the view), if absent delegates to
``options.editable`` which may have been set previously.
``defaults.editable``
``options.read_only``
Like ``tree/@editable``, one of absent (``null``)), ``"top"`` or
``"bottom"``, fallback for the list view if none of the previous
two flags are set.
force options.editable to false, or something?
.. note:: can probably be replaced by cancelling ``edit:before``
and :js:func:`~openerp.web.ListView.set_editable` which
ultimately behaves weird-as-fuck-ly.
These three flags can only *make* a listview editable, they can *not*
override a previously set flag. To do that, a listview user should
instead cancel :ref:`the edit:before event <listview-edit-before>`.
The editable list view module adds a number of methods to the list
view, on top of implementing the :js:class:`EditorDelegate` protocol:
@ -219,6 +222,14 @@ view provides a number of dedicated events to its lifecycle.
abort its current behavior as soon as possible, and rollback
any state modification.
Generally speaking, an event should only be cancelled (by
setting the ``cancel`` flag to ``true``), uncancelling an
event is undefined as event handlers are executed on a
first-come-first-serve basis and later handlers may
re-cancel an uncancelled event.
.. _listview-edit-before:
``edit:before`` *cancellable*
Invoked before the list view starts editing a record.