From 3579bd53bed09a6bd06ac32d8bce780937993501 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Mon, 30 Apr 2018 11:30:37 +0200 Subject: [PATCH 01/51] [FIX] hr_expense: account on expense - Set a specific expense account on an expense product - Send an email to the expense alias The specific expense account is not used; a default account is used instead. opw-1838174 --- addons/hr_expense/models/hr_expense.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/hr_expense/models/hr_expense.py b/addons/hr_expense/models/hr_expense.py index 53c64c4a5ac..703429b286f 100644 --- a/addons/hr_expense/models/hr_expense.py +++ b/addons/hr_expense/models/hr_expense.py @@ -350,6 +350,7 @@ class HrExpense(models.Model): expense_description = expense_description.replace(product_code.group(), '') products = self.env['product.product'].search([('default_code', 'ilike', product_code.group(1))]) or default_product product = products.filtered(lambda p: p.default_code == product_code.group(1)) or products[0] + account = product.product_tmpl_id._get_product_accounts()['expense'] pattern = '[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?' # Match the last occurence of a float in the string @@ -376,6 +377,8 @@ class HrExpense(models.Model): 'unit_amount': price, 'company_id': employee.company_id.id, }) + if account: + custom_values['account_id'] = account.id return super(HrExpense, self).message_new(msg_dict, custom_values) class HrExpenseSheet(models.Model): From e48767fe6509c9dc5bb3c0907ad36d16c4b5b773 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Mon, 14 May 2018 16:33:55 +0200 Subject: [PATCH 02/51] [FIX] mass_mailing: force to not use a template for the rendering If the user configures a default `template_id` for the `mail.compose.message`, this template was used by the mass mailing to render the email, and, among others, it therefore used the `email_to` of this email template, to render the recipients, and it was configured empty or something else than `object.id`, it did not used the `active_ids` passed in the context to the `mail.compose.message` `create` call to compute the correct recipients To reproduce: - In developer mode (?debug) - Open the full mail compose message e.g. in app sales, open a so, hit new message, and hit the button to open the full message composer - Set the template to the quotation template is not there already - In the debug menu of the dialog, View > Set defaults, - Click the radio button to all users, and the default to Use template = ... - Then, try to send a mass mailing. It will fail because it cannot compute the `email_to` values correctly because the `email_to` of the quotation template is empty. opw-1840287 --- addons/mass_mailing/models/mass_mailing.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py index 154acd47bd8..340d4c8ccb8 100644 --- a/addons/mass_mailing/models/mass_mailing.py +++ b/addons/mass_mailing/models/mass_mailing.py @@ -785,6 +785,7 @@ class MassMailing(osv.Model): 'mass_mailing_id': mailing.id, 'mailing_list_ids': [(4, l.id) for l in mailing.contact_list_ids], 'no_auto_thread': mailing.reply_to_mode != 'thread', + 'template_id': None, } if mailing.reply_to_mode == 'email': composer_values['reply_to'] = mailing.reply_to From 2b771757e2d02d1300400f743e9cae41dc7cf40f Mon Sep 17 00:00:00 2001 From: Toufik Benjaa Date: Mon, 14 May 2018 16:59:36 +0200 Subject: [PATCH 03/51] [FIX] crm: Access rights issues in contact merging - When merging partners with fields restricted to certain groups which the user doesn't belong, an access error is raised. To avoid this, we only merge fields that are accessible by the user. We do so by using the method fields_get() that only returns the fields accessible by the current user. --- addons/crm/wizard/base_partner_merge.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/crm/wizard/base_partner_merge.py b/addons/crm/wizard/base_partner_merge.py index 7af4b7487ed..f43b57fc5f7 100644 --- a/addons/crm/wizard/base_partner_merge.py +++ b/addons/crm/wizard/base_partner_merge.py @@ -223,7 +223,7 @@ class MergePartnerAutomatic(models.TransientModel): """ _logger.debug('_update_values for dst_partner: %s for src_partners: %r', dst_partner.id, src_partners.ids) - model_fields = dst_partner._fields + model_fields = dst_partner.fields_get().keys() def write_serializer(item): if isinstance(item, models.BaseModel): @@ -232,7 +232,8 @@ class MergePartnerAutomatic(models.TransientModel): return item # get all fields that are not computed or x2many values = dict() - for column, field in model_fields.items(): + for column in model_fields: + field = dst_partner._fields[column] if field.type not in ('many2many', 'one2many') and field.compute is None: for item in itertools.chain(src_partners, [dst_partner]): if item[column]: From 045086839184d89e6aa11b4938d5f685ce607513 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 14 May 2018 19:54:50 +0200 Subject: [PATCH 04/51] [FIX] website: correct GeoIP Legacy compatibility Attribute is different for country and continent objects. --- addons/website/geoipresolver.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/website/geoipresolver.py b/addons/website/geoipresolver.py index e95b9318eb2..24bbe723d6d 100644 --- a/addons/website/geoipresolver.py +++ b/addons/website/geoipresolver.py @@ -50,10 +50,10 @@ class GeoIPResolver(object): # Compatibility with Legacy database. # Some ips cannot be located to a specific country. Legacy DB used to locate them in # continent instead of country. Do the same to not change behavior of existing code. - country = r.country if r.country.geoname_id else r.continent + country, attr = (r.country, 'iso_code') if r.country.geoname_id else (r.continent, 'code') return { 'city': r.city.name, - 'country_code': country.iso_code, + 'country_code': getattr(country, attr), 'country_name': country.name, 'region': r.subdivisions[0].iso_code if r.subdivisions else None, 'time_zone': r.location.time_zone, From 429bcd9464928c21b0bdc3e99280cd50bf0c36b8 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 9 May 2018 14:10:51 +0200 Subject: [PATCH 05/51] [FIX] payment_sips: special characters The field `transactionReference` of Sips must contain only alphanumerical characters. Previous commit 31dc6b888eeb2d787f5675 solved the special case of several attempts to pay, but a much simpler case may appear in v11. Paying an invoice is likely to fail since the reference contains by default `/`. In the previous commit, we could simply modify the common `payment` module code. In this specific case, however, we only change the reference if the acquirer is Sips. opw-1841483 --- addons/account_payment/models/payment.py | 2 +- addons/payment/models/payment_acquirer.py | 4 ++++ addons/payment_sips/models/payment.py | 11 +++++++++++ addons/sale_payment/models/payment.py | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/addons/account_payment/models/payment.py b/addons/account_payment/models/payment.py index 389cfa206e1..cfc90258289 100644 --- a/addons/account_payment/models/payment.py +++ b/addons/account_payment/models/payment.py @@ -159,7 +159,7 @@ class PaymentTransaction(models.Model): 'currency_id': invoice.currency_id.id, 'partner_id': invoice.partner_id.id, 'partner_country_id': invoice.partner_id.country_id.id, - 'reference': self.get_next_reference(invoice.number), + 'reference': self._get_next_reference(invoice.number, acquirer=acquirer), 'account_invoice_id': invoice.id, } if add_tx_values: diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py index efd6573c778..98992c2a679 100644 --- a/addons/payment/models/payment_acquirer.py +++ b/addons/payment/models/payment_acquirer.py @@ -685,6 +685,10 @@ class PaymentTransaction(models.Model): @api.model def get_next_reference(self, reference): + return self._get_next_reference(reference) + + @api.model + def _get_next_reference(self, reference, acquirer=None): ref_suffix = 1 init_ref = reference while self.env['payment.transaction'].sudo().search_count([('reference', '=', reference)]): diff --git a/addons/payment_sips/models/payment.py b/addons/payment_sips/models/payment.py index 46464b7d60c..60e4d9f3153 100644 --- a/addons/payment_sips/models/payment.py +++ b/addons/payment_sips/models/payment.py @@ -4,6 +4,7 @@ import json import logging +import re from hashlib import sha256 from werkzeug import urls @@ -111,6 +112,16 @@ class AcquirerSips(models.Model): return self.environment == 'prod' and self.sips_prod_url or self.sips_test_url +class PaymentTransactionSips(models.Model): + _inherit = 'payment.transaction' + + @api.model + def _get_next_reference(self, reference, acquirer=None): + if acquirer and acquirer.provider == 'sips': + reference = re.sub(r'[^0-9a-zA-Z]+', 'x' , reference) + return super(PaymentTransactionSips, self)._get_next_reference(reference, acquirer=acquirer) + + class TxSips(models.Model): _inherit = 'payment.transaction' diff --git a/addons/sale_payment/models/payment.py b/addons/sale_payment/models/payment.py index 831af37550f..f710b63630f 100644 --- a/addons/sale_payment/models/payment.py +++ b/addons/sale_payment/models/payment.py @@ -182,7 +182,7 @@ class PaymentTransaction(models.Model): 'currency_id': order.pricelist_id.currency_id.id, 'partner_id': order.partner_id.id, 'partner_country_id': order.partner_id.country_id.id, - 'reference': self.get_next_reference(order.name), + 'reference': self._get_next_reference(order.name, acquirer=acquirer), 'sale_order_id': order.id, } if add_tx_values: From 1dbeda01578734859220bcb2079a5083789ff135 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Mon, 14 May 2018 12:13:06 +0200 Subject: [PATCH 06/51] [FIX] project: sub-tasks - Activate sub-tasks in projects - Enter a project's tasks, click on the stat button 'Sub-tasks' - Reload the page (F5) A traceback occurs since `project_id` is undefined. The fields `project_id` and `partner_id` are only defined in the context of the stat button. opw-1844334 --- addons/project/models/project.py | 14 ++++++++++++++ addons/project/views/project_views.xml | 12 +----------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/addons/project/models/project.py b/addons/project/models/project.py index d25de3f6ab4..b00b160ae2b 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -877,6 +877,20 @@ class Task(models.Model): 'type': 'ir.actions.act_window' } + def action_subtask(self): + action = self.env.ref('project.project_task_action_sub_task').read()[0] + ctx = self.env.context.copy() + ctx.update({ + 'default_parent_id' : self.id, + 'default_project_id' : self.env.context.get('project_id', self.subtask_project_id.id), + 'default_name' : self.env.context.get('name', self.name) + ':', + 'default_partner_id' : self.env.context.get('partner_id', self.partner_id.id), + 'search_default_project_id': self.env.context.get('project_id', self.subtask_project_id.id), + }) + action['context'] = ctx + action['domain'] = [('id', 'child_of', self.id), ('id', '!=', self.id)] + return action + class AccountAnalyticAccount(models.Model): _inherit = 'account.analytic.account' diff --git a/addons/project/views/project_views.xml b/addons/project/views/project_views.xml index 9ebcef69138..bf1e63a5599 100644 --- a/addons/project/views/project_views.xml +++ b/addons/project/views/project_views.xml @@ -84,16 +84,6 @@ Sub-tasks project.task kanban,tree,form,calendar,pivot,graph - [('id', 'child_of', active_id), ('id', '!=', active_id)] - - { - 'default_parent_id' : active_id, - 'default_project_id' : project_id, - 'default_name' : name + ':', - 'default_partner_id' : partner_id, - 'search_default_project_id': [project_id], - } - @@ -403,7 +393,7 @@
+
+
From 6558d52e9b5dd774145d2df3822dcea8a35f7872 Mon Sep 17 00:00:00 2001 From: qdp-odoo Date: Tue, 15 May 2018 16:30:05 +0200 Subject: [PATCH 17/51] [FIX] account: adjustment wizard usability This commits removes a disambiguation on the choices of the 'Adjustment Type' selection as 'in your favor' could be achieved by debitting the 'Collected Tax' account or creditting the 'Paid Tax' accounts (respectively for 'in favor of the Estate'). The choices now refers directly to the journal item where the tax is gonna be copied Related to https://github.com/odoo/odoo/commit/c58ef14a01f600d75391f2a9c38bb2b30e0e2528 Related to OPW 1826242 --- addons/account/wizard/wizard_tax_adjustments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/account/wizard/wizard_tax_adjustments.py b/addons/account/wizard/wizard_tax_adjustments.py index 22d2235ef04..05f893722a0 100644 --- a/addons/account/wizard/wizard_tax_adjustments.py +++ b/addons/account/wizard/wizard_tax_adjustments.py @@ -18,7 +18,7 @@ class TaxAdjustments(models.TransientModel): debit_account_id = fields.Many2one('account.account', string='Debit account', required=True, domain=[('deprecated', '=', False)]) credit_account_id = fields.Many2one('account.account', string='Credit account', required=True, domain=[('deprecated', '=', False)]) amount = fields.Monetary(currency_field='company_currency_id', required=True) - adjustment_type = fields.Selection([('debit', 'Adjustment in favor of the Estate'), ('credit', 'Adjustment in your favor')], string="Adjustment Type", store=False, required=True) + adjustment_type = fields.Selection([('debit', 'Applied on debit journal item'), ('credit', 'Applied on credit journal item')], string="Adjustment Type", store=False, required=True) company_currency_id = fields.Many2one('res.currency', readonly=True, default=lambda self: self.env.user.company_id.currency_id) tax_id = fields.Many2one('account.tax', string='Adjustment Tax', ondelete='restrict', domain=[('type_tax_use', '=', 'none'), ('tax_adjustment', '=', True)], required=True) From 84f0b4d9345a6c891e7cea63a55716f325b22e1e Mon Sep 17 00:00:00 2001 From: Toufik Benjaa Date: Tue, 15 May 2018 15:43:07 +0200 Subject: [PATCH 18/51] [FIX] mail: Avoid crashing when removing link from chatter - The code to remove mentionned users on the chatter isn't robust enough. It crashes when trying to remove a link added from a copy/paste as if it was a mention. Mentions have an id defined on their "a" html node, linked copied and pasted don't. Which crashes the javascript code because it is trying to use the id. This fix, make sure to delete the node without using its id (we already have the node) and make sure to remove it only if it starts with a '@' (meaning it is a mention). --- addons/mail/static/src/js/composer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js index 8354fe610b5..45958a620f6 100644 --- a/addons/mail/static/src/js/composer.js +++ b/addons/mail/static/src/js/composer.js @@ -745,8 +745,9 @@ var BasicComposer = Widget.extend({ }, // remove mention when user try to edit or remove it. _removeMention: function (event) { - if (window.getSelection().anchorNode.parentNode.tagName === 'A') { - document.getElementById(window.getSelection().anchorNode.parentNode.id).remove(); + var anchorNode = window.getSelection().anchorNode; + if (anchorNode.textContent.startsWith('@') && anchorNode.parentNode.tagName === 'A') { + anchorNode.parentNode.remove(); } }, From 35c2a74480cf06849f561abcc27c5c9021b28151 Mon Sep 17 00:00:00 2001 From: Goffin Simon Date: Tue, 15 May 2018 13:28:32 +0200 Subject: [PATCH 19/51] [FIX] delivery: Delivery method name not translated When adding a SO line with a delivery method (e.g. The Post) for a customer with a different language that the one set on the current language, the description of the SO line was not translated. Inspired from function 'product_id_change' in model 'sale.order.line' opw:1843934 --- addons/delivery/models/sale_order.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index 184374020af..cea84ee491c 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -89,9 +89,10 @@ class SaleOrder(models.Model): taxes_ids = self.fiscal_position_id.map_tax(taxes, carrier.product_id, self.partner_id).ids # Create the sales order line + carrier_name = carrier.product_id.with_context(lang=self.partner_id.lang).name_get()[0][1] values = { 'order_id': self.id, - 'name': carrier.name, + 'name': carrier_name, 'product_uom_qty': 1, 'product_uom': carrier.product_id.uom_id.id, 'product_id': carrier.product_id.id, From e5fb990db1d6216a156617e387d85d13c1a0b93c Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Tue, 15 May 2018 17:07:44 +0200 Subject: [PATCH 20/51] [FIX] project: prevent to create recursive hierarchy of tasks Until this revision, this was possible to set as parent task the current task. From then, it was impossible to compute the field `subtask_count` because of an infinite loop. This resulted to the inability to open the task form, which contains this field. opw-1847982 --- addons/project/i18n/project.pot | 6 ++++++ addons/project/models/project.py | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/addons/project/i18n/project.pot b/addons/project/i18n/project.pot index 101c95cdd82..79618e19e4a 100644 --- a/addons/project/i18n/project.pot +++ b/addons/project/i18n/project.pot @@ -1573,6 +1573,12 @@ msgstr "" msgid "Ending Date" msgstr "" +#. module: project +#: code:addons/project/models/project.py:556 +#, python-format +msgid "Error! You cannot create recursive hierarchy of task(s)." +msgstr "" + #. module: project #: sql_constraint:project.project:0 msgid "Error! project start-date must be lower than project end-date." diff --git a/addons/project/models/project.py b/addons/project/models/project.py index b00b160ae2b..2798faaf12a 100644 --- a/addons/project/models/project.py +++ b/addons/project/models/project.py @@ -4,7 +4,7 @@ from lxml import etree from odoo import api, fields, models, tools, SUPERUSER_ID, _ -from odoo.exceptions import UserError, AccessError +from odoo.exceptions import UserError, AccessError, ValidationError from odoo.tools.safe_eval import safe_eval @@ -549,6 +549,12 @@ class Task(models.Model): for task in self: task.subtask_count = self.search_count([('id', 'child_of', task.id), ('id', '!=', task.id)]) + @api.constrains('parent_id') + def _check_parent_id(self): + for task in self: + if not task._check_recursion(): + raise ValidationError(_('Error! You cannot create recursive hierarchy of task(s).')) + @api.constrains('parent_id') def _check_subtask_project(self): for task in self: From 04ce6e84c2c1fa5f33b3398ad3957d1b65d92456 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Fri, 11 May 2018 15:14:18 +0200 Subject: [PATCH 21/51] [IMP] website_event: show physical event before online if country specific. If a country is specified, we show also all our online events to promote it since they can be followed from anywhere. But we show in priority the physical event. opw-1845012 --- addons/event/models/event.py | 5 +++++ addons/website_event/controllers/main.py | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/event/models/event.py b/addons/event/models/event.py index 8551c6ec389..faa4466b7c7 100644 --- a/addons/event/models/event.py +++ b/addons/event/models/event.py @@ -220,6 +220,11 @@ class EventEvent(models.Model): else: self.date_end_located = False + @api.onchange('is_online') + def _onchange_is_online(self): + if self.is_online: + self.address_id = False + @api.onchange('event_type_id') def _onchange_type(self): if self.event_type_id: diff --git a/addons/website_event/controllers/main.py b/addons/website_event/controllers/main.py index b9c08b8232e..38bd5b0ce7f 100644 --- a/addons/website_event/controllers/main.py +++ b/addons/website_event/controllers/main.py @@ -62,7 +62,6 @@ class WebsiteEventController(http.Controller): ] # search domains - # TDE note: WTF ??? current_date = None current_type = None current_country = None @@ -117,9 +116,12 @@ class WebsiteEventController(http.Controller): step=step, scope=5) - order = 'website_published desc, date_begin' + order = 'date_begin' if searches.get('date', 'all') == 'old': - order = 'website_published desc, date_begin desc' + order = 'date_begin desc' + if searches["country"] != 'all': # if we are looking for a specific country + order = 'is_online, ' + order # show physical events first + order = 'website_published desc, ' + order events = Event.search(dom_without("none"), limit=step, offset=pager['offset'], order=order) values = { From 05ef2f24e08a06d586f9dc390878ecd3c069042f Mon Sep 17 00:00:00 2001 From: Toufik Benjaa Date: Tue, 15 May 2018 17:53:22 +0200 Subject: [PATCH 22/51] [FIX] mail: Missing parenthesis to call "remove" on chatter spinner - The code to remove the loading spinner from the chatter was missing parenthesis to actually do the function call. --- addons/mail/static/src/js/chatter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index dfc041325d9..7d9f324042d 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -247,7 +247,7 @@ var Chatter = Widget.extend({ }).always(function () { // disable widgets in create mode, otherwise enable self.isCreateMode ? self._disableChatter() : self._enableChatter(); - $spinner.remove; + $spinner.remove(); }); }, /** From fb17edd0b0d5c956f6991feabfa704566fa0a11b Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 15 May 2018 19:19:51 +0200 Subject: [PATCH 23/51] [FIX] event_sale: update registrations as sudo. Consequence of 19878d011f8abdc737b7b702c4c79632670d4b78 --- addons/event_sale/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index 7a2dcd8a745..6902d8e4743 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -41,7 +41,7 @@ class SaleOrderLine(models.Model): order line has a product_uom_qty attribute that will be the number of registrations linked to this line. This method update existing registrations and create new one for missing one. """ - Registration = self.env['event.registration'] + Registration = self.env['event.registration'].sudo() registrations = Registration.search([('sale_order_line_id', 'in', self.ids), ('state', '!=', 'cancel')]) for so_line in self.filtered('event_id'): existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id) From 25548eb7e963632668438f939401403431201904 Mon Sep 17 00:00:00 2001 From: len-odoo Date: Fri, 11 May 2018 16:59:10 +0200 Subject: [PATCH 24/51] [FIX] web: sort relational fields by their names When sorting records according to a many2one field in a list view embedded in a form view, the js would sort according to their ids, in a seemingly arbitrary order. Thus sorting records according to a field with values in ("a", "b", "c") could be sorted as "a", "a", "c", "b" instead of "a", "a", "b", "c". We make the comparison on the name of the field instead. opw 1838860 --- .../static/src/js/views/basic/basic_model.js | 14 ++++++- .../tests/fields/relational_fields_tests.js | 37 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index 9e8afe1629f..d0eed4dc524 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -4100,10 +4100,20 @@ var BasicModel = AbstractModel.extend({ var r2 = self.localData[record2ID]; var data1 = _.extend({}, r1.data, r1._changes); var data2 = _.extend({}, r2.data, r2._changes); - if (data1[order.name] < data2[order.name]) { + + // Default value to sort against: the value of the field + var orderData1 = data1[order.name]; + var orderData2 = data2[order.name]; + + // If the field is a relation, sort on the display_name of those records + if (list.fields[order.name].type === 'many2one') { + orderData1 = orderData1 ? self.localData[orderData1].data.display_name : ""; + orderData2 = orderData2 ? self.localData[orderData2].data.display_name : ""; + } + if (orderData1 < orderData2) { return order.asc ? -1 : 1; } - if (data1[order.name] > data2[order.name]) { + if (orderData1 > orderData2) { return order.asc ? 1 : -1; } return compareRecords(record1ID, record2ID, level + 1); diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index db91d9d3ae5..9d7362972de 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2271,6 +2271,43 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('x2many list sorted by many2one', function (assert) { + assert.expect(3); + + this.data.partner.records[0].p = [1, 2, 4]; + this.data.partner.fields.trululu.sortable = true; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + }); + + assert.strictEqual(form.$('.o_data_row .o_list_number').text(), '124', + "should have correct order initially"); + + form.$('.o_list_view thead th:nth(1)').click(); + + assert.strictEqual(form.$('.o_data_row .o_list_number').text(), '412', + "should have correct order (ASC)"); + + form.$('.o_list_view thead th:nth(1)').click(); + + assert.strictEqual(form.$('.o_data_row .o_list_number').text(), '214', + "should have correct order (DESC)"); + + form.destroy(); + }); + QUnit.test('many2many list add *many* records, remove, re-add', function (assert) { assert.expect(5); From 47cc4fbbab6e532b056fee26542283bd65978ac7 Mon Sep 17 00:00:00 2001 From: len-odoo Date: Tue, 15 May 2018 10:58:59 +0200 Subject: [PATCH 25/51] [FIX] auth_signup: add missing dependency on the computation of the signup validity The field signup_valid is a non stored computed field based on signup_token. The cache is filled with prefetched values, so in a loop the field is read from the cache and not recomputed due to the missing dependency. opw 1843442 --- addons/auth_signup/models/res_partner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/auth_signup/models/res_partner.py b/addons/auth_signup/models/res_partner.py index d2bad560398..cb253555a45 100644 --- a/addons/auth_signup/models/res_partner.py +++ b/addons/auth_signup/models/res_partner.py @@ -33,6 +33,7 @@ class ResPartner(models.Model): signup_url = fields.Char(compute='_compute_signup_url', string='Signup URL') @api.multi + @api.depends('signup_token', 'signup_expiration') def _compute_signup_valid(self): dt = now() for partner in self: From 9db6dfa25df26b340176b43d4c7df9d004b27afb Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 15 May 2018 19:19:51 +0200 Subject: [PATCH 26/51] [FIX] event_sale: update registrations as sudo. Consequence of 19878d011f8abdc737b7b702c4c79632670d4b78 Backport of fb17edd0b0d5c956f6991feabfa704566fa0a11b --- addons/event_sale/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index 8c2b8bc0c3f..30c5e40d122 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -56,7 +56,7 @@ class sale_order_line(osv.osv): order line has a product_uom_qty attribute that will be the number of registrations linked to this line. This method update existing registrations and create new one for missing one. """ - Registration = self.env['event.registration'] + Registration = self.env['event.registration'].sudo() registrations = Registration.search([('sale_order_line_id', 'in', self.ids)]) for so_line in [l for l in self if l.event_id]: existing_registrations = registrations.filtered(lambda self: self.sale_order_line_id.id == so_line.id) From 6fce298d7013379c4383e8368c40ee06d6146423 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Tue, 15 May 2018 12:14:02 +0200 Subject: [PATCH 27/51] [FIX] account: tax computation at reconciliation - Create a tax included of 7.7% - Set the company rounding to 'Round Globally' - Create a bank statement of 10.70, reconcile - Add a manual line with the 7.7% tax An extra line of 0.01 remains. The remaining amount after subtracting the tax is `0.00499...`, which is rounded to `0.005` by `Math.round(total*1000)/1000`, and finally displayed as `0.01`. The 'Round Globally' setting makes sense for objects containing multiple lines, such as SO, PO or invoice. In the case of a reconciliation, we can switch to the 'Round per line' config. opw-1837986 --- .../account/static/src/js/reconciliation/reconciliation_model.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js index 796531e9a62..ab10c740b63 100644 --- a/addons/account/static/src/js/reconciliation/reconciliation_model.js +++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js @@ -785,6 +785,7 @@ var StatementModel = BasicModel.extend({ model: 'account.tax', method: 'json_friendly_compute_all', args: args, + context: $.extend(self.context || {}, {'round': true}), }) .then(function (result) { _.each(result.taxes, function(tax){ From b8f5f17aed48876bfeab2b321e15f719983ea3b5 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 15 May 2018 17:14:51 +0200 Subject: [PATCH 28/51] [FIX] event: don't block scheduler at first exception Before this commit, when a scheduler fail for one event (eg: error in send_mail), the cron stop and don't continue to process all others event's scheduler. Now we try to warn (~ randomly once by hour) the responsible/organizer/write_uid that an error occurs with this scheduler, and we continue to process the others. opw-1840497 closes #24741 --- addons/event/models/event_mail.py | 50 +++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/addons/event/models/event_mail.py b/addons/event/models/event_mail.py index 1013f5a083b..680e1d4ba8a 100644 --- a/addons/event/models/event_mail.py +++ b/addons/event/models/event_mail.py @@ -4,7 +4,12 @@ from datetime import datetime from dateutil.relativedelta import relativedelta from odoo import api, fields, models, tools +from odoo.tools import exception_to_unicode +from odoo.tools.translate import _ +import random +import logging +_logger = logging.getLogger(__name__) _INTERVALS = { 'hours': lambda interval: relativedelta(hours=interval), @@ -114,13 +119,52 @@ class EventMailScheduler(models.Model): self.write({'mail_sent': True}) return True + @api.model + def _warn_template_error(self, scheduler, exception): + # We warn ~ once by hour ~ instead of every 10 min if the interval unit is more than 'hours'. + if random.random() < 0.1666 or scheduler.interval_unit in ('now', 'hours'): + ex_s = exception_to_unicode(exception) + try: + event, template = scheduler.event_id, scheduler.template_id + emails = list(set([event.organizer_id.email, event.user_id.email, template.write_uid.email])) + subject = _("WARNING: Event Scheduler Error for event: %s" % event.name) + body = _("""Event Scheduler for: + - Event: %s (%s) + - Scheduled: %s + - Template: %s (%s) + + Failed with error: + - %s + + You receive this email because you are: + - the organizer of the event, + - or the responsible of the event, + - or the last writer of the template.""" + % (event.name, event.id, scheduler.scheduled_date, template.name, template.id, ex_s)) + email = self.env['ir.mail_server'].build_email( + email_from=self.env.user.email, + email_to=emails, + subject=subject, body=body, + ) + self.env['ir.mail_server'].send_email(email) + except Exception as e: + _logger.error("Exception while sending traceback by email: %s.\n Original Traceback:\n%s", e, exception) + pass + @api.model def run(self, autocommit=False): schedulers = self.search([('done', '=', False), ('scheduled_date', '<=', datetime.strftime(fields.datetime.now(), tools.DEFAULT_SERVER_DATETIME_FORMAT))]) for scheduler in schedulers: - scheduler.execute() - if autocommit: - self.env.cr.commit() + try: + with self.env.cr.savepoint(): + scheduler.execute() + except Exception as e: + _logger.exception(e) + self.invalidate_cache() + self._warn_template_error(scheduler, e) + else: + if autocommit: + self.env.cr.commit() return True From cdabb9d74c93bca30a6a129bb9c6774e4c0212e8 Mon Sep 17 00:00:00 2001 From: Olivier Dony Date: Wed, 16 May 2018 12:17:14 +0200 Subject: [PATCH 29/51] [FIX] auth_signup: remove password from welcome message Revision 054c68689b58f554e9433938644f2960720e08ef added by mistake the password of the new user in the welcome message that is sent to users who signed up with an invitation token. There is no need for this, the user has just chosen their password, and we should not send them a copy which could be compromised on the way to their inbox or later in their inbox. It may also give users the impression that their passwords is stored in cleartext in the database, even when that is not the case. This patch minimalizes changes to the template and its translations. For existing databases where the code is updated without re-syncing the template, the password will simply be missing in the message (until a resync of auth_signup module is done) --- addons/auth_signup/controllers/main.py | 1 - addons/auth_signup/data/auth_signup_data.xml | 1 - addons/auth_signup/i18n/af.po | 1 - addons/auth_signup/i18n/am.po | 1 - addons/auth_signup/i18n/ar.po | 1 - addons/auth_signup/i18n/auth_signup.pot | 1 - addons/auth_signup/i18n/bg.po | 1 - addons/auth_signup/i18n/bs.po | 1 - addons/auth_signup/i18n/ca.po | 1 - addons/auth_signup/i18n/cs.po | 1 - addons/auth_signup/i18n/da.po | 1 - addons/auth_signup/i18n/de.po | 2 -- addons/auth_signup/i18n/el.po | 2 -- addons/auth_signup/i18n/en_GB.po | 1 - addons/auth_signup/i18n/es.po | 2 -- addons/auth_signup/i18n/es_AR.po | 1 - addons/auth_signup/i18n/es_BO.po | 1 - addons/auth_signup/i18n/es_CL.po | 1 - addons/auth_signup/i18n/es_CO.po | 1 - addons/auth_signup/i18n/es_CR.po | 1 - addons/auth_signup/i18n/es_DO.po | 1 - addons/auth_signup/i18n/es_EC.po | 1 - addons/auth_signup/i18n/es_PA.po | 1 - addons/auth_signup/i18n/es_PE.po | 1 - addons/auth_signup/i18n/es_PY.po | 1 - addons/auth_signup/i18n/es_VE.po | 1 - addons/auth_signup/i18n/et.po | 1 - addons/auth_signup/i18n/eu.po | 1 - addons/auth_signup/i18n/fa.po | 1 - addons/auth_signup/i18n/fi.po | 1 - addons/auth_signup/i18n/fo.po | 1 - addons/auth_signup/i18n/fr.po | 2 -- addons/auth_signup/i18n/fr_CA.po | 1 - addons/auth_signup/i18n/gl.po | 1 - addons/auth_signup/i18n/gu.po | 1 - addons/auth_signup/i18n/he.po | 1 - addons/auth_signup/i18n/hr.po | 1 - addons/auth_signup/i18n/hu.po | 1 - addons/auth_signup/i18n/id.po | 1 - addons/auth_signup/i18n/it.po | 1 - addons/auth_signup/i18n/ja.po | 1 - addons/auth_signup/i18n/ka.po | 1 - addons/auth_signup/i18n/kab.po | 1 - addons/auth_signup/i18n/ko.po | 1 - addons/auth_signup/i18n/lo.po | 1 - addons/auth_signup/i18n/lt.po | 2 -- addons/auth_signup/i18n/lv.po | 1 - addons/auth_signup/i18n/mk.po | 1 - addons/auth_signup/i18n/mn.po | 1 - addons/auth_signup/i18n/nb.po | 1 - addons/auth_signup/i18n/ne.po | 1 - addons/auth_signup/i18n/nl.po | 2 -- addons/auth_signup/i18n/nl_BE.po | 1 - addons/auth_signup/i18n/pl.po | 1 - addons/auth_signup/i18n/pt.po | 1 - addons/auth_signup/i18n/pt_BR.po | 2 -- addons/auth_signup/i18n/ro.po | 1 - addons/auth_signup/i18n/ru.po | 1 - addons/auth_signup/i18n/sk.po | 1 - addons/auth_signup/i18n/sl.po | 1 - addons/auth_signup/i18n/sq.po | 1 - addons/auth_signup/i18n/sr.po | 1 - addons/auth_signup/i18n/sr@latin.po | 1 - addons/auth_signup/i18n/sv.po | 1 - addons/auth_signup/i18n/th.po | 1 - addons/auth_signup/i18n/tr.po | 1 - addons/auth_signup/i18n/uk.po | 1 - addons/auth_signup/i18n/vi.po | 1 - addons/auth_signup/i18n/zh_CN.po | 2 -- addons/auth_signup/i18n/zh_TW.po | 1 - 70 files changed, 78 deletions(-) diff --git a/addons/auth_signup/controllers/main.py b/addons/auth_signup/controllers/main.py index 1d1b0476337..bce24f07885 100644 --- a/addons/auth_signup/controllers/main.py +++ b/addons/auth_signup/controllers/main.py @@ -42,7 +42,6 @@ class AuthSignupHome(Home): template.sudo().with_context( lang=user_sudo.lang, auth_login=werkzeug.url_encode({'auth_login': user_sudo.email}), - password=request.params.get('password') ).send_mail(user_sudo.id, force_send=True) return super(AuthSignupHome, self).web_login(*args, **kw) except UserError as e: diff --git a/addons/auth_signup/data/auth_signup_data.xml b/addons/auth_signup/data/auth_signup_data.xml index b9f88893d2a..b3364a51658 100644 --- a/addons/auth_signup/data/auth_signup_data.xml +++ b/addons/auth_signup/data/auth_signup_data.xml @@ -116,7 +116,6 @@

