diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index dbce531edce..30dc3718fa9 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -613,6 +613,12 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%, .openerp .oe-listview .oe-field-cell button:active { opacity: 0.5; } +.openerp .oe-listview .oe-field-cell button img { + cursor: pointer; +} +.openerp .oe-listview .oe-field-cell button img:hover { + opacity: 0.75; +} .openerp .oe-listview th.oe-actions { text-align: left; diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js index 42a314f4316..84aa4acc325 100644 --- a/addons/base/static/src/js/chrome.js +++ b/addons/base/static/src/js/chrome.js @@ -334,9 +334,6 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b // Construct a JSON-RPC2 request, method is currently unused params.session_id = this.session_id; params.context = typeof(params.context) != "undefined" ? params.context : this.context; - if (!params.context.bin_size) { - params.context.bin_size = true; - } // Use a default error handler unless defined error_callback = typeof(error_callback) != "undefined" ? error_callback : this.on_rpc_error; diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 42041f1b024..90357325928 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -33,6 +33,8 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV 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; this.has_been_loaded = $.Deferred(); }, @@ -70,8 +72,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV do_show: function () { var self = this; self.$element.show(); - if (this.dataset.index === null) { + if (this.dataset.index === null || (this.dataset.index === 0 && this.dataset.ids.length == 0)) { // null index means we should start a new record + // 0 index with empty ids means we called the form with empty dataset (wizards, switched to form from empty list, ...) this.on_button_new(); } else { this.dataset.read_index(_.keys(this.fields_view.fields), this.on_record_loaded); @@ -89,9 +92,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV var field = this.fields[f]; field.touched = false; field.set_value(this.datarecord[f] || false); - // TODO: here we should be able to alter the 'touched' state when setting value - // the following line will be removed by fme as soon as refactoring has been done - field.touched = false; field.validate(); } if (!record.id) { @@ -109,6 +109,9 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV } this.do_update_pager(record.id == null); this.do_update_sidebar(); + if (this.default_focus_field) { + this.default_focus_field.focus(); + } }, on_form_changed: function(widget) { if (widget && widget.node.attrs.on_change) { @@ -163,7 +166,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV if (field in argument_replacement) { args.push(argument_replacement[field]); } else if (self.fields[field]) { - var value = self.fields[field].value; + var value = self.fields[field].get_value(); args.push(value == null ? false : value); } else { args.push(false); @@ -194,7 +197,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV if (field) { var value = result.value[f]; processed.push(field.name); - if (field.value != value) { + if (field.get_value() != value) { field.set_value(value); if (_.indexOf(processed, field.name) < 0) { this.do_onchange(field, processed); @@ -540,10 +543,15 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ var type = this.view.fields_view.fields[node.attrs.name] || {}; var widget_type = node.attrs.widget || type.type || node.tag; var widget = new (this.view.registry.get_object(widget_type)) (this.view, node); - if (node.tag == 'field' && node.attrs.nolabel != '1') { - var label = new (this.view.registry.get_object('label')) (this.view, node); - label["for"] = widget; - this.add_widget(label); + if (node.tag == 'field') { + if (node.attrs.default_focus == '1') { + this.view.default_focus_field = widget; + } + if (node.attrs.nolabel != '1') { + var label = new (this.view.registry.get_object('label')) (this.view, node); + label["for"] = widget; + this.add_widget(label); + } } this.add_widget(widget); }, @@ -588,6 +596,10 @@ openerp.base.form.WidgetButton = openerp.base.form.Widget.extend({ init: function(view, node) { this._super(view, node); this.template = "WidgetButton"; + if (node.attrs.default_focus == '1') { + // TODO fme: provide enter key binding to widgets + this.view.default_focus_button = this; + } }, start: function() { this._super.apply(this, arguments); @@ -694,11 +706,18 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ }, on_ui_change: function() { this.touched = this.view.touched = true; - this.set_value_from_ui(); this.validate(); - this.view.on_form_changed(this); + if (!this.invalid) { + this.set_value_from_ui(); + this.view.on_form_changed(this); + } else { + this.update_dom(); + } }, validate: function() { + this.invalid = false; + }, + focus: function() { } }); @@ -725,11 +744,15 @@ openerp.base.form.FieldChar = openerp.base.form.Field.extend({ }, validate: function() { this.invalid = false; - if (this.value === false || this.value === "") { + var value = this.$element.find('input').val(); + if (value === "") { this.invalid = this.required; } else if (this.validation_regex) { - this.invalid = !this.validation_regex.test(this.value); + this.invalid = !this.validation_regex.test(value); } + }, + focus: function() { + this.$element.find('input').focus(); } }); @@ -781,23 +804,16 @@ openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({ this.validation_regex = /^-?\d+(\.\d+)?$/; }, set_value: function(value) { - if (!value) { + this._super.apply(this, [value]); + if (value === false || value === undefined) { // As in GTK client, floats default to 0 - this.touched = this.view.touched = true; value = 0; } - this._super.apply(this, [value]); var show_value = value.toFixed(2); this.$element.find('input').val(show_value); }, set_value_from_ui: function() { - this.value = this.$element.find('input').val().replace(/,/g, '.'); - }, - validate: function() { - this._super.apply(this, arguments); - if (!this.invalid) { - this.value = Number(this.value); - } + this.value = Number(this.$element.find('input').val().replace(/,/g, '.')); } }); @@ -819,8 +835,10 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ if (value == null || value == false) { this.$element.find('input').val(''); } else { - this.value = this.parse(value); - this.$element.find('input')[this.jqueryui_object]('setDate', this.value); + this.$element.find('input').unbind('change'); + // jQuery UI date picker wrongly call on_change event herebelow + this.$element.find('input')[this.jqueryui_object]('setDate', this.parse(value)); + this.$element.find('input').change(this.on_ui_change); } }, set_value_from_ui: function() { @@ -830,7 +848,10 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ } }, validate: function() { - this.invalid = this.required && this.value === false; + this.invalid = this.required && this.$element.find('input')[this.jqueryui_object]('getDate') === ''; + }, + focus: function() { + this.$element.find('input').focus(); }, parse: openerp.base.parse_datetime, format: openerp.base.format_datetime @@ -851,19 +872,17 @@ openerp.base.form.FieldFloatTime = openerp.base.form.FieldChar.extend({ this.validation_regex = /^\d+:\d+$/; }, set_value: function(value) { - value = value || 0; this._super.apply(this, [value]); + if (value === false || value === undefined) { + // As in GTK client, floats default to 0 + value = 0; + } var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); this.$element.find('input').val(show_value); }, - validate: function() { - if (typeof(this.value) == "string") { - this._super.apply(this, arguments); - if (!this.invalid) { - var time = this.value.split(':'); - this.set_value(parseInt(time[0], 10) + parseInt(time[1], 10) / 60); - } - } + set_value_from_ui: function() { + var time = this.$element.find('input').val().split(':'); + this.set_value(parseInt(time[0], 10) + parseInt(time[1], 10) / 60); } }); @@ -891,11 +910,15 @@ openerp.base.form.FieldText = openerp.base.form.Field.extend({ }, validate: function() { this.invalid = false; - if (this.value === false || this.value === "") { + var value = this.$element.find('textarea').val(); + if (value === "") { this.invalid = this.required; } else if (this.validation_regex) { - this.invalid = !this.validation_regex.test(this.value); + this.invalid = !this.validation_regex.test(value); } + }, + focus: function() { + this.$element.find('textarea').focus(); } }); @@ -925,7 +948,10 @@ openerp.base.form.FieldBoolean = openerp.base.form.Field.extend({ this.$element.find('input').attr('disabled', this.readonly); }, validate: function() { - this.invalid = this.required && !this.value; + this.invalid = this.required && !this.$element.find('input').is(':checked'); + }, + focus: function() { + this.$element.find('input').focus(); } }); @@ -980,22 +1006,25 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({ this.$element.find('select').attr('disabled', this.readonly); }, validate: function() { - this.invalid = this.required && this.value === ""; + this.invalid = this.required && this.$element.find('select').val() === ""; + }, + focus: function() { + this.$element.find('select').focus(); } }); // jquery autocomplete tweak to allow html -(function(x) { +(function() { var proto = $.ui.autocomplete.prototype, initSource = proto._initSource; - + function filter( array, term ) { var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); return $.grep( array, function(value) { return matcher.test( $( "
" ).html( value.label || value.value || value ).text() ); }); } - + $.extend( proto, { _initSource: function() { if ( this.options.html && $.isArray(this.options.source) ) { @@ -1006,7 +1035,7 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({ initSource.call( this ); } }, - + _renderItem: function( ul, item) { return $( "
  • " ) .data( "item.autocomplete", item ) @@ -1014,7 +1043,7 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({ .appendTo( ul ); } }); -})(null); +})(); /** * Builds a new context usable for operations related to fields by merging @@ -1043,7 +1072,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ this.$input = this.$element.find("input"); this.$drop_down = this.$element.find(".oe-m2o-drop-down-button"); this.$menu_btn = this.$element.find(".oe-m2o-cm-button"); - + // context menu var bindings = {}; bindings[this.cm_id + "_search"] = function() { @@ -1078,7 +1107,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ return true; } }); - + // some behavior for input this.$input.keyup(function() { if (self.$input.val() === "") { @@ -1111,7 +1140,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ } } this.$input.focusout(anyoneLoosesFocus); - + // autocomplete this.$input.autocomplete({ source: function(req, resp) { self.get_search_result(req, resp); }, @@ -1138,9 +1167,9 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ get_search_result: function(request, response) { var search_val = request.term; var self = this; - + var dataset = new openerp.base.DataSetStatic(this.session, this.field.relation, []); - + dataset.name_search([search_val, self.field.domain || [], 'ilike', build_relation_context(self), this.limit + 1], function(data) { self.last_search = data.result; @@ -1148,7 +1177,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ var values = _.map(data.result, function(x) { return {label: $('').text(x[1]).html(), name:x[1], id:x[0]}; }); - + // search more... if more results that max if (values.length > self.limit) { values = values.slice(0, self.limit); @@ -1175,7 +1204,7 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ self._change_int_value(null); self._search_create_popup("form"); }}); - + response(values); }); }, @@ -1247,16 +1276,16 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ }, start: function() { this._super.apply(this, arguments); - + var self = this; - + this.dataset = new openerp.base.DataSetStatic(this.session, this.field.relation); this.dataset.on_unlink.add_last(function(ids) { self.dataset.set_ids(_.without.apply(_, [self.dataset.ids].concat(ids))); self.on_ui_change(); self.reload_current_view(); }); - + var modes = this.node.attrs.mode; modes = !!modes ? modes.split(",") : ["tree", "form"]; var views = []; @@ -1272,7 +1301,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ views.push(view); }); this.views = views; - + this.viewmanager = new openerp.base.ViewManager(this.view.session, this.element_id, this.dataset, views); var reg = new openerp.base.Registry(); @@ -1280,7 +1309,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ reg.add("graph", openerp.base.views.map["graph"]); reg.add("list", "openerp.base.form.One2ManyListView"); this.viewmanager.registry = reg; - + this.viewmanager.on_controller_inited.add_last(function(view_type, controller) { if (view_type == "list") { controller.o2m = self; @@ -1290,7 +1319,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ self.is_started.resolve(); }); this.viewmanager.start(); - + $.when(this.is_started, this.is_setted).then(function() { if (modes[0] == "tree") { var view = self.viewmanager.views[self.viewmanager.active_view].controller; @@ -1348,14 +1377,14 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({ }, start: function() { this._super.apply(this, arguments); - + var self = this; - + this.dataset = new openerp.base.DataSetStatic( this.session, this.field.relation); this.dataset.on_unlink.add_last(function(ids) { self.list_view.reload_content(); - + self.on_ui_change(); }); diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index 8fba7eb6c4c..4217031a7e3 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -362,6 +362,25 @@ openerp.base.Sidebar = openerp.base.BaseWidget.extend({ openerp.base.NullSidebar = openerp.base.generate_null_object_class(openerp.base.Sidebar); +openerp.base.Export = openerp.base.Dialog.extend({ + dialog_title: "Export", + template: 'ExportDialog', + identifier_prefix: 'export_dialog', + init: function (session, model, domain) { + this._super(); + }, + start: function () { + this._super(); + this.$element.html(this.render()); + }, + on_button_Export: function() { + console.log("Export") + }, + on_button_Cancel: function() { + this.$element.dialog("close"); + } +}); + openerp.base.View = openerp.base.Controller.extend({ /** * 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 738d1823ae3..949b38e0115 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -341,7 +341,7 @@ -