diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-03-22 20:05:14 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-03-22 20:05:14 +0100 |
| commit | cdbee48888a9028ed54abc2c764d2b560e0af099 (patch) | |
| tree | 72dcd7ea458cd6ce14d2e365ee82bea53947dc4a /addons/web | |
| parent | 7d86bdca2111e3aeec8d165814b086c43b62998e (diff) | |
| parent | 39d9c362c5b67a6c5a5d589daa13941e21358b1d (diff) | |
[MERGE] forward port branch 11.0 up to 39d9c362c5b
Diffstat (limited to 'addons/web')
| -rw-r--r-- | addons/web/controllers/main.py | 63 | ||||
| -rw-r--r-- | addons/web/i18n/en_GB.po | 45 | ||||
| -rw-r--r-- | addons/web/i18n/es_EC.po | 38 | ||||
| -rw-r--r-- | addons/web/static/src/js/libs/jquery.js | 3 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/basic/basic_renderer.js | 16 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/list/list_editable_renderer.js | 4 | ||||
| -rw-r--r-- | addons/web/static/src/less/list_view.less | 8 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/relational_fields_tests.js | 79 |
8 files changed, 126 insertions, 130 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 8a307e893be..0dccd508186 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -1494,69 +1494,6 @@ class ExcelExport(ExportFormat, http.Controller): fp.close() return data -class Reports(http.Controller): - POLLING_DELAY = 0.25 - TYPES_MAPPING = { - 'doc': 'application/vnd.ms-word', - 'html': 'text/html', - 'odt': 'application/vnd.oasis.opendocument.text', - 'pdf': 'application/pdf', - 'sxw': 'application/vnd.sun.xml.writer', - 'xls': 'application/vnd.ms-excel', - } - - @http.route('/web/report', type='http', auth="user") - @serialize_exception - def index(self, action, token): - action = json.loads(action) - - context = dict(request.context) - context.update(action["context"]) - - report_data = {} - report_ids = context.get("active_ids", None) - if 'report_type' in action: - report_data['report_type'] = action['report_type'] - if 'datas' in action: - if 'ids' in action['datas']: - report_ids = action['datas'].pop('ids') - report_data.update(action['datas']) - - report_id = dispatch_rpc('report', 'report', [ - request.session.db, request.session.uid, request.session.password, - action["report_name"], report_ids, report_data, context]) - - report_struct = None - while True: - report_struct = dispatch_rpc('report', 'report_get', [ - request.session.db, request.session.uid, request.session.password, report_id]) - if report_struct["state"]: - break - - time.sleep(self.POLLING_DELAY) - - report = base64.b64decode(report_struct['result']) - if report_struct.get('code') == 'zlib': - report = zlib.decompress(report) - report_mimetype = self.TYPES_MAPPING.get( - report_struct['format'], 'octet-stream') - file_name = action.get('name', 'report') - if 'name' not in action: - reports = request.env['ir.actions.report'] - reports = reports.search([('report_name', '=', action['report_name'])]) - if reports: - file_name = reports[0].name - else: - file_name = action['report_name'] - file_name = '%s.%s' % (file_name, report_struct['format']) - - return request.make_response(report, - headers=[ - ('Content-Disposition', content_disposition(file_name)), - ('Content-Type', report_mimetype), - ('Content-Length', len(report))], - cookies={'fileToken': token}) - class Apps(http.Controller): @http.route('/apps/<app>', auth='user') def get_app_url(self, req, app): diff --git a/addons/web/i18n/en_GB.po b/addons/web/i18n/en_GB.po index 3c746ff0ffb..779d64d623d 100644 --- a/addons/web/i18n/en_GB.po +++ b/addons/web/i18n/en_GB.po @@ -10,8 +10,7 @@ msgstr "" "POT-Creation-Date: 2016-08-18 14:08+0000\n" "PO-Revision-Date: 2016-04-21 09:34+0000\n" "Last-Translator: Martin Trigaux\n" -"Language-Team: English (United Kingdom) (http://www.transifex.com/odoo/" -"odoo-9/language/en_GB/)\n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/odoo/odoo-9/language/en_GB/)\n" "Language: en_GB\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1054,8 +1053,7 @@ msgstr "" #: code:addons/web/static/src/js/views/pivot_view.js:808 #, python-format msgid "" -"For Excel compatibility, data cannot be exported if there is more than 256 " -"columns.\n" +"For Excel compatibility, data cannot be exported if there is more than 256 columns.\n" "\n" "Tip: try to flip axis, filter further or reduce the number of measures." msgstr "" @@ -1465,8 +1463,8 @@ msgstr "" #: code:addons/web/static/src/js/views/graph_widget.js:95 #, python-format msgid "" -"No data available for this chart. Try to add some records, or make sure that " -"there is no active filter in the search bar." +"No data available for this chart. Try to add some records, or make sure that" +" there is no active filter in the search bar." msgstr "" #. module: web @@ -1474,10 +1472,8 @@ msgstr "" #: code:addons/web/static/src/xml/base.xml:691 #, python-format msgid "" -"No data available for this pivot table. Try to add some records, or make " -"sure\n" -" that there is at least one measure and no active filter in " -"the search bar." +"No data available for this pivot table. Try to add some records, or make sure\n" +" that there is at least one measure and no active filter in the search bar." msgstr "" #. module: web @@ -1527,7 +1523,7 @@ msgstr "" #: code:addons/web/static/src/js/views/form_relational_widgets.js:329 #, fuzzy, python-format msgid "No value found for the field %s for value %s" -msgstr "No value found for the field for value " +msgstr "No value found for the field for value %s" #. module: web #. openerp-web @@ -2154,8 +2150,8 @@ msgstr "The following fields are invalid:" #: code:addons/web/static/src/js/views/list_view_editable.js:124 #, python-format msgid "" -"The line has been modified, your changes will be discarded. Are you sure you " -"want to discard the changes ?" +"The line has been modified, your changes will be discarded. Are you sure you" +" want to discard the changes ?" msgstr "" #. module: web @@ -2207,11 +2203,11 @@ msgstr "The selected file exceed the maximum file size of %s." #: code:addons/web/static/src/js/views/form_relational_widgets.js:1550 #, python-format msgid "" -"The type of the field '%s' must be a many2many field with a relation to 'ir." -"attachment' model." +"The type of the field '%s' must be a many2many field with a relation to " +"'ir.attachment' model." msgstr "" -"The type of the field '%s' must be a many2many field with a relation to 'ir." -"attachment' model." +"The type of the field '%s' must be a many2many field with a relation to " +"'ir.attachment' model." #. module: web #. openerp-web @@ -2241,15 +2237,11 @@ msgstr "This resource is empty" #: code:addons/web/static/src/xml/base.xml:1304 #, python-format msgid "" -"This wizard will export all data that matches the current search criteria to " -"a CSV file.\n" -" You can export all data or only the fields that can be " -"reimported after modification." +"This wizard will export all data that matches the current search criteria to a CSV file.\n" +" You can export all data or only the fields that can be reimported after modification." msgstr "" -"This wizard will export all data that matches the current search criteria to " -"a CSV file.\n" -" You can export all data or only the fields that can be " -"reimported after modification." +"This wizard will export all data that matches the current search criteria to a CSV file.\n" +" You can export all data or only the fields that can be reimported after modification." #. module: web #. openerp-web @@ -2584,7 +2576,8 @@ msgstr "" #. openerp-web #: code:addons/web/static/src/js/framework/misc.js:17 #, python-format -msgid "You may not believe it,<br />but the application is actually loading..." +msgid "" +"You may not believe it,<br />but the application is actually loading..." msgstr "" "You may not believe it,<br />but the application is actually loading..." diff --git a/addons/web/i18n/es_EC.po b/addons/web/i18n/es_EC.po index f9e2bfa8c05..ff764f72120 100644 --- a/addons/web/i18n/es_EC.po +++ b/addons/web/i18n/es_EC.po @@ -12,16 +12,13 @@ msgstr "" "POT-Creation-Date: 2016-08-18 14:08+0000\n" "PO-Revision-Date: 2016-02-22 05:01+0000\n" "Last-Translator: Rick Hunter <rick_hunter_ec@yahoo.com>\n" -"Language-Team: Spanish (Ecuador) (http://www.transifex.com/odoo/odoo-9/" -"language/es_EC/)\n" +"Language-Team: Spanish (Ecuador) (http://www.transifex.com/odoo/odoo-9/language/es_EC/)\n" "Language: es_EC\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "#-#-#-#-# es_EC.po (Odoo 9.0) #-#-#-#-#\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"#-#-#-#-# es_EC.po (Odoo 9.0) #-#-#-#-#\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" #. module: web #. openerp-web @@ -1472,8 +1469,8 @@ msgstr "Sin actualizar:" #: code:addons/web/static/src/js/views/graph_widget.js:95 #, python-format msgid "" -"No data available for this chart. Try to add some records, or make sure that " -"there is no active filter in the search bar." +"No data available for this chart. Try to add some records, or make sure that" +" there is no active filter in the search bar." msgstr "" "No existen datos disponibles para este gráfico. Trate de añadir algunos " "récords, o asegúrese que no existan filtros activos en la barra de búsqueda." @@ -1483,10 +1480,8 @@ msgstr "" #: code:addons/web/static/src/xml/base.xml:691 #, python-format msgid "" -"No data available for this pivot table. Try to add some records, or make " -"sure\n" -" that there is at least one measure and no active filter in " -"the search bar." +"No data available for this pivot table. Try to add some records, or make sure\n" +" that there is at least one measure and no active filter in the search bar." msgstr "" "No existen datos disponibles para esta tabla dinámica. Trate de añadir " "algunos registros, o asegúrese que exista por lo menos una medida y no " @@ -1727,8 +1722,8 @@ msgid "" "Pie chart cannot display all zero numbers.. Try to change your domain to " "display positive results" msgstr "" -"Los gráficos de pastel no pueden mostrar los números 0. Trate de cambiar sus " -"filtros para mostrar los resultados positivos." +"Los gráficos de pastel no pueden mostrar los números 0. Trate de cambiar sus" +" filtros para mostrar los resultados positivos." #. module: web #. openerp-web @@ -2221,18 +2216,18 @@ msgstr "" #: code:addons/web/static/src/js/views/form_widgets.js:1199 #, python-format msgid "The selected file exceed the maximum file size of %s." -msgstr "El archivo seleccionado supera el tamaño máximo de% s." +msgstr "El archivo seleccionado supera el tamaño máximo de %s." #. module: web #. openerp-web #: code:addons/web/static/src/js/views/form_relational_widgets.js:1550 #, python-format msgid "" -"The type of the field '%s' must be a many2many field with a relation to 'ir." -"attachment' model." +"The type of the field '%s' must be a many2many field with a relation to " +"'ir.attachment' model." msgstr "" -"El tipo de campo '%s' debe ser un campo many2many con una relación a 'ir." -"attachment' model." +"El tipo de campo '%s' debe ser un campo many2many con una relación a " +"'ir.attachment' model." #. module: web #. openerp-web @@ -2261,10 +2256,8 @@ msgstr "El recurso esta vacío" #: code:addons/web/static/src/xml/base.xml:1304 #, python-format msgid "" -"This wizard will export all data that matches the current search criteria to " -"a CSV file.\n" -" You can export all data or only the fields that can be " -"reimported after modification." +"This wizard will export all data that matches the current search criteria to a CSV file.\n" +" You can export all data or only the fields that can be reimported after modification." msgstr "" "Este asistente exportará todos los datos que coincidan con el criterio de " "búsqueda actual a un archivo CSV.\n" @@ -2607,7 +2600,8 @@ msgstr "" #. openerp-web #: code:addons/web/static/src/js/framework/misc.js:17 #, python-format -msgid "You may not believe it,<br />but the application is actually loading..." +msgid "" +"You may not believe it,<br />but the application is actually loading..." msgstr "" "Usted no lo creerá,<br />pero la aplicación actualmente está cargando ..." diff --git a/addons/web/static/src/js/libs/jquery.js b/addons/web/static/src/js/libs/jquery.js index 0b12b4fed0d..4bcab8eb866 100644 --- a/addons/web/static/src/js/libs/jquery.js +++ b/addons/web/static/src/js/libs/jquery.js @@ -11,6 +11,9 @@ $.extend($.expr[':'], { containsLike: function (element, index, matches){ return element.innerHTML.toUpperCase().indexOf(matches[3].toUpperCase()) >= 0; }, + containsTextLike: function (element, index, matches){ + return element.innerText.toUpperCase().indexOf(matches[3].toUpperCase()) >= 0; + }, containsExact: function (element, index, matches){ return $.trim(element.innerHTML) === matches[3]; }, diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js index 977674c022a..e8367e79c26 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -256,7 +256,7 @@ var BasicRenderer = AbstractRenderer.extend({ // If the view is in edit mode and that a widget have to switch // its "readonly" state, we have to re-render it completely if ('readonly' in modifiers && element.widget) { - var mode = modifiers.readonly ? 'readonly' : modifiersData.baseMode; + var mode = modifiers.readonly ? 'readonly' : modifiersData.baseModeByRecord[record.id]; if (mode !== element.widget.mode) { self._rerenderFieldWidget(element.widget, record, { keepBaseMode: true, @@ -416,16 +416,17 @@ var BasicRenderer = AbstractRenderer.extend({ * @param {Object} [options.callback] the callback to call on registration * and on modifiers updates * @param {boolean} [options.keepBaseMode=false] this function registers the - * 'baseMode' of the node; this is a field widget specific settings which + * 'baseMode' of the node on a per record basis; + * this is a field widget specific settings which * represents the generic mode of the widget, regardless of its modifiers * (the interesting case is the list view: all widgets are supposed to be * in the baseMode 'readonly', except the ones that are in the line that * is currently being edited). - * With option 'keepBaseMode' set to true, the current baseMode of the + * With option 'keepBaseMode' set to true, the baseMode of the record's * node isn't overridden (this is particularily useful when a field widget * is re-rendered because its readonly modifier changed, as in this case, * we don't want to change its base mode). - * @param {string} [options.mode] the 'baseMode' of the node is set to this + * @param {string} [options.mode] the 'baseMode' of the record's node is set to this * value (if not given, it is set to this.mode, the mode of the renderer) * @returns {Object} for code efficiency, returns the last evaluated * modifiers for the given node and record. @@ -443,15 +444,16 @@ var BasicRenderer = AbstractRenderer.extend({ modifiers: modifiers, evaluatedModifiers: {}, elementsByRecord: {}, + baseModeByRecord : {}, }; if (!_.isEmpty(modifiers)) { // Register only if modifiers might change (TODO condition might be improved here) this.allModifiersData.push(modifiersData); } } - // Compute node's base mode if necessary - if (!options.keepBaseMode) { - modifiersData.baseMode = options.mode || this.mode; + // Compute the record's base mode + if (!modifiersData.baseModeByRecord[record.id] || !options.keepBaseMode) { + modifiersData.baseModeByRecord[record.id] = options.mode || this.mode; } // Evaluate if necessary diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js index 8155862dbb4..2d9c02b8ebc 100644 --- a/addons/web/static/src/js/views/list/list_editable_renderer.js +++ b/addons/web/static/src/js/views/list/list_editable_renderer.js @@ -504,8 +504,8 @@ ListRenderer.include({ var $row = this._super.apply(this, arguments); if (this.addTrashIcon) { var $icon = this.isMany2Many ? - $('<i>', {class: 'fa fa-times', name: 'unlink'}) : - $('<i>', {class: 'fa fa-trash-o', name: 'delete'}); + $('<button>', {class: 'fa fa-times o_list_record_remove', name: 'unlink', 'aria-label': _t('Unlink row ') + (index+1)}) : + $('<button>', {class: 'fa fa-trash-o o_list_record_remove', name: 'delete', 'aria-label': _t('Delete row ') + (index+1)}); var $td = $('<td>', {class: 'o_list_record_remove'}).append($icon); $row.append($td); } diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less index 98a1d56fac0..22e046bf923 100644 --- a/addons/web/static/src/less/list_view.less +++ b/addons/web/static/src/less/list_view.less @@ -70,6 +70,14 @@ width: 1px; // to prevent the column to expand } + .o_list_record_delete_btn { + padding: 0px; + background-style: none; + border-style: none; + height: 0px; + display: table-cell; + } + // Decoration of the row .text-bf { font-weight: bold; diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index 100c2436377..6528969bbb7 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2261,6 +2261,65 @@ QUnit.module('relational_fields', { QUnit.module('FieldOne2Many'); + QUnit.test('one2many list editable with cell readonly modifier', function (assert) { + assert.expect(4); + + this.data.partner.records[0].p = [2]; + this.data.partner.records[1].turtles = [1,2]; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'<form string="Partners">' + + '<field name="p">' + + '<tree editable="bottom">' + + '<field name="turtles" invisible="1"/>' + + '<field name="foo" attrs="{"readonly" : [("turtles", "!=", [])] }"/>' + + '<field name="qux" attrs="{"readonly" : [("turtles", "!=", [])] }"/>' + + '</tree>' + + '</field>' + + '</form>', + res_id: 1, + mockRPC: function (route, args) { + if (route === '/web/dataset/call_kw/partner/write') { + assert.deepEqual(args.args[1].p[1][2], {foo: 'ff', qux: 99}, + 'The right values should be written'); + } + return this._super(route, args); + } + }); + + form.$buttons.find('.o_form_button_edit').click(); + form.$('.o_field_x2many_list_row_add a').click(); + + var $targetInput = $('.o_selected_row .o_input[name=foo]'); + assert.equal($targetInput[0], document.activeElement, + 'The first input of the line should have the focus'); + + // Simulating hitting the 'f' key twice + $targetInput.val('f').trigger('input'); + $targetInput.val($targetInput.val() + 'f').trigger('input'); + + assert.equal($targetInput[0], document.activeElement, + 'The first input of the line should still have the focus'); + + // Simulating a TAB key + $targetInput.trigger($.Event('keydown', {which: 9, keyCode:9})); + + var $secondTarget = $('.o_selected_row .o_input[name=qux]'); + + assert.equal($secondTarget[0], document.activeElement, + 'The second input of the line should have the focus after the TAB press'); + + + $secondTarget.val(9).trigger('input'); + $secondTarget.val($secondTarget.val() + 9).trigger('input'); + + form.$buttons.find('.o_form_button_save').click(); + + form.destroy(); + }); + QUnit.test('one2many basic properties', function (assert) { assert.expect(6); @@ -3891,13 +3950,13 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('td.o_list_record_remove i').length, 2, + assert.strictEqual(form.$('td.o_list_record_remove button').length, 2, "should have 2 remove buttons"); - assert.ok(form.$('td.o_list_record_remove i').first().hasClass('fa fa-times'), + assert.ok(form.$('td.o_list_record_remove button').first().hasClass('fa fa-times'), "should have X icons to remove (unlink) records"); - form.$('td.o_list_record_remove i').first().click(); + form.$('td.o_list_record_remove button').first().click(); assert.strictEqual(form.$('td.o_list_record_remove i').length, 1, "should have 1 remove button (a record is supposed to have been unlinked)"); @@ -3937,13 +3996,13 @@ QUnit.module('relational_fields', { }); form.$buttons.find('.o_form_button_edit').click(); - assert.strictEqual(form.$('td.o_list_record_remove i').length, 2, + assert.strictEqual(form.$('td.o_list_record_remove button').length, 2, "should have 2 remove buttons"); - assert.ok(form.$('td.o_list_record_remove i').first().hasClass('fa fa-trash-o'), + assert.ok(form.$('td.o_list_record_remove button').first().hasClass('fa fa-trash-o'), "should have trash bin icons to remove (delete) records"); - form.$('td.o_list_record_remove i').first().click(); + form.$('td.o_list_record_remove button').first().click(); assert.strictEqual(form.$('td.o_list_record_remove i').length, 1, "should have 1 remove button (a record is supposed to have been deleted)"); @@ -6689,8 +6748,8 @@ QUnit.module('relational_fields', { form.$('input.o_field_integer[name="int_field"]').val('0').trigger('input'); // remove and start over - form.$('.o_list_record_remove:first i').click(); - form.$('.o_list_record_remove:first i').click(); + form.$('.o_list_record_remove:first button').click(); + form.$('.o_list_record_remove:first button').click(); // enable the many2many onchange form.$('input.o_field_integer[name="int_field"]').val('10').trigger('input'); @@ -8423,7 +8482,7 @@ QUnit.module('relational_fields', { mode: 'edit', }, }); - form.$('.o_list_record_remove:first i').click(); + form.$('.o_list_record_remove:first button').click(); assert.strictEqual(form.$('.o_data_row').text(), 'from onchange', 'onchange has been properly applied'); form.destroy(); @@ -8463,7 +8522,7 @@ QUnit.module('relational_fields', { mode: 'edit', }, }); - form.$('.o_list_record_remove:first i').click(); + form.$('.o_list_record_remove:first button').click(); assert.strictEqual(form.$('.o_data_row').text(), 'from onchange id2from onchange id3', 'onchange has been properly applied'); form.destroy(); |
