[IMP] mail,sms: revamp the resend modals

The error messages of the resend modals can be partially hidden in the
table. The user can therefore have difficulty to understand what went
wrong when the server failed to send an email or an sms. To avoid that,
we will ensure that the error messages will be fully visible in the table.

To improve the interface, we will also update the label of a some fields
and we will automatically hide the 'Send & Close' buttons from the resend
modals when the user did not select at least one recipient from the list.

task-2523036

Part-of: odoo/odoo#71413
This commit is contained in:
Julien Banken
2021-09-30 13:31:53 +00:00
parent 259508fdd4
commit e4c583fcc8
4 changed files with 43 additions and 32 deletions
+12 -7
View File
@@ -12,12 +12,17 @@ class MailResendMessage(models.TransientModel):
mail_message_id = fields.Many2one('mail.message', 'Message', readonly=True)
partner_ids = fields.One2many('mail.resend.partner', 'resend_wizard_id', string='Recipients')
notification_ids = fields.Many2many('mail.notification', string='Notifications', readonly=True)
has_cancel = fields.Boolean(compute='_compute_has_cancel')
can_cancel = fields.Boolean(compute='_compute_can_cancel')
can_resend = fields.Boolean(compute='_compute_can_resend')
partner_readonly = fields.Boolean(compute='_compute_partner_readonly')
@api.depends("partner_ids")
def _compute_has_cancel(self):
self.has_cancel = self.partner_ids.filtered(lambda p: not p.resend)
def _compute_can_cancel(self):
self.can_cancel = self.partner_ids.filtered(lambda p: not p.resend)
@api.depends('partner_ids.resend')
def _compute_can_resend(self):
self.can_resend = any([partner.resend for partner in self.partner_ids])
def _compute_partner_readonly(self):
self.partner_readonly = not self.env['res.partner'].check_access_rights('write', raise_exception=False)
@@ -91,8 +96,8 @@ class PartnerResend(models.TransientModel):
_description = 'Partner with additional information for mail resend'
partner_id = fields.Many2one('res.partner', string='Partner', required=True, ondelete='cascade')
name = fields.Char(related="partner_id.name", related_sudo=False, readonly=False)
email = fields.Char(related="partner_id.email", related_sudo=False, readonly=False)
resend = fields.Boolean(string="Send Again", default=True)
name = fields.Char(related='partner_id.name', string='Recipient Name', related_sudo=False, readonly=False)
email = fields.Char(related='partner_id.email', string='Email Address', related_sudo=False, readonly=False)
resend = fields.Boolean(string='Try Again', default=True)
resend_wizard_id = fields.Many2one('mail.resend.message', string="Resend wizard")
message = fields.Char(string="Help message")
message = fields.Char(string='Error message')
@@ -9,31 +9,31 @@
<form string="Edit Partners">
<field name="mail_message_id" invisible="1"/>
<field name="notification_ids" invisible="1"/>
<field name="has_cancel" invisible="1"/>
<field name="can_resend" invisible="1"/>
<field name="partner_readonly" invisible="1"/>
<p>Select the action to do on each mail and correct the email address if needed. The modified address will be saved on the corresponding contact.</p>
<field name="partner_ids">
<tree string="Recipient" editable="top" create="0" delete="0">
<field name="name" readonly="1"/>
<field name="email" attrs="{'readonly': [('parent.partner_readonly', '=', True)]}"/>
<field name="message" readonly="1"/>
<field name="message" readonly="1" class="text-wrap"/>
<field name="partner_id" invisible="1"/>
<field name="resend" widget="boolean_toggle"/>
</tree>
</field>
<div class="alert alert-warning" role="alert" attrs="{'invisible': [('has_cancel', '=', False)]}">
<span class="fa fa-info-circle"/> Caution: It won't be possible to send this mail again to the recipients you did not select.
</div>
<footer>
<button string="Resend to selected" name="resend_mail_action" type="object" class="btn-primary o_mail_send" data-hotkey="q"/>
<button string="Ignore all failures" name="cancel_mail_action" type="object" class="btn-secondary" data-hotkey="w" />
<button string="Cancel" class="btn-secondary" special="cancel" data-hotkey="z" />
<button string="Send &amp; close" name="resend_mail_action" type="object" class="btn-primary o_mail_send"
attrs="{'invisible': [('can_resend', '=', False)]}" data-hotkey="q"/>
<button string="Ignore all" name="cancel_mail_action" type="object" class="btn-primary"
attrs="{'invisible': [('can_resend', '=', True)]}" data-hotkey="w"/>
<button string="Ignore all" name="cancel_mail_action" type="object" class="btn-secondary"
attrs="{'invisible': [('can_resend', '=', False)]}" data-hotkey="w"/>
<button string="Close" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</form>
</field>
</record>
<record id="mail_resend_message_action" model="ir.actions.act_window">
<field name="name">Resend mail</field>
<field name="name">Sending Failures</field>
<field name="res_model">mail.resend.message</field>
<field name="type">ir.actions.act_window</field>
<field name="view_mode">form</field>
+12 -7
View File
@@ -11,12 +11,12 @@ class SMSRecipient(models.TransientModel):
sms_resend_id = fields.Many2one('sms.resend', required=True)
notification_id = fields.Many2one('mail.notification', required=True, ondelete='cascade')
resend = fields.Boolean(string="Resend", default=True)
resend = fields.Boolean(string='Try Again', default=True)
failure_type = fields.Selection(
related='notification_id.failure_type', related_sudo=True, readonly=True)
related='notification_id.failure_type', string='Error Message', related_sudo=True, readonly=True)
partner_id = fields.Many2one('res.partner', 'Partner', related='notification_id.res_partner_id', readonly=True)
partner_name = fields.Char('Recipient', readonly='True')
sms_number = fields.Char('Number')
partner_name = fields.Char(string='Recipient Name', readonly='True')
sms_number = fields.Char(string='Phone Number')
class SMSResend(models.TransientModel):
@@ -40,7 +40,8 @@ class SMSResend(models.TransientModel):
mail_message_id = fields.Many2one('mail.message', 'Message', readonly=True, required=True)
recipient_ids = fields.One2many('sms.resend.recipient', 'sms_resend_id', string='Recipients')
has_cancel = fields.Boolean(compute='_compute_has_cancel')
can_cancel = fields.Boolean(compute='_compute_can_cancel')
can_resend = fields.Boolean(compute='_compute_can_resend')
has_insufficient_credit = fields.Boolean(compute='_compute_has_insufficient_credit')
has_unregistered_account = fields.Boolean(compute='_compute_has_unregistered_account')
@@ -53,8 +54,12 @@ class SMSResend(models.TransientModel):
self.has_insufficient_credit = self.recipient_ids.filtered(lambda p: p.failure_type == 'sms_credit')
@api.depends("recipient_ids.resend")
def _compute_has_cancel(self):
self.has_cancel = self.recipient_ids.filtered(lambda p: not p.resend)
def _compute_can_cancel(self):
self.can_cancel = self.recipient_ids.filtered(lambda p: not p.resend)
@api.depends('recipient_ids.resend')
def _compute_can_resend(self):
self.can_resend = any([recipient.resend for recipient in self.recipient_ids])
def _check_access(self):
if not self.mail_message_id or not self.mail_message_id.model or not self.mail_message_id.res_id:
+9 -8
View File
@@ -7,29 +7,30 @@
<field name="arch" type="xml">
<form string="Edit Partners">
<field name="mail_message_id" invisible="1"/>
<field name="has_cancel" invisible="1"/>
<field name="can_resend" invisible="1"/>
<field name="has_insufficient_credit" invisible="1"/>
<field name="has_unregistered_account" invisible="1"/>
<field name="recipient_ids">
<tree string="Recipient" editable="top" create="0" delete="0">
<field name="partner_name"/>
<field name="sms_number"/>
<field name="failure_type" string="Reason"/>
<field name="failure_type" string="Reason" class="text-wrap"/>
<field name="resend" widget="boolean_toggle"/>
<field name="notification_id" invisible="1"/>
</tree>
</field>
<div class="alert alert-warning" role="alert" attrs="{'invisible': [('has_cancel', '=', False)]}">
<span class="fa fa-info-circle"/> Caution: It won't be possible to send this SMS again to the recipients you did not select.
</div>
<footer>
<button string="Buy credits" name="action_buy_credits" type="object" class="btn-primary o_mail_send"
attrs="{'invisible': [('has_insufficient_credit', '=', False)]}" data-hotkey="q"/>
<button string="Set up an account" name="action_buy_credits" type="object" class="btn-primary o_mail_send"
attrs="{'invisible': [('has_unregistered_account', '=', False)]}" data-hotkey="q"/>
<button string="Resend" name="action_resend" type="object" class="btn-primary o_mail_send" data-hotkey="w"/>
<button string="Ignore all" name="action_cancel" type="object" class="btn-secondary" data-hotkey="x"/>
<button string="Discard" class="btn-secondary" special="cancel" data-hotkey="z"/>
<button string="Send &amp; Close" name="action_resend" type="object" class="btn-primary o_mail_send"
attrs="{'invisible': ['|', ('has_unregistered_account', '=', False), ('can_resend', '=', False)]}" data-hotkey="w"/>
<button string="Ignore all" name="action_cancel" type="object" class="btn-primary"
attrs="{'invisible': ['|', '|', ('has_insufficient_credit', '=', True), ('has_unregistered_account', '=', True), '&amp;', ('has_unregistered_account', '=', True), ('can_resend', '=', True)]}" data-hotkey="x"/>
<button string="Ignore all" name="action_cancel" type="object" class="btn-secondary"
attrs="{'invisible': ['!', '|', '|', ('has_insufficient_credit', '=', True), ('has_unregistered_account', '=', True), '&amp;', ('has_unregistered_account', '=', True), ('can_resend', '=', True)]}" data-hotkey="x"/>
<button string="Close" class="btn-secondary" special="cancel" data-hotkey="z"/>
</footer>
</form>
</field>