Your login: ${object.email}
- Your password: ${ctx['password']}

To gain access to your account, you can use the following link: diff --git a/addons/auth_signup/i18n/af.po b/addons/auth_signup/i18n/af.po index e95f0c01e3a..8fe284f2eb6 100644 --- a/addons/auth_signup/i18n/af.po +++ b/addons/auth_signup/i18n/af.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/am.po b/addons/auth_signup/i18n/am.po index 884e96a66f0..7ed08db42cb 100644 --- a/addons/auth_signup/i18n/am.po +++ b/addons/auth_signup/i18n/am.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ar.po b/addons/auth_signup/i18n/ar.po index aec6d4ea4b9..b379535575d 100644 --- a/addons/auth_signup/i18n/ar.po +++ b/addons/auth_signup/i18n/ar.po @@ -115,7 +115,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/auth_signup.pot b/addons/auth_signup/i18n/auth_signup.pot index d14676bed0b..2a55058943a 100644 --- a/addons/auth_signup/i18n/auth_signup.pot +++ b/addons/auth_signup/i18n/auth_signup.pot @@ -102,7 +102,6 @@ msgid "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/bg.po b/addons/auth_signup/i18n/bg.po index 42b73456d16..7ea2482acda 100644 --- a/addons/auth_signup/i18n/bg.po +++ b/addons/auth_signup/i18n/bg.po @@ -112,7 +112,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/bs.po b/addons/auth_signup/i18n/bs.po index e30567817fb..72953b3e2fb 100644 --- a/addons/auth_signup/i18n/bs.po +++ b/addons/auth_signup/i18n/bs.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ca.po b/addons/auth_signup/i18n/ca.po index 4154a0f8705..0d58beeaac2 100644 --- a/addons/auth_signup/i18n/ca.po +++ b/addons/auth_signup/i18n/ca.po @@ -134,7 +134,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/cs.po b/addons/auth_signup/i18n/cs.po index ee70411fb3a..af80655808a 100644 --- a/addons/auth_signup/i18n/cs.po +++ b/addons/auth_signup/i18n/cs.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/da.po b/addons/auth_signup/i18n/da.po index 2a50f034c72..f64def7236e 100644 --- a/addons/auth_signup/i18n/da.po +++ b/addons/auth_signup/i18n/da.po @@ -167,7 +167,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/de.po b/addons/auth_signup/i18n/de.po index 39935643c34..84fe3bdd16c 100644 --- a/addons/auth_signup/i18n/de.po +++ b/addons/auth_signup/i18n/de.po @@ -176,7 +176,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -210,7 +209,6 @@ msgstr "" "

