diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 850069bb141..1179eb37d42 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import base64 import glob, os -import pprint from xml.etree import ElementTree from cStringIO import StringIO @@ -125,14 +124,14 @@ class Session(openerpweb.Controller): def jslist(self, req, mods='base'): return {'files': self.manifest_glob(mods.split(','), 'js')} - def css(self, req, mods='base,base_hello'): + def css(self, req, mods='base'): files = self.manifest_glob(mods.split(','), 'css') concat = self.concat_files(files)[0] # TODO request set the Date of last modif and Etag return concat css.exposed = True - def js(self, req, mods='base,base_hello'): + def js(self, req, mods='base'): files = self.manifest_glob(mods.split(','), 'js') concat = self.concat_files(files)[0] # TODO request set the Date of last modif and Etag @@ -392,9 +391,10 @@ class DataSet(openerpweb.Controller): req.session.eval_context(req.context))} @openerpweb.jsonrequest - def search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, context=None, sort=None): - return self.do_search_read(request, model, fields, offset, limit, domain, context, sort) - def do_search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, context=None, sort=None): + def search_read(self, request, model, fields=False, offset=0, limit=False, domain=None, sort=None): + return self.do_search_read(request, model, fields, offset, limit, domain, sort) + def do_search_read(self, request, model, fields=False, offset=0, limit=False, domain=None + , sort=None): """ Performs a search() followed by a read() (if needed) using the provided search criteria @@ -407,22 +407,33 @@ class DataSet(openerpweb.Controller): :param int limit: the maximum number of records to return :param list domain: the search domain for the query :param list sort: sorting directives - :returns: a list of result records + :returns: A structure (dict) with two keys: ids (all the ids matching + the (domain, context) pair) and records (paginated records + matching fields selection set) :rtype: list """ Model = request.session.model(model) - context, domain = eval_context_and_domain(request.session, request.context, domain) - - ids = Model.search(domain, offset or 0, limit or False, - sort or False, context) + context, domain = eval_context_and_domain( + request.session, request.context, domain) + ids = Model.search(domain, 0, False, sort or False, context) + # need to fill the dataset with all ids for the (domain, context) pair, + # so search un-paginated and paginate manually before reading + paginated_ids = ids[offset:(offset + limit if limit else None)] if fields and fields == ['id']: # shortcut read if we only want the ids - return map(lambda id: {'id': id}, ids) + return { + 'ids': ids, + 'records': map(lambda id: {'id': id}, paginated_ids) + } + + records = Model.read(paginated_ids, fields or False, context) + records.sort(key=lambda obj: ids.index(obj['id'])) + return { + 'ids': ids, + 'records': records + } - reads = Model.read(ids, fields or False, context) - reads.sort(key=lambda obj: ids.index(obj['id'])) - return reads @openerpweb.jsonrequest def get(self, request, model, ids, fields=False): @@ -583,36 +594,6 @@ class View(openerpweb.Controller): return {'result': True} return {'result': False} - def normalize_attrs(self, elem, context): - """ Normalize @attrs, @invisible, @required, @readonly and @states, so - the client only has to deal with @attrs. - - See `the discoveries pad `_ for - the rationale. - - :param elem: the current view node (Python object) - :type elem: xml.etree.ElementTree.Element - :param dict context: evaluation context - """ - # If @attrs is normalized in json by server, the eval should be replaced by simplejson.loads - attrs = openerpweb.ast.literal_eval(elem.get('attrs', '{}')) - if 'states' in elem.attrib: - attrs.setdefault('invisible', [])\ - .append(('state', 'not in', elem.attrib.pop('states').split(','))) - if attrs: - elem.set('attrs', simplejson.dumps(attrs)) - for a in ['invisible', 'readonly', 'required']: - if a in elem.attrib: - # In the XML we trust - avalue = bool(eval(elem.get(a, 'False'), - {'context': context or {}})) - if not avalue: - del elem.attrib[a] - else: - elem.attrib[a] = '1' - if a == 'invisible' and 'attrs' in elem.attrib: - del elem.attrib['attrs'] - def transform_view(self, view_string, session, context=None): # transform nodes on the fly via iterparse, instead of # doing it statically on the parsing result @@ -622,7 +603,6 @@ class View(openerpweb.Controller): if event == "start": if root is None: root = elem - self.normalize_attrs(elem, context) self.parse_domains_and_contexts(elem, session) return root diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index 32a335d7eb8..e91bbd922ec 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -606,6 +606,9 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%, vertical-align: middle; text-align: left; } +.openerp .oe-listview td.oe-record-delete { + text-align: right; +} .openerp .oe-listview th.oe-sortable, .openerp .oe-listview th.oe-sortable .ui-icon { cursor: pointer; @@ -636,6 +639,17 @@ background: linear-gradient(top, #ffffff 0%,#d8d8d8 11%,#afafaf 86%,#333333 91%, .openerp .oe-listview th.oe-list-pager { text-align: right; } +.openerp .oe-list-pager .oe-pager-state { + cursor: pointer; +} + +.openerp .oe-listview .oe-group-name { + padding-right: 1em; +} +.openerp .oe-listview .oe-group-name, +.openerp .oe-listview .oe-group-pagination { + white-space: nowrap; +} .openerp .oe-listview tfoot td { padding: 3px 3px 0; diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js index 5d0dc0946c1..a4c1b22cf4f 100644 --- a/addons/base/static/src/js/chrome.js +++ b/addons/base/static/src/js/chrome.js @@ -350,7 +350,6 @@ openerp.base.Session = openerp.base.BasicController.extend( /** @lends openerp.b * @param {Object} params call parameters * @param {Function} success_callback function to execute on RPC call success * @param {Function} error_callback function to execute on RPC call failure - * one * @returns {jQuery.Deferred} jquery-provided ajax deferred */ rpc: function(url, params, success_callback, error_callback) { diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index ff74fa1639f..1eb9c0f0a0d 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -135,7 +135,7 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend( domain: this.domain, group_by_fields: this.group_by }, function () { }).then(function (response) { - var data_groups = _(response.result).map( + var data_groups = _(response).map( _.bind(self.transform_group, self)); self.groups = data_groups; d.resolveWith(self, [data_groups]); @@ -196,7 +196,9 @@ openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend( this._super(session, model, domain, context, null, level); }, list: function (ifGroups, ifRecords) { - ifRecords(new openerp.base.DataSetSearch(this.session, this.model, this.context, this.domain)); + ifRecords(_.extend( + new openerp.base.DataSetSearch(this.session, this.model), + {domain: this.domain, context: this.context})); } }); @@ -421,13 +423,10 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ sort: this.sort(), offset: offset, limit: limit - }, function (records) { - self.ids.splice(0, self.ids.length); + }, function (result) { + self.ids = result.ids; self.offset = offset; - for (var i=0; i < records.length; i++ ) { - self.ids.push(records[i].id); - } - callback(records); + callback(result.records); }); }, /** diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 98248ae37b9..7517ec23e01 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -132,7 +132,7 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV on_form_changed: function() { for (var w in this.widgets) { w = this.widgets[w]; - w.process_attrs(); + w.process_modifiers(); w.update_dom(); } }, @@ -166,7 +166,6 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.ready = false; var onchange = _.trim(widget.node.attrs.on_change); var call = onchange.match(/^\s?(.*?)\((.*?)\)\s?$/); - console.log("Onchange triggered for field '%s' -> %s", widget.name, onchange); if (call) { var method = call[1], args = []; var context_index = null; @@ -226,14 +225,12 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV on_processed_onchange: function(response, processed) { var result = response.result; if (result.value) { - console.log(" |-> Onchange Response :", result.value); for (var f in result.value) { var field = this.fields[f]; if (field) { var value = result.value[f]; processed.push(field.name); if (field.get_value() != value) { - console.log(" |-> Onchange Action : change '%s' value from '%s' to '%s'", field.name, field.get_value(), value); field.set_value(value); field.touched = true; if (_.indexOf(processed, field.name) < 0) { @@ -242,12 +239,11 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV } } else { // this is a common case, the normal behavior should be to ignore it - console.debug("on_processed_onchange can't find field " + f, result); } } this.on_form_changed(); } - if (result.warning && !_.isEmpty(result.warning)) { + if (!_.isEmpty(result.warning)) { $(QWeb.render("DialogWarning", result.warning)).dialog({ modal: true, buttons: { @@ -396,12 +392,13 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV this.on_attachments_loaded([]); } else { // TODO fme: modify this so it doesn't try to load attachments when there is not sidebar - /*this.rpc('/base/dataset/search_read', { - model: 'ir.attachment', - fields: ['name', 'url', 'type'], - domain: [['res_model', '=', this.dataset.model], ['res_id', '=', this.datarecord.id], ['type', 'in', ['binary', 'url']]], - context: this.dataset.get_context() - }, this.on_attachments_loaded);*/ + /*(new openerp.base.DataSetSearch( + this.session, '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) { @@ -506,7 +503,7 @@ openerp.base.form.compute_domain = function(expr, fields) { stack.push(!_(val).contains(field)); break; default: - this.log("Unsupported operator in attrs :", op); + this.log("Unsupported operator in modifiers :", op); } } return _.all(stack); @@ -517,7 +514,7 @@ openerp.base.form.Widget = openerp.base.Controller.extend({ init: function(view, node) { this.view = view; this.node = node; - this.attrs = JSON.parse(this.node.attrs.attrs || '{}'); + this.modifiers = JSON.parse(this.node.attrs.modifiers || '{}'); this.type = this.type || node.tag; this.element_name = this.element_name || this.type; this.element_id = [this.view.element_id, this.element_name, this.view.widgets_counter++].join("_"); @@ -530,15 +527,15 @@ openerp.base.form.Widget = openerp.base.Controller.extend({ this.string = this.string || node.attrs.string; this.help = this.help || node.attrs.help; - this.invisible = (node.attrs.invisible == '1'); + this.invisible = this.modifiers['invisible'] === true; }, start: function() { this.$element = $('#' + this.element_id); }, - process_attrs: function() { + process_modifiers: function() { var compute_domain = openerp.base.form.compute_domain; - for (var a in this.attrs) { - this[a] = compute_domain(this.attrs[a], this.view.fields); + for (var a in this.modifiers) { + this[a] = compute_domain(this.modifiers[a], this.view.fields); } }, update_dom: function() { @@ -739,10 +736,9 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ this.field = view.fields_view.fields[node.attrs.name] || {}; this.string = node.attrs.string || this.field.string; this.help = node.attrs.help || this.field.help; - this.invisible = (this.invisible || this.field.invisible == '1'); - this.nolabel = (this.field.nolabel || node.attrs.nolabel) == '1'; - this.readonly = (this.field.readonly || node.attrs.readonly) == '1'; - this.required = (this.field.required || node.attrs.required) == '1'; + this.nolabel = (this.field.nolabel || node.attrs.nolabel) === '1'; + this.readonly = this.modifiers['readonly'] === true; + this.required = this.modifiers['required'] === true; this.invalid = false; this.touched = false; }, @@ -801,7 +797,7 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ var v_context1 = this.node.attrs.default_get || {}; var v_context2 = this.node.attrs.context || {}; var v_context = new openerp.base.CompoundContext(v_context1, v_context2); - if (v_context1.__ref || v_context2.__ref) { + if (v_context1.__ref || v_context2.__ref || true) { //TODO niv: remove || true var fields_values = this._build_view_fields_values(); v_context.set_eval_context(fields_values); } @@ -811,7 +807,7 @@ openerp.base.form.Field = openerp.base.form.Widget.extend({ build_domain: function() { var f_domain = this.field.domain || []; var v_domain = this.node.attrs.domain || []; - if (!(v_domain instanceof Array)) { + if (!(v_domain instanceof Array) || true) { //TODO niv: remove || true var fields_values = this._build_view_fields_values(); v_domain = new openerp.base.CompoundDomain(v_domain).set_eval_context(fields_values); } @@ -915,6 +911,25 @@ openerp.base.form.FieldFloat = openerp.base.form.FieldChar.extend({ } }); +openerp.base.form.FieldInteger = openerp.base.form.FieldFloat.extend({ + init: function(view, node) { + this._super(view, node); + this.validation_regex = /^-?\d+$/; + }, + set_value: function(value) { + this._super.apply(this, [value]); + if (value === false || value === undefined) { + // TODO fme: check if GTK client default integers to 0 (like it does with floats) + value = 0; + } + var show_value = parseInt(value, 10); + this.$element.find('input').val(show_value); + }, + set_value_from_ui: function() { + this.value = Number(this.$element.find('input').val()); + } +}); + openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ init: function(view, node) { this._super(view, node); @@ -935,7 +950,7 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ }, set_value: function(value) { this._super.apply(this, arguments); - if (value == null || value == false) { + if (!value) { this.$element.find('input').val(''); } else { this.$element.find('input').unbind('change'); @@ -1086,7 +1101,7 @@ openerp.base.form.FieldProgressBar = openerp.base.form.Field.extend({ set_value: function(value) { this._super.apply(this, arguments); var show_value = Number(value); - if (show_value === NaN) { + if (isNaN(show_value)) { show_value = 0; } this.$element.find('div').progressbar('option', 'value', show_value).find('span').html(show_value + '%'); @@ -1101,28 +1116,54 @@ openerp.base.form.FieldSelection = openerp.base.form.Field.extend({ init: function(view, node) { this._super(view, node); this.template = "FieldSelection"; + this.field_index = _.map(this.field.selection, function(x, index) { + return {"ikey": "" + index, "ekey": x[0], "label": x[1]}; + }); }, start: function() { + // Flag indicating whether we're in an event chain containing a change + // event on the select, in order to know what to do on keyup[RETURN]: + // * If the user presses [RETURN] as part of changing the value of a + // selection, we should just let the value change and not let the + // event broadcast further (e.g. to validating the current state of + // the form in editable list view, which would lead to saving the + // current row or switching to the next one) + // * If the user presses [RETURN] with a select closed (side-effect: + // also if the user opened the select and pressed [RETURN] without + // changing the selected value), takes the action as validating the + // row + var ischanging = false; this._super.apply(this, arguments); - this.$element.find('select').change(this.on_ui_change); + this.$element.find('select') + .change(this.on_ui_change) + .change(function () { ischanging = true; }) + .click(function () { ischanging = false; }) + .keyup(function (e) { + if (e.which !== 13 || !ischanging) { return; } + e.stopPropagation(); + ischanging = false; + }); }, set_value: function(value) { - this._super.apply(this, arguments); - if (value != null && value !== false) { - this.$element.find('select').val(value); - } else { - this.$element.find('select').val('false'); - } + value = value === null ? false : value; + value = value instanceof Array ? value[0] : value; + this._super(value); + var option = _.detect(this.field_index, function(x) {return x.ekey === value;}); + this.$element.find('select').val(option === undefined ? '' : option.ikey); }, set_value_from_ui: function() { - this.value = this.$element.find('select').val(); + var ikey = this.$element.find('select').val(); + var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); + this.value = option === undefined ? false : option.ekey; }, update_dom: function() { this._super.apply(this, arguments); this.$element.find('select').attr('disabled', this.readonly); }, validate: function() { - this.invalid = this.required && this.$element.find('select').val() === ""; + var ikey = this.$element.find('select').val(); + var option = _.detect(this.field_index, function(x) {return x.ikey === ikey;}); + this.invalid = this.required && (option === undefined || option.ekey === false); }, focus: function() { this.$element.find('select').focus(); @@ -1493,7 +1534,9 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({ } self.is_started.resolve(); }); - this.viewmanager.start(); + setTimeout(function () { + self.viewmanager.start(); + }, 0); }, reload_current_view: function() { var self = this; @@ -1646,7 +1689,9 @@ openerp.base.form.FieldMany2Many = openerp.base.form.Field.extend({ this.list_view.on_loaded.add_last(function() { self.is_started.resolve(); }); - this.list_view.start(); + setTimeout(function () { + self.list_view.start(); + }, 0); }, set_value: function(value) { value = value || []; @@ -2021,7 +2066,7 @@ openerp.base.form.widgets = new openerp.base.Registry({ 'reference' : 'openerp.base.form.FieldReference', 'boolean' : 'openerp.base.form.FieldBoolean', 'float' : 'openerp.base.form.FieldFloat', - 'integer': 'openerp.base.form.FieldFloat', + 'integer': 'openerp.base.form.FieldInteger', 'progressbar': 'openerp.base.form.FieldProgressBar', 'float_time': 'openerp.base.form.FieldFloatTime', 'image': 'openerp.base.form.FieldBinaryImage', diff --git a/addons/base/static/src/js/list-editable.js b/addons/base/static/src/js/list-editable.js index b97a35d0612..a460dfcff41 100644 --- a/addons/base/static/src/js/list-editable.js +++ b/addons/base/static/src/js/list-editable.js @@ -116,6 +116,23 @@ openerp.base.list.editable = function (openerp) { delete this.edition_index; delete this.edition; }, + /** + * Adapts this list's view description to be suitable to the inner form view of a row being edited. + * + * @returns {Object} fields_view_get's view section suitable for putting into form view of editable rows. + */ + get_form_fields_view: function () { + // deep copy of view + var view = $.extend(true, {}, this.group.view.fields_view); + _(view.arch.children).each(function (widget) { + widget.attrs.nolabel = true; + if (widget.tag === 'button') { + delete widget.attrs.string; + } + }); + view.arch.attrs.col = 2 * view.arch.children.length; + return view; + }, render_row_as_form: function (row) { this.cancel_pending_edition(); @@ -161,7 +178,7 @@ openerp.base.list.editable = function (openerp) { template: 'ListView.row.form', registry: openerp.base.list.form.widgets }); - $.when(this.edition_form.on_loaded({fields_view: this.get_fields_view()})).then(function () { + $.when(this.edition_form.on_loaded({fields_view: this.get_form_fields_view()})).then(function () { // put in $.when just in case FormView.on_loaded becomes asynchronous $new_row.find('td') .addClass('oe-field-cell') @@ -251,10 +268,12 @@ openerp.base.list.editable = function (openerp) { openerp.base.list.form[key] = (form_widgets.get_object(key)).extend({ update_dom: function () { this.$element.children().css('visibility', ''); - if (this.invisible && this.node.attrs.invisible !== '1') { + if (this.invisible) { this.$element.children().css('visibility', 'hidden'); } else { + this.invisible = !!this.modifiers.tree_invisible; this._super(); + this.invisible = false; } } }); diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 9c68e4f9b78..c4aea837a4f 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -59,6 +59,24 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi if (this.dataset instanceof openerp.base.DataSetStatic) { this.groups.datagroup = new openerp.base.StaticDataGroup(this.dataset); } + + this.page = 0; + }, + /** + * Retrieves the view's number of records per page (|| section) + * + * options > defaults > view_manager.action.limit > indefinite + * + * @returns {Number|null} + */ + limit: function () { + if (this._limit === undefined) { + this._limit = (this.options.limit + || this.defaults.limit + || (this.view_manager.action || {}).limit + || null); + } + return this._limit; }, /** * Set a custom Group construct as the root of the List View. @@ -134,10 +152,10 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi this.$element.html(QWeb.render("ListView", this)); // Head hook - this.$element.find('#oe-list-add') + this.$element.find('.oe-list-add') .click(this.do_add_record) .attr('disabled', grouped && this.options.editable); - this.$element.find('#oe-list-delete') + this.$element.find('.oe-list-delete') .attr('disabled', true) .click(this.do_delete_selected); this.$element.find('thead').delegate('th[data-id]', 'click', function (e) { @@ -149,8 +167,75 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi self.reload_view(); }); + this.$element.find('.oe-list-pager') + .delegate('button', 'click', function () { + var $this = $(this); + switch ($this.data('pager-action')) { + case 'first': + self.page = 0; break; + case 'last': + self.page = Math.floor( + self.dataset.ids.length / self.limit()); + break; + case 'next': + self.page += 1; break; + case 'previous': + self.page -= 1; break; + } + self.reload_content(); + }).find('.oe-pager-state') + .click(function (e) { + e.stopPropagation(); + var $this = $(this); + + var $select = $(' diff --git a/addons/base/static/test/list.js b/addons/base/static/test/list.js index 1a2b1719086..3d441f190db 100644 --- a/addons/base/static/test/list.js +++ b/addons/base/static/test/list.js @@ -149,7 +149,7 @@ $(document).ready(function () { listview.$element.find('tbody th input:eq(1)') .attr('checked', true); - listview.$element.find('#oe-list-delete').click(); + listview.$element.find('.oe-list-delete').click(); deepEqual(deleted, [2, 3]); }); }); diff --git a/addons/base_gantt/static/src/js/gantt.js b/addons/base_gantt/static/src/js/gantt.js index 7f7aec85b63..336454f0bd1 100644 --- a/addons/base_gantt/static/src/js/gantt.js +++ b/addons/base_gantt/static/src/js/gantt.js @@ -262,21 +262,13 @@ init: function(view_manager, session, element_id, dataset, view_id) { throw "Unrecognized date/time format"; }, - reload_gantt: function(domain) { + reload_gantt: function() { var self = this; - var ajax = { - url: '/base/dataset/search_read', - async: false - }; - this.rpc(ajax, { - model: this.dataset.model, - domain: self.dataset.domain, - context :self.dataset.get_context() - }, function(response) { - ganttChartControl.clearAll(); - jQuery("#GanttDiv").children().remove(); - self.load_event(response); - }); + this.dataset.read_slice(false, false, false, function(response) { + ganttChartControl.clearAll(); + jQuery("#GanttDiv").children().remove(); + self.load_event(response); + }); }, do_search: function (domains, contexts, groupbys) { @@ -290,7 +282,7 @@ init: function(view_manager, session, element_id, dataset, view_id) { }, function (results) { self.dataset.context = results.context; self.dataset.domain = results.domain; - return self.reload_gantt(self.dataset.domain); + self.reload_gantt(); }); } diff --git a/addons/base_hello/__openerp__.py b/addons/base_hello/__openerp__.py index d52b5c82ec1..7a80645f3b8 100644 --- a/addons/base_hello/__openerp__.py +++ b/addons/base_hello/__openerp__.py @@ -4,4 +4,5 @@ "depends": [], "js": ["static/*/*.js", "static/*/js/*.js"], "css": [], + 'active': False, } diff --git a/addons/web_mobile/static/src/js/web_mobile.js b/addons/web_mobile/static/src/js/web_mobile.js index be856678e31..cdf25b22b38 100644 --- a/addons/web_mobile/static/src/js/web_mobile.js +++ b/addons/web_mobile/static/src/js/web_mobile.js @@ -3,4 +3,3 @@ openerp.web_mobile = function(instance) { openerp.web_mobile.list_mobile(instance); openerp.web_mobile.form_mobile(instance); }; - diff --git a/openerpweb/openerpweb.py b/openerpweb/openerpweb.py index 33c5c14edb3..13864d3e026 100644 --- a/openerpweb/openerpweb.py +++ b/openerpweb/openerpweb.py @@ -74,8 +74,7 @@ class OpenERPSession(object): Used to store references to non-literal domains which need to be round-tripped to the client browser. """ - def __init__(self, server='127.0.0.1', port=8069, - model_factory=OpenERPModel): + def __init__(self, server='127.0.0.1', port=8069, model_factory=OpenERPModel): self._server = server self._port = port self._db = False @@ -234,11 +233,7 @@ class OpenERPSession(object): # OpenERP Web RequestHandler #---------------------------------------------------------- class JsonRequest(object): - """ JSON-RPC2 over HTTP POST using non standard POST encoding. - Difference with the standard: - - * the json string is passed as a form parameter named "request" - * method is currently ignored + """ JSON-RPC2 over HTTP. Sucessful request:: @@ -278,7 +273,9 @@ class JsonRequest(object): self.httpsession_id = "cookieid" self.httpsession = cherrypy.session self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex - self.session = self.httpsession.setdefault(self.session_id, OpenERPSession()) + host = cherrypy.config['openerp.server.host'] + port = cherrypy.config['openerp.server.port'] + self.session = self.httpsession.setdefault(self.session_id, OpenERPSession(host, port)) self.context = self.params.pop('context', None) return self.params @@ -369,7 +366,9 @@ class HttpRequest(object): self.httpsession_id = "cookieid" self.httpsession = cherrypy.session self.context = kw.get('context', {}) - self.session = self.httpsession.setdefault(kw.get('session_id', None), OpenERPSession()) + host = cherrypy.config['openerp.server.host'] + port = cherrypy.config['openerp.server.port'] + self.session = self.httpsession.setdefault(kw.get('session_id', None), OpenERPSession(host, port)) self.result = "" if request.method == 'GET': print "GET --> %s.%s %s %r" % (controller.__class__.__name__, f.__name__, request, kw) @@ -454,8 +453,10 @@ class Root(object): def main(argv): # change the timezone of the program to the OpenERP server's assumed timezone os.environ["TZ"] = "UTC" - + DEFAULT_CONFIG = { + 'openerp.server.host': '127.0.0.1', + 'openerp.server.port': 8069, 'server.socket_port': 8002, 'server.socket_host': '0.0.0.0', 'tools.sessions.on': True, @@ -463,13 +464,13 @@ def main(argv): 'tools.sessions.storage_path': os.path.join(tempfile.gettempdir(), "cpsessions"), 'tools.sessions.timeout': 60 } - + # Parse config op = optparse.OptionParser() - op.add_option("-p", "--port", dest="server.socket_port", help="listening port", - type="int", metavar="NUMBER") - op.add_option("-s", "--session-path", dest="tools.sessions.storage_path", - help="directory used for session storage", metavar="DIR") + op.add_option("-p", "--port", dest="server.socket_port", help="listening port", type="int", metavar="NUMBER") + op.add_option("-s", "--session-path", dest="tools.sessions.storage_path", help="directory used for session storage", metavar="DIR") + op.add_option("", "--server-host", dest="openerp.server.host", help="OpenERP server hostname", metavar="HOST") + op.add_option("", "--server-port", dest="openerp.server.port", help="OpenERP server port", type="int", metavar="NUMBER") (o, args) = op.parse_args(argv[1:]) o = vars(o) for k in o.keys(): @@ -478,19 +479,17 @@ def main(argv): # Setup and run cherrypy cherrypy.tree.mount(Root()) - + cherrypy.config.update(config=DEFAULT_CONFIG) - if os.path.exists(os.path.join(os.path.dirname( - os.path.dirname(__file__)),'openerp-web.cfg')): - cherrypy.config.update(os.path.join(os.path.dirname( - os.path.dirname(__file__)),'openerp-web.cfg')) + if os.path.exists(os.path.join(os.path.dirname( os.path.dirname(__file__)),'openerp-web.cfg')): + cherrypy.config.update(os.path.join(os.path.dirname( os.path.dirname(__file__)),'openerp-web.cfg')) if os.path.exists(os.path.expanduser('~/.openerp_webrc')): cherrypy.config.update(os.path.expanduser('~/.openerp_webrc')) cherrypy.config.update(o) - + if not os.path.exists(cherrypy.config['tools.sessions.storage_path']): - os.mkdir(cherrypy.config['tools.sessions.storage_path'], 0700) - + os.makedirs(cherrypy.config['tools.sessions.storage_path'], 0700) + cherrypy.server.subscribe() cherrypy.engine.start() cherrypy.engine.block()