diff options
| author | noz (OpenERP) <noz@tinyerp.com> | 2011-07-13 15:02:09 +0530 |
|---|---|---|
| committer | noz (OpenERP) <noz@tinyerp.com> | 2011-07-13 15:02:09 +0530 |
| commit | bcccef82d08ce5ecc626fa6a47f2d13f854bf176 (patch) | |
| tree | b041d9716df0a55e283c3feee5c327c3cd8015f3 /addons/base | |
| parent | 59bb0fd4e637cd4100e53d24df184ad5c53ed86b (diff) | |
| parent | 97966e8effa47972106d7f016532d80b64f96f99 (diff) | |
[Merge] Merged with main branch.
bzr revid: noz@tinyerp.com-20110713093209-3f2njjjhp0cgd5rj
Diffstat (limited to 'addons/base')
| -rw-r--r-- | addons/base/controllers/main.py | 6 | ||||
| -rw-r--r-- | addons/base/static/lib/qweb/qweb2.js | 1 | ||||
| -rw-r--r-- | addons/base/static/src/js/chrome.js | 6 | ||||
| -rw-r--r-- | addons/base/static/src/js/data.js | 46 | ||||
| -rw-r--r-- | addons/base/static/src/js/form.js | 57 | ||||
| -rw-r--r-- | addons/base/static/src/js/list.js | 34 | ||||
| -rw-r--r-- | addons/base/static/src/js/views.js | 95 | ||||
| -rw-r--r-- | addons/base/static/src/xml/base.xml | 44 |
8 files changed, 186 insertions, 103 deletions
diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 618d86f3750..5657ef13aaf 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -394,7 +394,7 @@ def fix_view_modes(action): generate_views(action) if action.pop('view_type') != 'form': - return + return action action['views'] = [ [id, mode if mode != 'tree' else 'list'] @@ -596,12 +596,12 @@ class DataSet(openerpweb.Controller): class DataGroup(openerpweb.Controller): _cp_path = "/base/group" @openerpweb.jsonrequest - def read(self, request, model, group_by_fields, domain=None): + def read(self, request, model, fields, group_by_fields, domain=None): Model = request.session.model(model) context, domain = eval_context_and_domain(request.session, request.context, domain) return Model.read_group( - domain or [], False, group_by_fields, 0, False, + domain or [], fields, group_by_fields, 0, False, dict(context, group_by=group_by_fields)) class View(openerpweb.Controller): diff --git a/addons/base/static/lib/qweb/qweb2.js b/addons/base/static/lib/qweb/qweb2.js index e617df60183..4f136f3c98a 100644 --- a/addons/base/static/lib/qweb/qweb2.js +++ b/addons/base/static/lib/qweb/qweb2.js @@ -304,6 +304,7 @@ QWeb2.Engine = (function() { " /* START TEMPLATE */ try {\n" + (e.compile()) + "\n" + " /* END OF TEMPLATE */ } catch(error) {\n" + + " if (console && console.exception) console.exception(error);\n" + " context.engine.tools.exception('Runtime Error: ' + error, context);\n" + " }\n" + " return r.join('');"; diff --git a/addons/base/static/src/js/chrome.js b/addons/base/static/src/js/chrome.js index 47e3de67677..98f0af5a8d1 100644 --- a/addons/base/static/src/js/chrome.js +++ b/addons/base/static/src/js/chrome.js @@ -845,6 +845,7 @@ openerp.base.Dialog = openerp.base.BaseWidget.extend({ this.$dialog.dialog('close'); }, stop: function () { + this.close(); this.$dialog.dialog('destroy'); } }); @@ -1174,6 +1175,11 @@ openerp.base.Login = openerp.base.Controller.extend({ this.selected_db = localStorage.getItem('last_db_login_success'); this.selected_login = localStorage.getItem('last_login_login_success'); } + if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) { + this.selected_db = this.selected_db || "trunk"; + this.selected_login = this.selected_login || "admin"; + this.selected_password = this.selected_password || "a"; + } }, start: function() { var self = this; diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index 1eb9c0f0a0d..534fd356f06 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -120,29 +120,25 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend( aggregates: aggregates }; }, - fetch: function () { + fetch: function (fields) { // internal method var d = new $.Deferred(); var self = this; - // disable caching for now, not sure what I should do there - if (false && this.groups) { - d.resolveWith(this, [this.groups]); - } else { - this.rpc('/base/group/read', { - model: this.model, - context: this.context, - domain: this.domain, - group_by_fields: this.group_by - }, function () { }).then(function (response) { - var data_groups = _(response).map( - _.bind(self.transform_group, self)); - self.groups = data_groups; - d.resolveWith(self, [data_groups]); - }, function () { - d.rejectWith.apply(d, self, [arguments]); - }); - } + this.rpc('/base/group/read', { + model: this.model, + context: this.context, + domain: this.domain, + fields: _.uniq(this.group_by.concat(fields)), + group_by_fields: this.group_by + }, function () { }).then(function (response) { + var data_groups = _(response).map( + _.bind(self.transform_group, self)); + self.groups = data_groups; + d.resolveWith(self, [data_groups]); + }, function () { + d.rejectWith.apply(d, [self, arguments]); + }); return d.promise(); }, /** @@ -163,10 +159,14 @@ openerp.base.ContainerDataGroup = openerp.base.DataGroup.extend( * records have for the current ``grouped_on`` field name). * ``aggregates`` * a mapping of other aggregation fields provided by ``read_group`` + * + * @param {Array} fields the list of fields to aggregate in each group, can be empty + * @param {Function} ifGroups function executed if any group is found (DataGroup.group_by is non-null and non-empty), called with a (potentially empty) list of groups as parameters. + * @param {Function} ifRecords function executed if there is no grouping left to perform, called with a DataSet instance as parameter */ - list: function (ifGroups, ifRecords) { + list: function (fields, ifGroups, ifRecords) { var self = this; - this.fetch().then(function (group_records) { + this.fetch(fields).then(function (group_records) { ifGroups(_(group_records).map(function (group) { var child_context = _.extend({}, self.context, group.__context); return _.extend( @@ -195,7 +195,7 @@ openerp.base.GrouplessDataGroup = openerp.base.DataGroup.extend( init: function (session, model, domain, context, level) { this._super(session, model, domain, context, null, level); }, - list: function (ifGroups, ifRecords) { + list: function (fields, ifGroups, ifRecords) { ifRecords(_.extend( new openerp.base.DataSetSearch(this.session, this.model), {domain: this.domain, context: this.context})); @@ -215,7 +215,7 @@ openerp.base.StaticDataGroup = openerp.base.GrouplessDataGroup.extend( init: function (dataset) { this.dataset = dataset; }, - list: function (ifGroups, ifRecords) { + list: function (fields, ifGroups, ifRecords) { ifRecords(this.dataset); } }); diff --git a/addons/base/static/src/js/form.js b/addons/base/static/src/js/form.js index 7517ec23e01..7faa942c6b0 100644 --- a/addons/base/static/src/js/form.js +++ b/addons/base/static/src/js/form.js @@ -51,6 +51,11 @@ openerp.base.FormView = openerp.base.View.extend( /** @lends openerp.base.FormV toolbar:!!this.flags.sidebar, context: context}, this.on_loaded); } }, + stop: function() { + _.each(this.widgets, function(w) { + w.stop(); + }); + }, on_loaded: function(data) { var self = this; this.fields_view = data.fields_view; @@ -532,6 +537,9 @@ openerp.base.form.Widget = openerp.base.Controller.extend({ start: function() { this.$element = $('#' + this.element_id); }, + stop: function() { + this.$element.remove(); + }, process_modifiers: function() { var compute_domain = openerp.base.form.compute_domain; for (var a in this.modifiers) { @@ -590,7 +598,10 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ } }, handle_node: function(node) { - var type = this.view.fields_view.fields[node.attrs.name] || {}; + var type = {}; + if (node.tag == 'field') { + type = this.view.fields_view.fields[node.attrs.name] || {}; + } var widget = new (this.view.registry.get_any( [node.attrs.widget, type.type, node.tag])) (this.view, node); if (node.tag == 'field') { @@ -617,14 +628,14 @@ openerp.base.form.WidgetFrame = openerp.base.form.Widget.extend({ }); openerp.base.form.WidgetNotebook = openerp.base.form.Widget.extend({ + template: 'WidgetNotebook', init: function(view, node) { this._super(view, node); - this.template = "WidgetNotebook"; this.pages = []; for (var i = 0; i < node.children.length; i++) { var n = node.children[i]; if (n.tag == "page") { - var page = new openerp.base.form.WidgetFrame(this.view, n); + var page = new openerp.base.form.WidgetNotebookPage(this.view, n, this, this.pages.length); this.pages.push(page); } } @@ -635,6 +646,28 @@ openerp.base.form.WidgetNotebook = openerp.base.form.Widget.extend({ } }); +openerp.base.form.WidgetNotebookPage = openerp.base.form.WidgetFrame.extend({ + template: 'WidgetNotebookPage', + init: function(view, node, notebook, index) { + this.notebook = notebook; + this.index = index; + this.element_name = 'page_' + index; + this._super(view, node); + this.element_tab_id = this.element_id + '_tab'; + }, + start: function() { + this._super.apply(this, arguments); + this.$element_tab = $('#' + this.element_tab_id); + }, + update_dom: function() { + if (this.invisible) { + this.notebook.$element.tabs('select', 0); + } + this.$element_tab.toggle(!this.invisible); + this.$element.toggle(!this.invisible); + } +}); + openerp.base.form.WidgetSeparator = openerp.base.form.Widget.extend({ init: function(view, node) { this._super(view, node); @@ -902,6 +935,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; } var show_value = value.toFixed(2); this.$element.find('input').val(show_value); @@ -921,6 +955,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; } var show_value = parseInt(value, 10); this.$element.find('input').val(show_value); @@ -967,7 +1002,7 @@ openerp.base.form.FieldDatetime = openerp.base.form.Field.extend({ }, update_dom: function() { this._super.apply(this, arguments); - this.$element.find('input').attr('disabled', this.readonly); + this.$element.find('input').datepicker(this.readonly ? 'disable' : 'enable'); }, validate: function() { this.invalid = false; @@ -1007,6 +1042,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; } var show_value = _.sprintf("%02d:%02d", Math.floor(value), Math.round((value % 1) * 60)); this.$element.find('input').val(show_value); @@ -1285,10 +1321,12 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ } this.$input.focusout(anyoneLoosesFocus); + var isSelecting = false; // autocomplete this.$input.autocomplete({ source: function(req, resp) { self.get_search_result(req, resp); }, select: function(event, ui) { + isSelecting = true; var item = ui.item; if (item.id) { self._change_int_value([item.id, item.name]); @@ -1306,6 +1344,14 @@ openerp.base.form.FieldMany2One = openerp.base.form.Field.extend({ minLength: 0, delay: 0 }); + // used to correct a bug when selecting an element by pushing 'enter' in an editable list + this.$input.keyup(function(e) { + if (e.which === 13) { + if (isSelecting) + e.stopPropagation(); + } + isSelecting = false; + }); }, // autocomplete component content handling get_search_result: function(request, response) { @@ -1775,7 +1821,8 @@ openerp.base.form.SelectCreatePopup = openerp.base.BaseWidget.extend({ this.initial_ids = this.options.initial_ids; jQuery(this.render()).dialog({title: '', modal: true, - minWidth: 800}); + width: 960, + height: 600}); this.start(); }, start: function() { diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index c4aea837a4f..c1df8857f08 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -256,11 +256,12 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi if (column.modifiers) { var modifiers = JSON.parse(column.modifiers); column.modifiers_for = function (fields) { - var result = {}; - for (var modifier in modifiers) { - result[modifier] = domain_computer(modifiers[modifier], fields); + if (!modifiers.invisible) { + return {}; } - return result; + return { + 'invisible': domain_computer(modifiers.invisible, fields) + }; }; } else { column.modifiers_for = noop; @@ -1074,18 +1075,23 @@ openerp.base.ListView.Groups = Class.extend( /** @lends openerp.base.ListView.Gr var self = this; var $element = $('<tbody>'); this.elements = [$element[0]]; - this.datagroup.list(function (groups) { - $element[0].appendChild( - self.render_groups(groups)); - if (post_render) { post_render(); } - }, function (dataset) { - self.render_dataset(dataset).then(function (list) { - self.children[null] = list; - self.elements = - [list.$current.replaceAll($element)[0]]; + + this.datagroup.list( + _(this.view.visible_columns).chain() + .filter(function (column) { return column.tag === 'field' }) + .pluck('name').value(), + function (groups) { + $element[0].appendChild( + self.render_groups(groups)); if (post_render) { post_render(); } + }, function (dataset) { + self.render_dataset(dataset).then(function (list) { + self.children[null] = list; + self.elements = + [list.$current.replaceAll($element)[0]]; + if (post_render) { post_render(); } + }); }); - }); return $element; }, /** diff --git a/addons/base/static/src/js/views.js b/addons/base/static/src/js/views.js index 9ed8886c1e5..a8ba8067bc0 100644 --- a/addons/base/static/src/js/views.js +++ b/addons/base/static/src/js/views.js @@ -9,7 +9,7 @@ openerp.base.ActionManager = openerp.base.Controller.extend({ init: function(session, element_id) { this._super(session, element_id); this.viewmanager = null; - this.dialog_stack = []; + this.current_dialog = null; // Temporary linking view_manager to session. // Will use controller_parent to find it when implementation will be done. session.action_manager = this; @@ -22,34 +22,44 @@ openerp.base.ActionManager = openerp.base.Controller.extend({ var self = this; action.flags = _.extend({ sidebar : action.target != 'new', - search_view : true, + search_view : action.target != 'new', new_window : false, - views_switcher : true, - action_buttons : true, - pager : true + views_switcher : action.target != 'new', + action_buttons : action.target != 'new', + pager : action.target != 'new' }, action.flags || {}); // instantiate the right controllers by understanding the action + if (this.current_dialog) { + this.current_dialog.stop(); + this.current_dialog = null; + } + if (this.current_dialog) { + this.current_dialog.stop(); + this.current_dialog = null; + } else if (this.view_manager && this.view_manager.current_dialog) { + this.view_manager.current_dialog.stop(); + this.view_manager.current_dialog = null; + } switch (action.type) { case 'ir.actions.act_window': - if (!action.target && this.dialog_stack.length) { + if (!action.target && this.current_dialog) { action.flags.new_window = true; } if (action.target == 'new') { - var element_id = _.uniqueId("act_window_dialog"); - $('<div>', {id: element_id}).dialog({ + var dialog = this.current_dialog = new openerp.base.ActionDialog(this.session, { title: action.name, - modal: true, - width: '50%', - height: 'auto' - }).bind('dialogclose', function(event) { - // When dialog is closed with ESC key or close manually, branch to act_window_close logic - self.do_action({ type: 'ir.actions.act_window_close' }); + width: '50%' }); - var viewmanager = new openerp.base.ViewManagerAction(this.session, element_id, action); + if (on_closed) { + dialog.on_closed.add_first(on_closed); + } + dialog.start(false); + var viewmanager = new openerp.base.ViewManagerAction(this.session, dialog.element_id, action); viewmanager.start(); - viewmanager.on_act_window_closed.add(on_closed); - viewmanager.is_dialog = true; - this.dialog_stack.push(viewmanager); + // TODO: merge ActionManager & ViewManager in order to get rid of this circular reference + viewmanager.current_dialog = dialog; + dialog.viewmanager = viewmanager; + dialog.open(); } else if (action.flags.new_window) { action.flags.new_window = false; this.rpc("/base/session/save_session_action", { the_action : action}, function(key) { @@ -66,12 +76,6 @@ openerp.base.ActionManager = openerp.base.Controller.extend({ } break; case 'ir.actions.act_window_close': - var dialog = this.dialog_stack.pop(); - if (!action.special) { - dialog.on_act_window_closed(); - } - dialog.$element.dialog('destroy'); - dialog.stop(); break; case 'ir.actions.server': this.rpc('/base/action/run', { @@ -100,7 +104,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ this.flags = this.flags || {}; this.sidebar = new openerp.base.NullSidebar(); this.registry = openerp.base.views; - this.is_dialog = false; }, /** * @returns {jQuery.Deferred} initial view loading promise @@ -219,11 +222,6 @@ openerp.base.ViewManager = openerp.base.Controller.extend({ return this.searchview.start(); }, /** - * Called when this view manager has been created by an action 'act_window@target=new' is closed - */ - on_act_window_closed : function() { - }, - /** * Called when one of the view want to execute an action */ on_action: function(action) { @@ -344,6 +342,22 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({ } }); +openerp.base.ActionDialog = openerp.base.Dialog.extend({ + identifier_prefix: 'action_dialog', + close: function() { + this._super(this, arguments); + this.on_closed(); + }, + on_closed: function() { + }, + stop: function() { + this._super(this, arguments); + if (this.viewmanager) { + this.viewmanager.stop(); + } + } +}); + openerp.base.Sidebar = openerp.base.BaseWidget.extend({ template: "ViewManager.sidebar", init: function(parent, view_manager) { @@ -398,6 +412,7 @@ 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({ @@ -445,28 +460,22 @@ openerp.base.View = openerp.base.Controller.extend({ active_model: dataset.model }); action.flags = { - sidebar : false, - search_view : false, - views_switcher : false, - action_buttons : false, - pager : false, new_window: true }; action_manager.do_action(action, on_closed); - if (self.view_manager.is_dialog && action.type != 'ir.actions.act_window_close') { - handler({ - result : { type: 'ir.actions.act_window_close' } - }); - } } else { on_no_action(action); } }; if (action_data.special) { - handler({ - result : { type: 'ir.actions.act_window_close', special: action_data.special } - }); + if (action_manager.current_dialog) { + action_manager.current_dialog.stop(); + action_manager.current_dialog = null; + } else if (this.view_manager.current_dialog) { + this.view_manager.current_dialog.stop(); + this.view_manager.current_dialog = null; + } } else { var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {}); switch(action_data.type) { diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index e2b67c3aa8e..035332d2961 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -270,7 +270,8 @@ </tr> <tr> <td><label for="password">Password:</label></td> - <td><input type="password" name="password"/></td> + <td><input type="password" name="password" + t-att-value="selected_password || ''"/></td> </tr> <tr> <td></td> @@ -463,7 +464,7 @@ <t t-esc="column.string"/> </th> </t> - <th t-if="options.selectable"/> + <th t-if="options.selectable" width="1"/> <t t-foreach="columns" t-as="column"> <th t-if="!column.meta and column.invisible !== '1'" t-att-data-id="column.id" t-att-class="((options.sortable and column.tag !== 'button') ? 'oe-sortable' : null)"> @@ -473,7 +474,7 @@ </t> </th> </t> - <th t-if="options.deletable"/> + <th t-if="options.deletable" width="1"/> </tr> </thead> <tfoot class="ui-widget-header"> @@ -501,7 +502,7 @@ </td> </t> - <th t-if="options.selectable" class="oe-record-selector"> + <th t-if="options.selectable" class="oe-record-selector" width="1"> <input type="checkbox"/> </th> <t t-foreach="columns" t-as="column"> @@ -512,7 +513,7 @@ <t t-raw="render_cell(row.data, column)"/> </td> </t> - <td t-if="options.deletable" class='oe-record-delete'> + <td t-if="options.deletable" class='oe-record-delete' width="1"> <button type="button" name="delete">♻</button> </td> </tr> @@ -604,18 +605,21 @@ </t> <t t-name="WidgetNotebook"> <ul> - <li t-foreach="widget.pages" t-as="page"> - <a t-att-href="'#' + widget.element_id + '-' + page_index"> + <li t-foreach="widget.pages" t-as="page" t-att-id="page.element_tab_id"> + <a t-att-href="'#' + page.element_id"> <t t-esc="page.string"/> </a> </li> </ul> <t t-foreach="widget.pages" t-as="page"> - <div t-att-id="widget.element_id + '-' + page_index"> - <t t-raw="page.render()"/> - </div> + <t t-raw="page.render()"/> </t> </t> +<t t-name="WidgetNotebookPage"> + <div t-att-id="widget.element_id"> + <t t-call="WidgetFrame"/> + </div> +</t> <t t-name="WidgetSeparator"> <div t-att-class="'separator ' + (widget.node.attrs.orientation || 'horizontal')"> <t t-esc="widget.string"/> @@ -704,9 +708,9 @@ <span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'"> <img src="/base/static/src/img/icons/gtk-index.png"/></span> <div t-att-id="widget.cm_id" class="contextMenu" style="display:none"><ul> - <li t-att-id="widget.cm_id + '_search'">Search...</li> - <li t-att-id="widget.cm_id + '_create'">Create New...</li> <li t-att-id="widget.cm_id + '_open'" style="color:grey">Open...</li> + <li t-att-id="widget.cm_id + '_create'">Create and Edit...</li> + <li t-att-id="widget.cm_id + '_search'">Search...</li> </ul></div> </div> </t> @@ -1066,9 +1070,19 @@ </t> <t t-name="SelectCreatePopup"> <div t-att-id="element_id"> - <div t-att-id="element_id + '_search'"></div> - <div t-att-id="element_id + '_view_list'"></div> - <div t-att-id="element_id + '_view_form'"></div> + <table style="width:100%"> + <tr style="width:100%"> + <td style="width:100%"> + <div t-att-id="element_id + '_search'" style="width:100%"></div> + </td> + </tr> + <tr style="width:100%"> + <td style="width:100%"> + <div t-att-id="element_id + '_view_list'" style="width:100%"></div> + </td> + </tr> + </table> + <div t-att-id="element_id + '_view_form'" style="width:100%"></div> </div> </t> <t t-name="SelectCreatePopup.search.buttons"> |