\n" " Ihre Anmeldedaten: ${object.email}\n" "
\n" -" Ihr Passwort: ${ctx['password']}\n" "

\n" "

\n" " Um Zugriff auf Ihr Konto zu erlangen, können Sie den folgenden Link verwenden:\n" diff --git a/addons/auth_signup/i18n/el.po b/addons/auth_signup/i18n/el.po index 527e38d061c..bdd6ddbfdeb 100644 --- a/addons/auth_signup/i18n/el.po +++ b/addons/auth_signup/i18n/el.po @@ -165,7 +165,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -199,7 +198,6 @@ msgstr "" "

\n" " Email/Όνομα χρήστη: ${object.email}\n" "
\n" -" Κωδικός Πρόσβασης: ${ctx['password']}\n" "

\n" "

\n" " Για να αποκτήσετε πρόσβαση στο λογαριασμό σας, ακολουθήστε τον παρακάτω σύνδεσμο:\n" diff --git a/addons/auth_signup/i18n/en_GB.po b/addons/auth_signup/i18n/en_GB.po index c533eb0e2c3..e9d962451fc 100644 --- a/addons/auth_signup/i18n/en_GB.po +++ b/addons/auth_signup/i18n/en_GB.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es.po b/addons/auth_signup/i18n/es.po index 32c650d770f..4349fcd5ca4 100644 --- a/addons/auth_signup/i18n/es.po +++ b/addons/auth_signup/i18n/es.po @@ -174,7 +174,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -208,7 +207,6 @@ msgstr "" "

