diff --git a/.bzrignore b/.bzrignore index 62f8a05c90f..f4d605ac633 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,23 +1,13 @@ -*.pyc -.*.swp -.bzrignore -openerp/addons/* -openerp/filestore* -.Python -include -lib -bin/activate -bin/activate_this.py -bin/easy_install -bin/easy_install-2.6 -bin/pip -bin/python -bin/python2.6 -*.pyc -*.pyo +.* +*.egg-info +*.orig build/ -bin/yolk -bin/pil*.py -.project -.pydevproject -.settings +RE:^bin/ +RE:^dist/ +RE:^include/ + +RE:^share/ +RE:^man/ +RE:^lib/ + +RE:^doc/_build/ diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index 72c87727481..162087fc81e 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -314,6 +314,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search } }, on_loaded: function(data) { + var self = this; this.fields_view = data.fields_view; if (data.fields_view.type !== 'search' || data.fields_view.arch.tag !== 'search') { @@ -322,12 +323,16 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search data.fields_view.type, data.fields_view.arch.tag)); } - var self = this, - lines = this.make_widgets( + this.make_widgets( data.fields_view['arch'].children, data.fields_view.fields); - return this.ready.resolve().promise(); + // load defaults + return $.when.apply(null, _(this.inputs).invoke('facet_for_defaults', this.defaults)) + .then(function () { + self.vs.searchQuery.reset(_(arguments).compact()); + self.ready.resolve(); + }); // for extended search view var ext = new openerp.web.search.ExtendedSearch(this, this.model); @@ -730,10 +735,6 @@ openerp.web.search.Widget = openerp.web.OldWidget.extend( /** @lends openerp.web destroy: function () { delete this.view; this._super(); - }, - render: function (defaults) { - // FIXME - return this._super(_.extend(this, {defaults: defaults})); } }); openerp.web.search.add_expand_listener = function($root) { @@ -781,11 +782,29 @@ openerp.web.search.Input = openerp.web.search.Widget.extend( /** @lends openerp. * label, value prefixed with an object with keys type=section and label * * @param {String} value value to complete - * @returns {jQuery.Deferred} + * @returns {jQuery.Deferred} */ complete: function (value) { return $.when(null) }, + /** + * Returns a VS.model.SearchFacet instance for the provided defaults if + * they apply to this widget, or null if they don't. + * + * This default implementation will try calling + * :js:func:`openerp.web.search.Input#facet_for` if the widget's name + * matches the input key + * + * @param {Object} defaults + * @returns {jQuery.Deferred} + */ + facet_for_defaults: function (defaults) { + if (!this.attrs || + !(this.attrs.name in defaults && defaults[this.attrs.name])) { + return $.when(null); + } + return this.facet_for(defaults[this.attrs.name]); + }, get_context: function () { throw new Error( "get_context not implemented for widget " + this.attrs.type); @@ -879,26 +898,18 @@ openerp.web.search.Filter = openerp.web.search.Input.extend(/** @lends openerp.w self.view.do_toggle_filter(self); }); }, - /** - * Returns whether the filter is currently enabled (in use) or not. - * - * @returns a boolean - */ - is_enabled:function () { - return this.$element.hasClass('enabled'); - }, /** * If the filter is present in the defaults (and has a truthy value), * enable the filter. * * @param {Object} defaults the search view's default values */ - render: function (defaults) { - if (this.attrs.name && defaults[this.attrs.name]) { - this.classes.push('enabled'); - this.view.do_toggle_filter(this, true); - } - return this._super(defaults); + facet_for: function (value) { + return $.when(new VS.model.SearchFacet({ + category: this.attrs.string || this.attrs.name, + value: 'true', + app: this.view.vs + })); }, get_context: function () { if (!this.is_enabled()) { @@ -939,6 +950,13 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w })), view); this.make_id('input', field.type, this.attrs.name); }, + facet_for: function (value) { + return $.when(new VS.model.SearchFacet({ + category: this.attrs.name, + value: String(value), + app: this.view.vs + })); + }, start: function () { this._super(); this.filters.start(); @@ -1096,6 +1114,17 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o return $.when.apply(null, [{type: 'section', label: this.attrs.string}].concat(results)); }, + facet_for: function (value) { + var match = _(this.attrs.selection).detect(function (sel) { + return sel[0] === value; + }); + if (!match) { return $.when(null); } + return $.when(new VS.model.SearchFacet({ + category: this.attrs.name, + value: match[1], + app: this.view.vs + })); + }, get_value: function () { var index = parseInt(this.$element.val(), 10); if (isNaN(index)) { return null; } @@ -1103,20 +1132,6 @@ openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends o if (value === false) { return null; } return value; }, - /** - * The selection field needs a default ``false`` value in case none is - * provided, so that selector options with a ``false`` value (convention - * for explicitly empty options) get selected by default rather than the - * first (value-holding) option in the selection. - * - * @param {Object} defaults search default values - */ - render: function (defaults) { - if (!defaults[this.attrs.name]) { - defaults[this.attrs.name] = false; - } - return this._super(defaults); - }, clear: function () { var self = this, d = $.Deferred(), selection = this.attrs.selection; for(var index=0; index``. + +There is no built-in (default) implementation of +:js:func:`openerp.web.search.Input.facet_for`. + +Providing auto-completion +------------------------- + +An important component of the unified search view is the faceted autocompletion +pane. In order to provide good user and developer experiences, this pane is +pluggable (value-wise): each and every control of the search view can check for +(and provide) categorized auto-completions for a given value being typed by +the user. + +This is done by implementing :js:func:`openerp.web.search.Input.complete`: the +method is provided with a value to complete, and the input must either return +a ``jQuery.Deferred`` or fetch (by returning a ``jQuery.Deferred``) an +array of completion values. + +.. todo:: describe the shape of "completion values"? + +Converting to and from facet objects +------------------------------------ + +Changes +------- + +.. todo:: merge in changelog instead + +The displaying of the search view was significantly altered from OpenERP Web +6.1 to OpenERP Web 6.2: it went form a form-like appearance (inherited from +previous web client versions and ultimately from the GTK client) to a +"universal" search input with facets. + +As a result, while the external API used to interact with the search view does +not change the internal details — including the interaction between the search +view and its widgets — is significantly altered: + +Widgets API ++++++++++++ + +* :js:func:`openerp.web.search.Widget.render` has been removed +* Search field objects are not openerp widgets anymore, their ``start`` is + not generally called + +Filters ++++++++ + +* :js:func:`openerp.web.search.Filter.is_enabled` has been removed + +Many To One ++++++++++++ + +* Because the autocompletion service is now provided by the search view + itself, :js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has + been removed.