summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-03-22 20:05:14 +0100
committerChristophe Simonis <chs@odoo.com>2018-03-22 20:05:14 +0100
commitcdbee48888a9028ed54abc2c764d2b560e0af099 (patch)
tree72dcd7ea458cd6ce14d2e365ee82bea53947dc4a /addons/web
parent7d86bdca2111e3aeec8d165814b086c43b62998e (diff)
parent39d9c362c5b67a6c5a5d589daa13941e21358b1d (diff)
[MERGE] forward port branch 11.0 up to 39d9c362c5b
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/controllers/main.py63
-rw-r--r--addons/web/i18n/en_GB.po45
-rw-r--r--addons/web/i18n/es_EC.po38
-rw-r--r--addons/web/static/src/js/libs/jquery.js3
-rw-r--r--addons/web/static/src/js/views/basic/basic_renderer.js16
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js4
-rw-r--r--addons/web/static/src/less/list_view.less8
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js79
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="{&quot;readonly&quot; : [(&quot;turtles&quot;, &quot;!=&quot;, [])] }"/>' +
+ '<field name="qux" attrs="{&quot;readonly&quot; : [(&quot;turtles&quot;, &quot;!=&quot;, [])] }"/>' +
+ '</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();