\n" " Usuario: ${object.email}\n" "
\n" -" Contraseña: ${ctx['password']}\n" "

\n" "

\n" " Puede acceder a su cuenta desde el siguiente enlace:\n" diff --git a/addons/auth_signup/i18n/es_AR.po b/addons/auth_signup/i18n/es_AR.po index 8d8866cef06..64e393f129a 100644 --- a/addons/auth_signup/i18n/es_AR.po +++ b/addons/auth_signup/i18n/es_AR.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_BO.po b/addons/auth_signup/i18n/es_BO.po index bfd8e1e489e..47b5859f164 100644 --- a/addons/auth_signup/i18n/es_BO.po +++ b/addons/auth_signup/i18n/es_BO.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_CL.po b/addons/auth_signup/i18n/es_CL.po index a67181ae4d1..ea610d886fe 100644 --- a/addons/auth_signup/i18n/es_CL.po +++ b/addons/auth_signup/i18n/es_CL.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_CO.po b/addons/auth_signup/i18n/es_CO.po index c663d241bab..e8d1451aff7 100644 --- a/addons/auth_signup/i18n/es_CO.po +++ b/addons/auth_signup/i18n/es_CO.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_CR.po b/addons/auth_signup/i18n/es_CR.po index e62e0727939..8f7b7380f02 100644 --- a/addons/auth_signup/i18n/es_CR.po +++ b/addons/auth_signup/i18n/es_CR.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_DO.po b/addons/auth_signup/i18n/es_DO.po index ae7f686a112..eb6d9532822 100644 --- a/addons/auth_signup/i18n/es_DO.po +++ b/addons/auth_signup/i18n/es_DO.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_EC.po b/addons/auth_signup/i18n/es_EC.po index 49115bebd99..9c46530c695 100644 --- a/addons/auth_signup/i18n/es_EC.po +++ b/addons/auth_signup/i18n/es_EC.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_PA.po b/addons/auth_signup/i18n/es_PA.po index b7e4b4a2b79..7300ae412a2 100644 --- a/addons/auth_signup/i18n/es_PA.po +++ b/addons/auth_signup/i18n/es_PA.po @@ -141,7 +141,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_PE.po b/addons/auth_signup/i18n/es_PE.po index 7831cdc8391..8f56db0a42c 100644 --- a/addons/auth_signup/i18n/es_PE.po +++ b/addons/auth_signup/i18n/es_PE.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_PY.po b/addons/auth_signup/i18n/es_PY.po index 32973798220..ee3607f40ee 100644 --- a/addons/auth_signup/i18n/es_PY.po +++ b/addons/auth_signup/i18n/es_PY.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/es_VE.po b/addons/auth_signup/i18n/es_VE.po index f952ba5f792..d36f3817ded 100644 --- a/addons/auth_signup/i18n/es_VE.po +++ b/addons/auth_signup/i18n/es_VE.po @@ -142,7 +142,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/et.po b/addons/auth_signup/i18n/et.po index fb99e25ebda..39c7ab2ae08 100644 --- a/addons/auth_signup/i18n/et.po +++ b/addons/auth_signup/i18n/et.po @@ -113,7 +113,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/eu.po b/addons/auth_signup/i18n/eu.po index 1a0ce5bd509..5d2a38415f7 100644 --- a/addons/auth_signup/i18n/eu.po +++ b/addons/auth_signup/i18n/eu.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/fa.po b/addons/auth_signup/i18n/fa.po index 725e37a6f1c..3aee3d5b30d 100644 --- a/addons/auth_signup/i18n/fa.po +++ b/addons/auth_signup/i18n/fa.po @@ -112,7 +112,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/fi.po b/addons/auth_signup/i18n/fi.po index 45126bd0c40..50afb11038f 100644 --- a/addons/auth_signup/i18n/fi.po +++ b/addons/auth_signup/i18n/fi.po @@ -115,7 +115,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/fo.po b/addons/auth_signup/i18n/fo.po index c2b513c1339..47a4304b83d 100644 --- a/addons/auth_signup/i18n/fo.po +++ b/addons/auth_signup/i18n/fo.po @@ -105,7 +105,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/fr.po b/addons/auth_signup/i18n/fr.po index 1ce976aeb06..9a06c282f7d 100644 --- a/addons/auth_signup/i18n/fr.po +++ b/addons/auth_signup/i18n/fr.po @@ -165,7 +165,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -195,7 +194,6 @@ msgstr "" "

