From 8184aa0154a451d096f37f81ec0db014f8c3479a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Tue, 26 Jul 2011 17:37:47 +0200 Subject: [imp] improved o2m, added auto-save bzr revid: nicolas.vanhoren@openerp.com-20110726153747-2zj63korpu6xct6e --- addons/base/static/src/js/form.js | 46 ++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) (limited to 'addons/base/static/src/js/form.js') diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 25dcca611bd..598cdd12c20 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -301,6 +301,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV if (!this.ready) { return false; } + var dirty = false; var invalid = false, values = {}, first_invalid_field = null; @@ -313,6 +314,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV first_invalid_field = f; } } else if (f.touched) { + dirty = true; values[f.name] = f.get_value(); } } @@ -320,18 +322,19 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV first_invalid_field.focus(); this.on_invalid(); return false; - } else { + } else if (dirty) { this.log("About to save", values); if (!this.datarecord.id) { - this.dataset.create(values, function(r) { + return this.dataset.create(values, function(r) { self.on_created(r, success, prepend_on_create); }); } else { - this.dataset.write(this.datarecord.id, values, function(r) { + return this.dataset.write(this.datarecord.id, values, function(r) { self.on_saved(r, success); }); } - return true; + } else { + return false; } }, do_save_edit: function() { @@ -1612,6 +1615,9 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ controller.on_record_loaded.add_last(function() { once.resolve(); }); + controller.on_form_changed.add_last(function() { + self.save_form_view(); + }); } self.is_started.resolve(); }); @@ -1692,6 +1698,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ var self = this; if (!this.dataset) return []; + this.save_form_view(); var val = this.dataset.delete_all ? [commands.delete_all()] : []; val = val.concat(_.map(this.dataset.ids, function(id) { var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;}); @@ -1708,9 +1715,38 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ this.dataset.to_delete, function(x) { return commands['delete'](x.id);})); }, + save_form_view: function() { + if (this.viewmanager && this.viewmanager.views && this.viewmanager.active_view && + this.viewmanager.views[this.viewmanager.active_view] && + this.viewmanager.views[this.viewmanager.active_view].controller) { + var view = this.viewmanager.views[this.viewmanager.active_view].controller; + if (this.viewmanager.active_view === "form") { + var res = view.do_save(); + if (res === false) { + // ignore + } else if (res.isRejected()) { + throw "Save or create on one2many dataset is not supposed to fail."; + } else if (!res.isResolved()) { + throw "Asynchronous get_value() is not supported in form view."; + } + } + } + }, validate: function() { this.invalid = false; - // TODO niv + var self = this; + var view = self.viewmanager.views[self.viewmanager.active_view].controller; + if(self.viewmanager.active_view === "list") { + return; + } else if (self.viewmanager.active_view === "form") { + for (var f in view.fields) { + f = view.fields[f]; + if (f.invalid) { + this.invalid = true; + return; + } + } + } } }); -- cgit v1.2.3 From d0234fa5dd424e7722443fda7e41f955d857027a Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 26 Jul 2011 23:00:05 +0200 Subject: [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 --- addons/base/static/src/js/form.js | 102 +++++++++++++++++++++++--------------- 1 file changed, 61 insertions(+), 41 deletions(-) (limited to 'addons/base/static/src/js/form.js') 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 $('' + openerp.base.json_node_to_xml(self.fields_view.arch, true) + '').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--) { -- cgit v1.2.3 From 30bca6090729aec58e7076443cc751e09678d860 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 27 Jul 2011 10:03:19 +0200 Subject: [REM] Removed reference to view_manager.flags from views. The action flags are merged in View's options constructor argument so we shall not fetch them from view_manager anymore. bzr revid: fme@openerp.com-20110727080319-nztgq4txu2tt6odq --- addons/base/static/src/js/form.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/base/static/src/js/form.js') diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index e66a073643c..6cc208facda 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -32,7 +32,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi this.ready = false; this.show_invalid = true; this.touched = false; - this.flags = this.view_manager.flags || {}; this.default_focus_field = null; this.default_focus_button = null; this.registry = openerp.base.form.widgets; -- cgit v1.2.3 From 9d6085e99e6436a9b5b9edc96050eba46d896436 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 27 Jul 2011 11:28:01 +0200 Subject: [REM] Removed debug logging in dialog function bzr revid: fme@openerp.com-20110727092801-fg93veg1rcox72z7 --- addons/base/static/src/js/form.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/base/static/src/js/form.js') diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 5c14b953b70..c8d205b9492 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -1289,7 +1289,6 @@ openerp.base.form.dialog = function(content, options) { options.autoOpen = true; var dialog = new openerp.base.Dialog(null, options); dialog.$dialog = $(content).dialog(dialog.options); - console.log(dialog.options) return dialog.$dialog; } -- cgit v1.2.3 From 216ab84e5f27927ff1bf664ac8bdf38bbed57897 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 27 Jul 2011 12:25:19 +0200 Subject: [FIX] Fixed niv's mood bzr revid: fme@openerp.com-20110727102519-at3qxx4sxc3fqp44 --- addons/base/static/src/js/form.js | 56 ++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'addons/base/static/src/js/form.js') diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index c8d205b9492..d5a87a78309 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -31,7 +31,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi this.datarecord = {}; this.ready = false; this.show_invalid = true; - this.touched = false; + this.dirty = false; this.default_focus_field = null; this.default_focus_button = null; this.registry = openerp.base.form.widgets; @@ -133,22 +133,22 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi this.$form_header.find('.oe_form_on_update').show(); this.$form_header.find('button.oe_form_button_new').show(); } - this.touched = false; + this.dirty = false; this.datarecord = record; for (var f in this.fields) { var field = this.fields[f]; - field.touched = false; + field.dirty = false; field.set_value(this.datarecord[f] || false); field.validate(); } if (!record.id) { // New record: Second pass in order to trigger the onchanges - this.touched = true; + this.dirty = true; this.show_invalid = false; for (var f in record) { var field = this.fields[f]; if (field) { - field.touched = true; + field.dirty = true; this.do_onchange(field); } } @@ -267,7 +267,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi processed.push(field.name); if (field.get_value() != value) { field.set_value(value); - field.touched = true; + field.dirty = true; if (_.indexOf(processed, field.name) < 0) { this.do_onchange(field, processed); } @@ -315,28 +315,28 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi if (!this.ready) { return false; } - var dirty = false; - var invalid = false, + var form_dirty = false, + form_invalid = false, values = {}, first_invalid_field = null; for (var f in this.fields) { f = this.fields[f]; - if (f.invalid) { - invalid = true; + if (!f.is_valid()) { + form_invalid = true; f.update_dom(); if (!first_invalid_field) { first_invalid_field = f; } - } else if (f.touched) { - dirty = true; + } else if (f.is_dirty()) { + form_dirty = true; values[f.name] = f.get_value(); } } - if (invalid) { + if (form_invalid) { first_invalid_field.focus(); this.on_invalid(); return false; - } else if (dirty) { + } else if (form_dirty) { this.log("About to save", values); if (!this.datarecord.id) { return this.dataset.create(values, function(r) { @@ -362,7 +362,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormVi on_invalid: function() { var msg = "
    "; _.each(this.fields, function(f) { - if (f.invalid) { + if (!f.is_valid()) { msg += "
  • " + f.string + "
  • "; } }); @@ -729,7 +729,7 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({ }, on_click: function(saved) { var self = this; - if (!this.node.attrs.special && this.view.touched && saved !== true) { + if (!this.node.attrs.special && this.view.dirty && saved !== true) { this.view.do_save(function() { self.on_click(true); }); @@ -809,7 +809,7 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ this.readonly = this.modifiers['readonly'] === true; this.required = this.modifiers['required'] === true; this.invalid = false; - this.touched = false; + this.dirty = false; }, set_value: function(value) { this.value = value; @@ -822,6 +822,12 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ get_value: function() { return this.value; }, + is_valid: function() { + return !this.invalid; + }, + is_dirty: function() { + return this.dirty; + }, get_on_change_value: function() { return this.get_value(); }, @@ -830,13 +836,13 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ this.$element.toggleClass('disabled', this.readonly); this.$element.toggleClass('required', this.required); if (this.view.show_invalid) { - this.$element.toggleClass('invalid', this.invalid); + this.$element.toggleClass('invalid', !this.is_valid()); } }, on_ui_change: function() { - this.touched = this.view.touched = true; + this.dirty = this.view.dirty = true; this.validate(); - if (!this.invalid) { + if (this.is_valid()) { this.set_value_from_ui(); this.view.do_onchange(this); this.view.on_form_changed(); @@ -934,7 +940,7 @@ openerp.base.form.FieldEmail = openerp.base.form.FieldChar.extend({ this.$element.find('button').click(this.on_button_clicked); }, on_button_clicked: function() { - if (!this.value || this.invalid) { + if (!this.value || !this.is_valid()) { this.notification.warn("E-mail error", "Can't send email to invalid e-mail address"); } else { location.href = 'mailto:' + this.value; @@ -975,7 +981,7 @@ openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({ if (value === false || value === undefined) { // As in GTK client, floats default to 0 value = 0; - this.touched = true; + this.dirty = true; } var show_value = value.toFixed(2); this.$element.find('input').val(show_value); @@ -995,7 +1001,7 @@ openerp.base.form.FieldInteger = openerp.base.form.FieldFloat.extend({ if (value === false || value === undefined) { // TODO fme: check if GTK client default integers to 0 (like it does with floats) value = 0; - this.touched = true; + this.dirty = true; } var show_value = parseInt(value, 10); this.$element.find('input').val(show_value); @@ -1082,7 +1088,7 @@ openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({ if (value === false || value === undefined) { // As in GTK client, floats default to 0 value = 0; - this.touched = true; + this.dirty = true; } var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); this.$element.find('input').val(show_value); @@ -1759,7 +1765,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ } else if (self.viewmanager.active_view === "form") { for (var f in view.fields) { f = view.fields[f]; - if (f.invalid) { + if (!f.is_valid()) { this.invalid = true; return; } -- cgit v1.2.3