[IMP] website_slides: add invite wizard for 'invite' slide_channel
Purpose ======= Currently, the slide_channels having a visibility configured as 'invite' could only add members manually. This commit adds an 'Invite' button on top of the slide channel form that opens a wizard allowing to send emails to contacts and also make them members of the related slide channel.
This commit is contained in:
committed by
Thibault Delavallée
parent
779d9c9b90
commit
e5536fc07b
@@ -31,6 +31,7 @@ Share and Publish Videos, Presentations and Documents'
|
||||
'views/slide_channel_partner_views.xml',
|
||||
'views/slide_channel_views.xml',
|
||||
'views/slide_channel_tag_views.xml',
|
||||
'views/slide_channel_invite_views.xml',
|
||||
'views/website_slides_menu_views.xml',
|
||||
'data/website_slides_ir_data.xml',
|
||||
'data/mail_data.xml',
|
||||
|
||||
@@ -60,5 +60,29 @@
|
||||
<field name="default" eval="True"/>
|
||||
<field name="description">Presentation Published</field>
|
||||
</record>
|
||||
|
||||
<!-- Slide channel invite feature -->
|
||||
<record id="mail_template_slide_channel_invite" model="mail.template">
|
||||
<field name="name">Channel: Invite by email</field>
|
||||
<field name="model_id" ref="model_slide_channel_partner" />
|
||||
<field name="subject">You have been invited to join ${object.channel_id.name}</field>
|
||||
<field name="body_html" type="html">
|
||||
<div style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
<p style="margin: 0px; padding: 0px; font-size: 13px;">
|
||||
Dear ${object.partner_id.name or 'participant'}<br/><br/>
|
||||
You have been invited to join a new course: ${object.channel_id.name}.
|
||||
<div style="margin: 16px 0px 16px 0px;">
|
||||
<a href="${(object.channel_id.website_url) | safe}"
|
||||
style="background-color: #875A7B; padding: 8px 16px 8px 16px; text-decoration: none; color: #fff; border-radius: 5px; font-size:13px;">
|
||||
Click here to start the course.
|
||||
</a>
|
||||
</div>
|
||||
Enjoy this exclusive content !
|
||||
</p>
|
||||
</div>
|
||||
</field>
|
||||
<field name="auto_delete" eval="True"/>
|
||||
<field name="user_signature" eval="False"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -4,5 +4,6 @@ from . import gamification_challenge
|
||||
from . import slide_slide
|
||||
from . import slide_channel
|
||||
from . import slide_channel_tag
|
||||
from . import slide_channel_invite
|
||||
from . import res_config_settings
|
||||
from . import website
|
||||
|
||||
@@ -7,6 +7,7 @@ import uuid
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.addons.http_routing.models.ir_http import slug
|
||||
from odoo.tools.translate import html_translate
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
@@ -205,6 +206,31 @@ class Channel(models.Model):
|
||||
|
||||
return action
|
||||
|
||||
@api.multi
|
||||
def action_channel_invite(self):
|
||||
self.ensure_one()
|
||||
|
||||
if self.visibility != 'invite':
|
||||
raise UserError(_("You cannot send invitations for channels that are not set as 'invite'."))
|
||||
|
||||
template = self.env.ref('website_slides.mail_template_slide_channel_invite', raise_if_not_found=False)
|
||||
|
||||
local_context = dict(
|
||||
self.env.context,
|
||||
default_channel_id=self.id,
|
||||
default_use_template=bool(template),
|
||||
default_template_id=template and template.id or False,
|
||||
notif_layout='mail.mail_notification_light',
|
||||
)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'slide.channel.invite',
|
||||
'target': 'new',
|
||||
'context': local_context,
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# ORM Overrides
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from email.utils import formataddr
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
emails_split = re.compile(r"[;,\n\r]+")
|
||||
|
||||
|
||||
class SlideChannelInvite(models.TransientModel):
|
||||
_name = 'slide.channel.invite'
|
||||
_description = 'Channel Invitation Wizard'
|
||||
|
||||
@api.model
|
||||
def _default_email_from(self):
|
||||
if self.env.user.email:
|
||||
return formataddr((self.env.user.name, self.env.user.email))
|
||||
raise UserError(_("Unable to post message, please configure the sender's email address."))
|
||||
|
||||
@api.model
|
||||
def _default_author_id(self):
|
||||
return self.env.user.partner_id
|
||||
|
||||
# composer content
|
||||
subject = fields.Char('Subject')
|
||||
body = fields.Html('Contents', default='', sanitize_style=True)
|
||||
attachment_ids = fields.Many2many('ir.attachment', string='Attachments')
|
||||
template_id = fields.Many2one(
|
||||
'mail.template', 'Use template',
|
||||
domain="[('model', '=', 'slide.channel.partner')]")
|
||||
# origin
|
||||
email_from = fields.Char('From', default=_default_email_from)
|
||||
author_id = fields.Many2one(
|
||||
'res.partner', 'Author',
|
||||
ondelete='set null', default=_default_author_id)
|
||||
# recipients
|
||||
partner_ids = fields.Many2many('res.partner', string='Recipients')
|
||||
# slide channel
|
||||
channel_id = fields.Many2one('slide.channel', string='Slide channel', required=True)
|
||||
channel_url = fields.Char(related="channel_id.website_url", readonly=True)
|
||||
|
||||
@api.onchange('template_id')
|
||||
def _onchange_template_id(self):
|
||||
""" Make the 'subject' and 'body' field match the selected template_id """
|
||||
if self.template_id:
|
||||
self.subject = self.template_id.subject
|
||||
self.body = self.template_id.body_html
|
||||
|
||||
@api.onchange('partner_ids')
|
||||
def _onchange_partner_ids(self):
|
||||
if self.partner_ids:
|
||||
signup_allowed = self.env['res.users'].sudo()._get_signup_invitation_scope() == 'b2c'
|
||||
if not signup_allowed:
|
||||
invalid_partners = self.env['res.partner'].search([
|
||||
('user_ids', '=', False),
|
||||
('id', 'in', self.partner_ids.ids)
|
||||
])
|
||||
if invalid_partners:
|
||||
raise UserError(
|
||||
_('The following recipients have no user account: %s. You should create user accounts for them or allow external sign up in configuration.' %
|
||||
(','.join(invalid_partners.mapped('name')))))
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if values.get('template_id') and not (values.get('body') or values.get('subject')):
|
||||
template = self.env['mail.template'].browse(values['template_id'])
|
||||
if not values.get('subject'):
|
||||
values['subject'] = template.subject
|
||||
if not values.get('body'):
|
||||
values['body'] = template.body_html
|
||||
return super(SlideChannelInvite, self).create(values)
|
||||
|
||||
@api.multi
|
||||
def action_invite(self):
|
||||
""" Process the wizard content and proceed with sending the related
|
||||
email(s), rendering any template patterns on the fly if needed """
|
||||
self.ensure_one()
|
||||
|
||||
mail_values = []
|
||||
for partner_id in self.partner_ids:
|
||||
slide_channel_partner = self.channel_id._action_add_member(target_partner=partner_id)
|
||||
if slide_channel_partner:
|
||||
mail_values.append(self._prepare_mail_values(slide_channel_partner))
|
||||
|
||||
# TODO awa: change me to create multi when mail.mail supports it
|
||||
for mail_value in mail_values:
|
||||
self.env['mail.mail'].sudo().create(mail_value)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def _prepare_mail_values(self, slide_channel_partner):
|
||||
""" Create mail specific for recipient """
|
||||
subject = self.env['mail.template']._render_template(self.subject, 'slide.channel.partner', slide_channel_partner.id, post_process=True)
|
||||
body = self.env['mail.template']._render_template(self.body, 'slide.channel.partner', slide_channel_partner.id, post_process=True)
|
||||
# post the message
|
||||
mail_values = {
|
||||
'email_from': self.email_from,
|
||||
'author_id': self.author_id.id,
|
||||
'model': None,
|
||||
'res_id': None,
|
||||
'subject': subject,
|
||||
'body_html': body,
|
||||
'attachment_ids': [(4, att.id) for att in self.attachment_ids],
|
||||
'auto_delete': True,
|
||||
'recipient_ids': [(4, slide_channel_partner.partner_id.id)]
|
||||
}
|
||||
|
||||
# optional support of notif_layout in context
|
||||
notif_layout = self.env.context.get('notif_layout', self.env.context.get('custom_layout'))
|
||||
if notif_layout:
|
||||
try:
|
||||
template = self.env.ref(notif_layout, raise_if_not_found=True)
|
||||
except ValueError:
|
||||
_logger.warning('QWeb template %s not found when sending slide channel mails. Sending without layouting.' % (notif_layout))
|
||||
else:
|
||||
template_ctx = {
|
||||
'message': self.env['mail.message'].sudo().new(dict(body=mail_values['body_html'], record_name=self.channel_id.name)),
|
||||
'model_description': self.env['ir.model']._get('website_slides.slide_channel').display_name,
|
||||
'company': self.env.user.company_id,
|
||||
}
|
||||
body = template.render(template_ctx, engine='ir.qweb', minimal_qcontext=True)
|
||||
mail_values['body_html'] = self.env['mail.thread']._replace_local_links(body)
|
||||
|
||||
return mail_values
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="slide_channel_invite_view_form" model="ir.ui.view">
|
||||
<field name="name">slide.channel.invite.view.form</field>
|
||||
<field name="model">slide.channel.invite</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Compose Email">
|
||||
<group col="1">
|
||||
<group col="2">
|
||||
<field name="partner_ids"
|
||||
widget="many2many_tags_email"
|
||||
placeholder="Add existing contacts..."
|
||||
context="{'force_email':True, 'show_email':True, 'no_create_edit': True}"/>
|
||||
</group>
|
||||
<group col="2">
|
||||
<field name="subject" placeholder="Subject..."/>
|
||||
</group>
|
||||
<field name="body" options="{'style-inline': true}"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="attachment_ids" widget="many2many_binary"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="template_id" label="Use template"/>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
<button string="Send" name="action_invite" type="object" class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -47,6 +47,9 @@
|
||||
<field name="model">slide.channel</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Channels">
|
||||
<header>
|
||||
<button name="action_channel_invite" string="Invite" type="object" class="oe_highlight" attrs="{'invisible': [('visibility', '!=', 'invite')]}"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_redirect_to_members"
|
||||
|
||||
Reference in New Issue
Block a user