\n" " Votre identifiant : ${object.email}\n" "
\n" -" Votre mot de passe : ${ctx['password']}\n" "

\n" " \n" " Pour accéder à votre compte, vous pouvez utiliser le lien suivant :\n" diff --git a/addons/auth_signup/i18n/fr_CA.po b/addons/auth_signup/i18n/fr_CA.po index 469fd480492..516ffa5ceaa 100644 --- a/addons/auth_signup/i18n/fr_CA.po +++ b/addons/auth_signup/i18n/fr_CA.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/gl.po b/addons/auth_signup/i18n/gl.po index d3ba0b2ac14..7e3f96ee07e 100644 --- a/addons/auth_signup/i18n/gl.po +++ b/addons/auth_signup/i18n/gl.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/gu.po b/addons/auth_signup/i18n/gu.po index e36ed3369b5..9899535ddd7 100644 --- a/addons/auth_signup/i18n/gu.po +++ b/addons/auth_signup/i18n/gu.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/he.po b/addons/auth_signup/i18n/he.po index d4adca058c8..5010a56142a 100644 --- a/addons/auth_signup/i18n/he.po +++ b/addons/auth_signup/i18n/he.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/hr.po b/addons/auth_signup/i18n/hr.po index a51417494c2..e28691d2ab8 100644 --- a/addons/auth_signup/i18n/hr.po +++ b/addons/auth_signup/i18n/hr.po @@ -143,7 +143,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/hu.po b/addons/auth_signup/i18n/hu.po index 24c13f4e57a..cfd59a75b52 100644 --- a/addons/auth_signup/i18n/hu.po +++ b/addons/auth_signup/i18n/hu.po @@ -165,7 +165,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/id.po b/addons/auth_signup/i18n/id.po index 6a1a3ff1898..3105d982405 100644 --- a/addons/auth_signup/i18n/id.po +++ b/addons/auth_signup/i18n/id.po @@ -112,7 +112,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/it.po b/addons/auth_signup/i18n/it.po index 7062f4d1605..5f0dfd9c0c5 100644 --- a/addons/auth_signup/i18n/it.po +++ b/addons/auth_signup/i18n/it.po @@ -110,7 +110,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ja.po b/addons/auth_signup/i18n/ja.po index 14f82c46eda..042c36e57b5 100644 --- a/addons/auth_signup/i18n/ja.po +++ b/addons/auth_signup/i18n/ja.po @@ -165,7 +165,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ka.po b/addons/auth_signup/i18n/ka.po index 42efcdb58f4..25971dd117e 100644 --- a/addons/auth_signup/i18n/ka.po +++ b/addons/auth_signup/i18n/ka.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/kab.po b/addons/auth_signup/i18n/kab.po index 0dec5bea4da..0e670472029 100644 --- a/addons/auth_signup/i18n/kab.po +++ b/addons/auth_signup/i18n/kab.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ko.po b/addons/auth_signup/i18n/ko.po index 809d65abba3..a23730a871c 100644 --- a/addons/auth_signup/i18n/ko.po +++ b/addons/auth_signup/i18n/ko.po @@ -111,7 +111,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/lo.po b/addons/auth_signup/i18n/lo.po index e7bb5b2769a..8ae06fffbc2 100644 --- a/addons/auth_signup/i18n/lo.po +++ b/addons/auth_signup/i18n/lo.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/lt.po b/addons/auth_signup/i18n/lt.po index cb6a84b9b04..77181498483 100644 --- a/addons/auth_signup/i18n/lt.po +++ b/addons/auth_signup/i18n/lt.po @@ -169,7 +169,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -203,7 +202,6 @@ msgstr "" "

\n" " Jūsų prisijungimo vardas: ${object.email}\n" "
\n" -" Jūsų slaptažodis: ${ctx['password']}\n" "

\n" "

\n" " Prisijungimui prie savo paskyros, galite naudoti šią nuorodą:\n" diff --git a/addons/auth_signup/i18n/lv.po b/addons/auth_signup/i18n/lv.po index 837ea92a732..c1ac14aab67 100644 --- a/addons/auth_signup/i18n/lv.po +++ b/addons/auth_signup/i18n/lv.po @@ -110,7 +110,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/mk.po b/addons/auth_signup/i18n/mk.po index 723427f51d1..2bb3dadd211 100644 --- a/addons/auth_signup/i18n/mk.po +++ b/addons/auth_signup/i18n/mk.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/mn.po b/addons/auth_signup/i18n/mn.po index 59d0abc0d33..f4338bae13f 100644 --- a/addons/auth_signup/i18n/mn.po +++ b/addons/auth_signup/i18n/mn.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/nb.po b/addons/auth_signup/i18n/nb.po index 0397adfdfa5..b70c115663f 100644 --- a/addons/auth_signup/i18n/nb.po +++ b/addons/auth_signup/i18n/nb.po @@ -136,7 +136,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ne.po b/addons/auth_signup/i18n/ne.po index bd9db832c01..d94a5813dea 100644 --- a/addons/auth_signup/i18n/ne.po +++ b/addons/auth_signup/i18n/ne.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/nl.po b/addons/auth_signup/i18n/nl.po index 9bc84576d42..9ceea1d4942 100644 --- a/addons/auth_signup/i18n/nl.po +++ b/addons/auth_signup/i18n/nl.po @@ -167,7 +167,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -201,7 +200,6 @@ msgstr "" "

\n" " Uw login: ${object.email}\n" "
\n" -" Uw wachtwoord: ${ctx['password']}\n" "

\n" "

\n" " Om toegang te krijgen tot uw account, kan u de volgende link gebruiken::\n" diff --git a/addons/auth_signup/i18n/nl_BE.po b/addons/auth_signup/i18n/nl_BE.po index 405e872d815..85eb30d00cd 100644 --- a/addons/auth_signup/i18n/nl_BE.po +++ b/addons/auth_signup/i18n/nl_BE.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/pl.po b/addons/auth_signup/i18n/pl.po index 75a82cfdb0b..b10f6f5831a 100644 --- a/addons/auth_signup/i18n/pl.po +++ b/addons/auth_signup/i18n/pl.po @@ -115,7 +115,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/pt.po b/addons/auth_signup/i18n/pt.po index 670cb2cb90a..c6e7d0228b9 100644 --- a/addons/auth_signup/i18n/pt.po +++ b/addons/auth_signup/i18n/pt.po @@ -110,7 +110,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/pt_BR.po b/addons/auth_signup/i18n/pt_BR.po index 2a700ca35a1..6c15d465714 100644 --- a/addons/auth_signup/i18n/pt_BR.po +++ b/addons/auth_signup/i18n/pt_BR.po @@ -167,7 +167,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -201,7 +200,6 @@ msgstr "" "

\n" " Seu login: ${object.email}\n" "
\n" -" Sua senha: ${ctx['password']}\n" "

\n" "

\n" " Para acessar sua conta, você pode acessar o seguinte link:\n" diff --git a/addons/auth_signup/i18n/ro.po b/addons/auth_signup/i18n/ro.po index e9c27054c27..668b86514bc 100644 --- a/addons/auth_signup/i18n/ro.po +++ b/addons/auth_signup/i18n/ro.po @@ -165,7 +165,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/ru.po b/addons/auth_signup/i18n/ru.po index ff71bf2746a..35f6bb4a5e6 100644 --- a/addons/auth_signup/i18n/ru.po +++ b/addons/auth_signup/i18n/ru.po @@ -172,7 +172,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sk.po b/addons/auth_signup/i18n/sk.po index a4d1b88045a..19ffb9c03ff 100644 --- a/addons/auth_signup/i18n/sk.po +++ b/addons/auth_signup/i18n/sk.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sl.po b/addons/auth_signup/i18n/sl.po index 9d55f11f98d..d2011ee612c 100644 --- a/addons/auth_signup/i18n/sl.po +++ b/addons/auth_signup/i18n/sl.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sq.po b/addons/auth_signup/i18n/sq.po index 164fdf95948..0bcff3b0ad8 100644 --- a/addons/auth_signup/i18n/sq.po +++ b/addons/auth_signup/i18n/sq.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sr.po b/addons/auth_signup/i18n/sr.po index 39bcf501d75..6a1f8a51afb 100644 --- a/addons/auth_signup/i18n/sr.po +++ b/addons/auth_signup/i18n/sr.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sr@latin.po b/addons/auth_signup/i18n/sr@latin.po index 08a385e2a3b..bd4ac9ee65e 100644 --- a/addons/auth_signup/i18n/sr@latin.po +++ b/addons/auth_signup/i18n/sr@latin.po @@ -110,7 +110,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/sv.po b/addons/auth_signup/i18n/sv.po index d3b6c33642c..aa14a9b4a39 100644 --- a/addons/auth_signup/i18n/sv.po +++ b/addons/auth_signup/i18n/sv.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/th.po b/addons/auth_signup/i18n/th.po index 16eaf1167ef..46fe1210082 100644 --- a/addons/auth_signup/i18n/th.po +++ b/addons/auth_signup/i18n/th.po @@ -108,7 +108,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/tr.po b/addons/auth_signup/i18n/tr.po index 7516441be69..8e0333e0cb6 100644 --- a/addons/auth_signup/i18n/tr.po +++ b/addons/auth_signup/i18n/tr.po @@ -170,7 +170,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/uk.po b/addons/auth_signup/i18n/uk.po index d2223996c04..0666c2a5bb4 100644 --- a/addons/auth_signup/i18n/uk.po +++ b/addons/auth_signup/i18n/uk.po @@ -169,7 +169,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/vi.po b/addons/auth_signup/i18n/vi.po index 4fd58b26cfa..84d5bab21b7 100644 --- a/addons/auth_signup/i18n/vi.po +++ b/addons/auth_signup/i18n/vi.po @@ -109,7 +109,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" diff --git a/addons/auth_signup/i18n/zh_CN.po b/addons/auth_signup/i18n/zh_CN.po index 8accd5a1bed..6c02191a5b6 100644 --- a/addons/auth_signup/i18n/zh_CN.po +++ b/addons/auth_signup/i18n/zh_CN.po @@ -170,7 +170,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" @@ -204,7 +203,6 @@ msgstr "" "

\n" " 您的登录账号:${object.email}\n" "
\n" -" 您的密码:${ctx['password']}\n" "

\n" "

\n" " 要获取访问您账户的权限,可使用以下链接:\n" diff --git a/addons/auth_signup/i18n/zh_TW.po b/addons/auth_signup/i18n/zh_TW.po index fd843e2e2f2..9c710056350 100644 --- a/addons/auth_signup/i18n/zh_TW.po +++ b/addons/auth_signup/i18n/zh_TW.po @@ -166,7 +166,6 @@ msgid "" "

\n" " Your login: ${object.email}\n" "
\n" -" Your password: ${ctx['password']}\n" "

\n" "

\n" " To gain access to your account, you can use the following link:\n" From c22d3f67320f3c3edfdd3d00732021e896f2cda6 Mon Sep 17 00:00:00 2001 From: Xavier ALT Date: Thu, 3 May 2018 10:07:22 +0200 Subject: [PATCH 30/51] [FIX] web: widget char_domain should pass context to selection dialog In case we define a field like, when selecting records the dialog should display all records (as asked by the context), but it's not the case. This commit ensure the field context is passed to the selection dialog. opw-1831902 --- addons/web/static/src/js/views/form_widgets.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js index b99732774f2..25b4fbed8ba 100644 --- a/addons/web/static/src/js/views/form_widgets.js +++ b/addons/web/static/src/js/views/form_widgets.js @@ -454,6 +454,7 @@ var FieldCharDomain = common.AbstractField.extend(common.ReinitializeFieldMixin, var self = this; var dialog = new common.DomainEditorDialog(this, { res_model: this.options.model || this.field_manager.get_field_value(this.options.model_field), + context: self.build_context(), default_domain: this.get('value'), title: this.get('effective_readonly') ? _t('Selected records') : _t('Select records...'), readonly: this.get('effective_readonly'), From 491243d1caa46b75a08a656a0049e79fd7597258 Mon Sep 17 00:00:00 2001 From: Nicolas Martinelli Date: Wed, 16 May 2018 13:23:00 +0200 Subject: [PATCH 31/51] [FIX] stock_account: partial reception with avg cost MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create a product where the associated product category has Costing Method "Average Cost (AVCO)" - Create a PO. Order 1 unit at $1000. - Receive that unit. (System now has 1 unit at $1000). - Create another PO. Order 3 units at $500 each. - Receive only 1 unit and don’t create any back order. System has 2 units @ $625, instead of $750. The quantity computed should take into account the quantity actually done. opw-1843998 --- addons/stock_account/models/stock.py | 8 +++-- .../tests/test_stockvaluation.py | 33 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py index 113ff99b87a..2a7cb101c4e 100644 --- a/addons/stock_account/models/stock.py +++ b/addons/stock_account/models/stock.py @@ -372,6 +372,7 @@ class StockMove(models.Model): product_tot_qty_available = move.product_id.qty_available + tmpl_dict[move.product_id.id] rounding = move.product_id.uom_id.rounding + qty_done = 0.0 if float_is_zero(product_tot_qty_available, precision_rounding=rounding): new_std_price = move._get_price_unit() elif float_is_zero(product_tot_qty_available + move.product_qty, precision_rounding=rounding): @@ -379,10 +380,11 @@ class StockMove(models.Model): else: # Get the standard price amount_unit = std_price_update.get((move.company_id.id, move.product_id.id)) or move.product_id.standard_price - qty = forced_qty or move.product_qty - new_std_price = ((amount_unit * product_tot_qty_available) + (move._get_price_unit() * qty)) / (product_tot_qty_available + move.product_qty) + qty_done = move.product_uom._compute_quantity(move.quantity_done, move.product_id.uom_id) + qty = forced_qty or qty_done + new_std_price = ((amount_unit * product_tot_qty_available) + (move._get_price_unit() * qty)) / (product_tot_qty_available + qty_done) - tmpl_dict[move.product_id.id] += move.product_qty + tmpl_dict[move.product_id.id] += qty_done # Write the standard price, as SUPERUSER_ID because a warehouse manager may not have the right to write on products move.product_id.with_context(force_company=move.company_id.id).sudo().write({'standard_price': new_std_price}) std_price_update[move.company_id.id, move.product_id.id] = new_std_price diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py index 50cc57885bb..0450d66e9a1 100644 --- a/addons/stock_account/tests/test_stockvaluation.py +++ b/addons/stock_account/tests/test_stockvaluation.py @@ -2489,6 +2489,39 @@ class TestStockValuation(TransactionCase): move2.move_line_ids.qty_done = 0 self.assertEqual(self.product1.stock_value, -187.5) + def test_average_perpetual_4(self): + self.product1.product_tmpl_id.cost_method = 'average' + + move1 = self.env['stock.move'].create({ + 'name': 'Receive 1 unit at 10', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 1.0, + 'price_unit': 10, + }) + move1._action_confirm() + move1._action_assign() + move1.move_line_ids.qty_done = 1.0 + move1._action_done() + + move2 = self.env['stock.move'].create({ + 'name': 'Receive 3 units at 5', + 'location_id': self.supplier_location.id, + 'location_dest_id': self.stock_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 3.0, + 'price_unit': 5, + }) + move2._action_confirm() + move2._action_assign() + move2.move_line_ids.qty_done = 1.0 + move2._action_done() + + self.assertAlmostEqual(self.product1.standard_price, 7.5) + def test_average_negative_1(self): """ Test edit in the past. Receive 10, send 20, edit the second move to only send 10. """ From 1c6aa878cb8cf71f02596e28f0e2ba63981ad339 Mon Sep 17 00:00:00 2001 From: Toufik Benjaa Date: Tue, 15 May 2018 18:13:35 +0200 Subject: [PATCH 32/51] [FIX] project: Access rights issue on /my/tasks - Portal users do not have the rights to read on project.project. This causes issues on the page "/my/tasks" as it is trying to read the label_tasks and the name of the tasks' project. To address this issue we read those two fields using sudo --- addons/project/views/project_portal_templates.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project/views/project_portal_templates.xml b/addons/project/views/project_portal_templates.xml index 2a75caba97f..7273a76faad 100644 --- a/addons/project/views/project_portal_templates.xml +++ b/addons/project/views/project_portal_templates.xml @@ -142,7 +142,7 @@ Name - for project: + for project: Stage Ref From c52243794dc7c9874373f98528ce606bb80a029d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Wed, 16 May 2018 10:21:19 +0200 Subject: [PATCH 33/51] [REVERT] "[FIX] mail: fix composer style for chat windows" This reverts commit 0275c70f78b7f10c5f84692dcebc4f2aeeec76b6. --- addons/mail/static/src/less/composer.less | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/addons/mail/static/src/less/composer.less b/addons/mail/static/src/less/composer.less index 2836e3c93bb..976473f6e1e 100644 --- a/addons/mail/static/src/less/composer.less +++ b/addons/mail/static/src/less/composer.less @@ -2,6 +2,7 @@ position: relative; .o-flex(0, 0, auto); .o-flex-display(); + margin: 1px 0; border-top: none; background: @gray-lighter; @@ -36,12 +37,10 @@ cursor: text; display: inline-block; height: 100%; + padding: 0px 0px @o-mail-chatter-gap; white-space: pre-wrap; word-break: break-all; } - .o_composer_text_field { - padding: 0 0 @o-mail-chatter-gap; - } .o_composer_mention_dropdown .o_mention_proposition > a { .o-text-overflow(); width: 100%; @@ -148,6 +147,7 @@ .o_composer { display: flex; min-height: 40px; + padding: @o-mail-chatter-gap @o-mail-chatter-gap 0 @o-mail-chatter-gap; border-radius: 2px 0 0 2px; border-right-width: 0; } @@ -159,7 +159,6 @@ .o-flex-flow(row, wrap); } .o_composer_text_field { - padding: @o-mail-chatter-gap; .o-flex(1, 1, 50%); } .o_chatter_composer_tools { @@ -172,8 +171,8 @@ .o_chatter_composer_tools { border: none; border-left: 1px solid @gray-lighter-dark; - padding-top: @o-mail-chatter-gap*0.5; padding-left: @o-mail-chatter-gap*0.5; + .o-transform(translateY(-@o-mail-chatter-gap*0.5)); } .o_composer_button_send { @@ -197,7 +196,6 @@ border-bottom-width: 1px; } .o_composer_input { - padding: @o-mail-chatter-gap; .o-flex-flow(row, nowrap); .o_chatter_composer_tools { From 93f9131450118f25c72982f7326ff820cee4aadf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Wed, 16 May 2018 10:30:55 +0200 Subject: [PATCH 34/51] [REVERT] "[IMP] mail : display mentions in green color in edit mode" This reverts commit c778de44c7cd9b7ef5a9a91738164ab0ebd0ca06. --- addons/mail/static/src/js/chatter.js | 2 +- addons/mail/static/src/js/chatter_composer.js | 2 +- addons/mail/static/src/js/composer.js | 257 ++++++------------ addons/mail/static/src/less/composer.less | 85 +++--- .../static/src/less/extended_chat_window.less | 8 +- addons/mail/static/src/xml/composer.xml | 12 +- addons/mail/static/tests/chatter_tests.js | 19 +- addons/mail/static/tests/discuss_tests.js | 9 +- addons/web/static/tests/helpers/test_utils.js | 48 ---- 9 files changed, 144 insertions(+), 298 deletions(-) diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index 7d9f324042d..e48a7c60028 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -184,7 +184,7 @@ var Chatter = Widget.extend({ input_baseline: 14, is_log: options && options.is_log, record_name: this.record_name, - default_body: old_composer && old_composer.$input && old_composer.$input.html(), + default_body: old_composer && old_composer.$input && old_composer.$input.val(), default_mention_selections: old_composer && old_composer.mention_get_listener_selections(), }); this.composer.on('input_focused', this, function () { diff --git a/addons/mail/static/src/js/chatter_composer.js b/addons/mail/static/src/js/chatter_composer.js index 0a8088d87ae..c1660ba1c68 100644 --- a/addons/mail/static/src/js/chatter_composer.js +++ b/addons/mail/static/src/js/chatter_composer.js @@ -211,7 +211,7 @@ var ChatterComposer = composer.BasicComposer.extend({ recipient_done.then(function (partner_ids) { var context = { default_parent_id: self.id, - default_body: utils.get_text2html(self.$input.html()), + default_body: utils.get_text2html(self.$input.val()), default_attachment_ids: _.pluck(self.get('attachment_ids'), 'id'), default_partner_ids: partner_ids, default_is_log: self.options.is_log, diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js index 45958a620f6..f89c0382554 100644 --- a/addons/mail/static/src/js/composer.js +++ b/addons/mail/static/src/js/composer.js @@ -7,6 +7,7 @@ var utils = require('mail.utils'); var config = require('web.config'); var core = require('web.core'); var data = require('web.data'); +var dom = require('web.dom'); var session = require('web.session'); var Widget = require('web.Widget'); @@ -29,7 +30,7 @@ var MentionManager = Widget.extend({ events: { "mouseover .o_mention_proposition": "on_hover_mention_proposition", - "click .o_mention_proposition": "_onClickMentionItem", + "click .o_mention_proposition": "on_click_mention_item", }, init: function (parent, options) { @@ -52,6 +53,49 @@ var MentionManager = Widget.extend({ this.$('.o_mention_proposition').removeClass('active'); $elem.addClass('active'); }, + on_click_mention_item: function (event) { + event.preventDefault(); + + var text_input = this.composer.$input.val(); + var id = $(event.currentTarget).data('id'); + var selected_suggestion = _.find(_.flatten(this.get('mention_suggestions')), function (s) { + return s.id === id; + }); + var substitution = selected_suggestion.substitution; + if (!substitution) { // no substitution string given, so use the mention name instead + // replace white spaces with non-breaking spaces to facilitate mentions detection in text + selected_suggestion.name = selected_suggestion.name.replace(/ /g, NON_BREAKING_SPACE); + substitution = this.active_listener.delimiter + selected_suggestion.name; + } + var get_mention_index = function (matches, cursor_position) { + for (var i=0; i 0) { return false; } - var search_str = textVal.substring(delimiter_position, cursorPosition); + var search_str = text_val.substring(delimiter_position, cursor_position); var pattern = "(^"+delimiter+"|(^\\s"+delimiter+"))"; var regex_start = new RegExp(pattern, "g"); search_str = search_str.replace(/^\s\s*|^[\n\r]/g, ''); @@ -203,8 +247,6 @@ var MentionManager = Widget.extend({ /** * Returns the matches (as RexExp.exec does) for the mention in the input text - * - * @private * @param {String} input_text: the text to search matches * @param {Object} listener: the listener for which we want to find a match * @returns {Object[]} matches in the same format as RexExp.exec() @@ -228,32 +270,6 @@ var MentionManager = Widget.extend({ } return result; }, - /** - * Get cursor position in contenteditable div with it's inner html content. - * - * @private - * @return a current cursor position - */ - _getSelectionPositions: function () { - if (window.getSelection && window.getSelection().getRangeAt) { - var range = window.getSelection().getRangeAt(0); - var selectedObj = window.getSelection(); - var rangeCount = 0; - var childNodes = selectedObj.anchorNode.parentNode.childNodes; - for (var i = 0; i < childNodes.length; i++) { - if (childNodes[i] === selectedObj.anchorNode) { - break; - } - if (childNodes[i].outerHTML) - rangeCount += childNodes[i].outerHTML.length; - else if (childNodes[i].nodeType === 3) { - rangeCount += childNodes[i].textContent.length; - } - } - return range.startOffset + rangeCount; - } - return -1; - }, /** * @private * @param {integer} keycode @@ -312,23 +328,9 @@ var MentionManager = Widget.extend({ this.open = false; } }, - /* - * Set cursor position after mention is added. - * @private - * @paran {int} node - id of childnode to set cursor position after it. - */ - _setCursorPosition: function (nodeID) { - var range = document.createRange(); - var selection = window.getSelection(); - range.setStart(document.getElementById(nodeID).nextSibling, 1); - range.collapse(true); - selection.removeAllRanges(); - selection.addRange(range); - this.composer.$input.focus(); - }, - _validate_selection: function (selection, inputMentions) { + _validate_selection: function (selection, input_mentions) { var validated_selection = []; - _.each(inputMentions, function (mention) { + _.each(input_mentions, function (mention) { var validated_mention = _.findWhere(selection, {name: mention.slice(1)}); if (validated_mention) { validated_selection.push(validated_mention); @@ -337,60 +339,15 @@ var MentionManager = Widget.extend({ return validated_selection; }, - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * after click on mention item it set to a contenteditable div with it's new - * cursor postion - * - * @private - * @param {KeyboardEvent} event - to get a current selected mention from - * list and eventlistener. - */ - _onClickMentionItem: function (event) { - event.preventDefault(); - - var textInput = this.composer.$input.html(); - var id = $(event.currentTarget).data('id'); - var selectedSuggestion = _.find(_.flatten(this.get('mention_suggestions')), function (s) { - return s.id === id; + // Cursor position and selection utils + _get_selection_positions: function () { + var el = this.composer.$input.get(0); + return el ? dom.getSelectionRange(el) : {start: 0, end: 0}; + }, + _set_cursor_position: function (pos) { + this.composer.$input.each(function (index, elem) { + dom.setSelectionRange(elem, {start: pos, end: pos}); }); - var substitution = selectedSuggestion.substitution; - if (!substitution) { // no substitution string given, so use the mention name instead - // replace white spaces with non-breaking spaces to facilitate mentions detection in text - selectedSuggestion.name = selectedSuggestion.name.replace(/ /g, NON_BREAKING_SPACE); - substitution = _.escape(this.active_listener.delimiter + selectedSuggestion.name); - } - var getMentionIndex = function (matches, cursorPosition) { - for (var i=0; i" + substitution + " " + textRight; - this.composer.$input.html(newTextInput); - this._setCursorPosition(nodeID); - this.set('mention_suggestions', []); }, }); @@ -398,8 +355,8 @@ var MentionManager = Widget.extend({ var BasicComposer = Widget.extend({ template: "mail.ChatComposer", events: { - "keydown .o_composer_input": "_onKeydown", - "keyup .o_composer_input": "_onKeyup", + "keydown .o_composer_input textarea": "on_keydown", + "keyup .o_composer_input": "on_keyup", "change input.o_input_file": "on_attachment_change", "click .o_composer_button_send": "send_message", "click .o_composer_button_add_attachment": "on_click_add_attachment", @@ -410,7 +367,6 @@ var BasicComposer = Widget.extend({ 'focusout .o_composer_button_emoji': '_onEmojiButtonFocusout', 'focus .o_mail_emoji_container .o_mail_emoji': '_onEmojiImageFocus', 'click .o_mail_emoji_container .o_mail_emoji': '_onEmojiImageClick', - 'input .o_composer_input': '_removeMention', }, // RPCs done to fetch the mention suggestions are throttled with the following value MENTION_THROTTLE: 200, @@ -487,12 +443,12 @@ var BasicComposer = Widget.extend({ this.$attachment_button = this.$(".o_composer_button_add_attachment"); this.$attachments_list = this.$('.o_composer_attachments_list'); - this.$input = this.$('.o_composer_input'); + this.$input = this.$('.o_composer_input textarea'); this.$input.focus(function () { self.trigger('input_focused'); }); - this.$input.html(this.options.default_body); - this.$input.css('min-height', this.options.input_min_height); + this.$input.val(this.options.default_body); + dom.autoresize(this.$input, {parent: this, min_height: this.options.input_min_height}); // Attachments $(window).on(this.fileupload_id, this.on_attachment_loaded); @@ -514,7 +470,7 @@ var BasicComposer = Widget.extend({ // behavior for the chatter composer //Removing unwanted extra spaces from message - var value = _.escape(this.$input.text()).trim(); + var value = _.escape(this.$input.val()).trim(); value = value.replace(/(\r|\n){2,}/g, '

'); value = value.replace(/(\r|\n)/g, '
'); @@ -545,7 +501,7 @@ var BasicComposer = Widget.extend({ clear_composer: function() { // Empty input, selected partners and attachments - this.$input.html(''); + this.$input.val(''); this.mention_manager.reset_selections(); this.set('attachment_ids', []); }, @@ -557,7 +513,7 @@ var BasicComposer = Widget.extend({ getState: function () { return { attachments: this.get('attachment_ids'), - text: this.$input.html(), + text: this.$input.val(), }; }, @@ -572,7 +528,7 @@ var BasicComposer = Widget.extend({ setState: function (state) { this.set('attachment_ids', state.attachments); - this.$input.html(state.text); + this.$input.val(state.text); }, /** @@ -581,18 +537,8 @@ var BasicComposer = Widget.extend({ should_send: function (event) { return !event.shiftKey; }, - /** - * _onKeydown event is triggered when is key is pressed - * - on UP and DOWN arrow is pressed then event prevents it's default - * behaviour if mention manager is open else it break it. - * - on ENTER key is pressed and mention manager is open then event - * prevents it's default behaviour else check if ControlKey is - * pressed or not if yes then it send a message - * - * @private - * @param {KeyboardEvent} event - */ - _onKeydown: function (event) { + + on_keydown: function (event) { switch(event.which) { // UP, DOWN, TAB: prevent moving cursor if navigation in mention propositions case $.ui.keyCode.UP: @@ -617,16 +563,7 @@ var BasicComposer = Widget.extend({ } }, - /** - * _onKeyup event is triggered when key is released. - * on ESCAP key it close the mention suggestion dropdown menu. - * on ENTER key it selects that mention and add to a content editable div. - * on UP or DOWN key it highlights previous or next mention respectively. - * - * @private - * @param {KeyboardEvent} event - */ - _onKeyup: function (event) { + on_keyup: function (event) { switch(event.which) { // ESCAPED KEYS: do nothing case $.ui.keyCode.END: @@ -743,13 +680,6 @@ var BasicComposer = Widget.extend({ attachments: this.get('attachment_ids'), })); }, - // remove mention when user try to edit or remove it. - _removeMention: function (event) { - var anchorNode = window.getSelection().anchorNode; - if (anchorNode.textContent.startsWith('@') && anchorNode.parentNode.tagName === 'A') { - anchorNode.parentNode.remove(); - } - }, // Mention mention_fetch_throttled: function (model, method, kwargs) { @@ -835,14 +765,8 @@ var BasicComposer = Widget.extend({ }, // Others - /** - * used to check if contenteditable div is empty or not - * - * @return - it returns length of attachment and trim content of input box - * tp check for empty. - */ is_empty: function () { - return !this.$input.text().trim() && !this.$('.o_attachments').children().length; + return !this.$input.val().trim() && !this.$('.o_attachments').children().length; }, focus: function () { this.$input.focus(); @@ -901,7 +825,7 @@ var BasicComposer = Widget.extend({ if (this.$emojisContainer.parent().length) { this._hideEmojis(); } else { - this.$emojisContainer.appendTo(this.$('.o_composer_container')); + this.$emojisContainer.appendTo(this.$('.o_composer')); } }, /** @@ -925,31 +849,6 @@ var BasicComposer = Widget.extend({ _onEmojiImageFocus: function () { clearTimeout(this._hideEmojisTimeout); }, - /** - * set cursor position at the end in input box - * - * @todo move that kind of code in a utility file. Maybe dom.js - * - * @private - * @param {Element} el - */ - _placeCaretAtEnd: function (el) { - el.focus(); - if (typeof window.getSelection !== "undefined" - && typeof document.createRange !== "undefined") { - var range = document.createRange(); - range.selectNodeContents(el); - range.collapse(false); - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } else if (typeof document.body.createTextRange !== "undefined") { - var textRange = document.body.createTextRange(); - textRange.moveToElementText(el); - textRange.collapse(false); - textRange.select(); - } - }, /** * Called when an emoji is clicked -> adds it in the , focuses the * and closes the emoji panel. @@ -958,8 +857,8 @@ var BasicComposer = Widget.extend({ * @param {Event} ev */ _onEmojiImageClick: function (ev) { - this.$input.html(this.$input.html() + " " + $(ev.currentTarget).data('emoji') + " "); - this._placeCaretAtEnd(this.$input[0]); + this.$input.val(this.$input.val() + " " + $(ev.currentTarget).data('emoji') + " "); + this.$input.focus(); this._hideEmojis(); }, }); diff --git a/addons/mail/static/src/less/composer.less b/addons/mail/static/src/less/composer.less index 976473f6e1e..9213fb6c416 100644 --- a/addons/mail/static/src/less/composer.less +++ b/addons/mail/static/src/less/composer.less @@ -10,7 +10,7 @@ position: relative; background: white; - input { + textarea, input { border: none; } } @@ -27,19 +27,9 @@ } .o_composer { - .o_composer_input[contenteditable=true]:empty:before { - content: attr(placeholder); - opacity: 0.4; - } - .o_composer_input { - border: none; - box-shadow: none; - cursor: text; - display: inline-block; - height: 100%; - padding: 0px 0px @o-mail-chatter-gap; - white-space: pre-wrap; - word-break: break-all; + .o_composer_input > textarea { + width: 100%; + resize: none; } .o_composer_mention_dropdown .o_mention_proposition > a { .o-text-overflow(); @@ -68,16 +58,17 @@ color: @odoo-brand-optional; } } - } - .o_mail_emoji_container { - padding: 0 @o-mail-chatter-gap @o-mail-chatter-gap 0; - border: 1px solid @gray-lighter-dark; - background-color: @gray-lighter; + .o_mail_emoji_container { + padding: 0 @o-mail-chatter-gap @o-mail-chatter-gap 0; + border: 1px solid @gray-lighter-dark; + border-width: 1px 0 0 0; + background-color: @gray-lighter; - .o_mail_emoji { - margin: @o-mail-chatter-gap 0 0 @o-mail-chatter-gap; - cursor: pointer; // only in the popover + .o_mail_emoji { + margin: @o-mail-chatter-gap 0 0 @o-mail-chatter-gap; + cursor: pointer; // only in the popover + } } } @@ -103,13 +94,19 @@ .o_composer { border-radius: 2px; + textarea { + padding-right: @grid-gutter-width; // avoid overlaps betwenn textarea and o_composer_button_full_composer + } + .o_mail_emoji_container { + margin: 0 -@o-mail-chatter-gap; + } } .o_composer, .o_composer_subject { border: 1px solid @gray-lighter-dark; - input { + textarea, input { padding: 0 0 @o-mail-chatter-gap; border: none; } @@ -121,9 +118,6 @@ .o_chatter_composer_tools { border-top: 1px solid @gray-lighter-dark; - @media (max-width: @screen-xs-max) { - margin-top: 10px; - } } &:not(.o_chat_inline_composer) { @@ -142,24 +136,26 @@ &.o_chat_inline_composer { .o_composer_container { - .o-flex(1, 1, auto); + .o-flex(1, 0, auto); } .o_composer { - display: flex; - min-height: 40px; padding: @o-mail-chatter-gap @o-mail-chatter-gap 0 @o-mail-chatter-gap; border-radius: 2px 0 0 2px; border-right-width: 0; - } - .o_mail_emoji_container { - text-align: right; - border-width: 1px; + + .o_mail_emoji_container { + text-align: right; + border-right-width: 1px; + } } .o_composer_input { + .o-flex-display(); .o-flex-flow(row, wrap); } .o_composer_text_field { .o-flex(1, 1, 50%); + margin: 0; + padding: 0; } .o_chatter_composer_tools { .o-flex(0, 1, auto); @@ -191,25 +187,32 @@ border-top: 1px solid @gray-lighter-dark; width: 100%; } - .o_mail_emoji_container { - .o-position-absolute(auto, 0, 100%, 0); - border-bottom-width: 1px; + .o_composer { + .o_mail_emoji_container { + .o-position-absolute(auto, 0, 100%, 0); + border-bottom-width: 1px; + } } .o_composer_input { + .o-flex-display(); .o-flex-flow(row, nowrap); + textarea.o_composer_text_field { + .o-flex(1, 1, auto); + } + .o_chatter_composer_tools { .o-flex(0, 0, auto); } + @media (max-width: @screen-xs-max) { + .o_composer_button_send { + display: inline-block; + } + } } .o_composer_button_send, .o_chatter_avatar { display: none; } - @media (max-width: @screen-xs-max) { - .o_composer_button_send { - display: inline-block; - } - } } } diff --git a/addons/mail/static/src/less/extended_chat_window.less b/addons/mail/static/src/less/extended_chat_window.less index fcf92cf052a..3ae73dee861 100644 --- a/addons/mail/static/src/less/extended_chat_window.less +++ b/addons/mail/static/src/less/extended_chat_window.less @@ -42,14 +42,10 @@ } .o_chatter_composer_tools { .o-position-absolute(@right: 0px, @top: 0px); - - @media (max-width: @screen-xs-max) { - .o-position-absolute(@right: 6px, @top: 0px); - } button { - padding: 8px; + padding: 10px; @media (max-width: @screen-xs-max) { - padding: 7px 6px 0px 6px; + padding: 13px; } &.btn-icon { font-size: 1.3em; diff --git a/addons/mail/static/src/xml/composer.xml b/addons/mail/static/src/xml/composer.xml index 2795a0bb724..b46af297928 100644 --- a/addons/mail/static/src/xml/composer.xml +++ b/addons/mail/static/src/xml/composer.xml @@ -8,11 +8,13 @@

-
-
-