From 583cc5d4394f0ad9f7ede3cc94112c441fa80cc6 Mon Sep 17 00:00:00 2001 From: std-odoo Date: Thu, 1 Jul 2021 11:52:58 +0000 Subject: [PATCH] [REM] website_mail_channel: remove the module "website_mail_channel" Rationale ========= Currently, mail channels have 2 modes - They can be used like Discuss channel (chat, livechat, group) - They can be used like a Mailing List (with the "email_send" field) The mix of both feature in the same model cause some code complexity. Several fields are not used in both cases (moderation related field) and the future "Discord like" Discuss will even push the mail channel further than the usage of the mailing list. Because of all those reasons, we want to split the 2 mains features of the mail channels into 2 different modules and models. Purpose ======= Remove the module "website_mail_channel" because we will merge it into a new one, "mail_group" and "website_mail_group". This new module "website_mail_group" will contains the website snippets but this snippets will only work the the new model and not with like before. Links ===== Task-2510267 See odoo/odoo/pull/71599 See odoo/enterprise/pull/19296 See odoo/upgrade/pull/2600 --- addons/website_mail_channel/__init__.py | 4 - addons/website_mail_channel/__manifest__.py | 26 -- .../controllers/__init__.py | 3 - .../website_mail_channel/controllers/main.py | 279 -------------- .../data/mail_template_data.xml | 46 --- .../website_mail_channel/models/__init__.py | 5 - .../models/mail_channel.py | 63 ---- .../website_mail_channel/models/mail_mail.py | 34 -- addons/website_mail_channel/models/website.py | 14 - .../static/description/icon.png | Bin 7319 -> 0 bytes .../static/description/icon.svg | 1 - .../static/src/css/website_mail_channel.css | 7 - .../static/src/js/website_mail_channel.js | 71 ---- .../static/src/snippets/s_channel/000.js | 148 -------- .../static/src/snippets/s_channel/options.js | 102 ------ addons/website_mail_channel/tests/__init__.py | 2 - .../tests/test_unsubscribe.py | 60 --- .../views/snippets/s_channel.xml | 47 --- .../views/snippets/snippets.xml | 14 - .../views/website_mail_channel_templates.xml | 345 ------------------ 20 files changed, 1271 deletions(-) delete mode 100644 addons/website_mail_channel/__init__.py delete mode 100644 addons/website_mail_channel/__manifest__.py delete mode 100644 addons/website_mail_channel/controllers/__init__.py delete mode 100644 addons/website_mail_channel/controllers/main.py delete mode 100644 addons/website_mail_channel/data/mail_template_data.xml delete mode 100644 addons/website_mail_channel/models/__init__.py delete mode 100644 addons/website_mail_channel/models/mail_channel.py delete mode 100644 addons/website_mail_channel/models/mail_mail.py delete mode 100644 addons/website_mail_channel/models/website.py delete mode 100644 addons/website_mail_channel/static/description/icon.png delete mode 100644 addons/website_mail_channel/static/description/icon.svg delete mode 100644 addons/website_mail_channel/static/src/css/website_mail_channel.css delete mode 100644 addons/website_mail_channel/static/src/js/website_mail_channel.js delete mode 100644 addons/website_mail_channel/static/src/snippets/s_channel/000.js delete mode 100644 addons/website_mail_channel/static/src/snippets/s_channel/options.js delete mode 100644 addons/website_mail_channel/tests/__init__.py delete mode 100644 addons/website_mail_channel/tests/test_unsubscribe.py delete mode 100644 addons/website_mail_channel/views/snippets/s_channel.xml delete mode 100644 addons/website_mail_channel/views/snippets/snippets.xml delete mode 100644 addons/website_mail_channel/views/website_mail_channel_templates.xml diff --git a/addons/website_mail_channel/__init__.py b/addons/website_mail_channel/__init__.py deleted file mode 100644 index bb0aae7ee63..00000000000 --- a/addons/website_mail_channel/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import controllers -from . import models diff --git a/addons/website_mail_channel/__manifest__.py b/addons/website_mail_channel/__manifest__.py deleted file mode 100644 index 76f45a70f08..00000000000 --- a/addons/website_mail_channel/__manifest__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. -{ - 'name': 'Website Mail Channels', - 'category': 'Website/Website', - 'summary': 'Allow visitors to join public mail channels', - 'description': """ -Visitors can join public mail channels managed in the Discuss app in order to get regular updates or reach out with your community. - """, - 'depends': ['website_mail'], - 'data': [ - 'data/mail_template_data.xml', - 'views/snippets/s_channel.xml', - 'views/snippets/snippets.xml', - 'views/website_mail_channel_templates.xml', - ], - 'assets': { - 'web.assets_frontend': [ - 'website_mail_channel/static/src/css/website_mail_channel.css', - 'website_mail_channel/static/src/js/website_mail_channel.js', - ], - 'website.assets_wysiwyg': [ - 'website_mail_channel/static/src/snippets/s_channel/options.js', - ], - } -} diff --git a/addons/website_mail_channel/controllers/__init__.py b/addons/website_mail_channel/controllers/__init__.py deleted file mode 100644 index 7fc0cd7cb93..00000000000 --- a/addons/website_mail_channel/controllers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import main diff --git a/addons/website_mail_channel/controllers/main.py b/addons/website_mail_channel/controllers/main.py deleted file mode 100644 index 0237ef4dc1d..00000000000 --- a/addons/website_mail_channel/controllers/main.py +++ /dev/null @@ -1,279 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -import werkzeug - -from datetime import datetime -from dateutil import relativedelta - -from odoo import http, fields, tools, _ -from odoo.http import request -from odoo.addons.http_routing.models.ir_http import slug - - -class MailGroup(http.Controller): - _thread_per_page = 20 - _replies_per_page = 10 - - def _get_archives(self, group_id): - MailMessage = request.env['mail.message'] - # use sudo to avoid side-effects due to custom ACLs - groups = MailMessage.sudo()._read_group_raw( - [('model', '=', 'mail.channel'), ('res_id', '=', group_id), ('message_type', '!=', 'notification')], - ['subject', 'date'], - groupby=["date"], orderby="date desc") - for group in groups: - (r, label) = group['date'] - start, end = r.split('/') - group['date'] = label - group['date_begin'] = self._to_date(start) - group['date_end'] = self._to_date(end) - return groups - - def _to_date(self, dt): - """ date is (of course) a datetime so start and end are datetime - strings, but we just want date strings - """ - return (datetime - .strptime(dt, tools.DEFAULT_SERVER_DATETIME_FORMAT) - .date() # may be unnecessary? - .strftime(tools.DEFAULT_SERVER_DATE_FORMAT)) - - @http.route("/groups", type='http', auth="public", website=True, sitemap=True) - def view(self, **post): - groups = request.env['mail.channel'].search([('alias_id.alias_name', '!=', False)]) - - # compute statistics - month_date = datetime.today() - relativedelta.relativedelta(months=1) - # use sudo to avoid side-effects due to custom ACLs - messages = request.env['mail.message'].sudo().read_group([ - ('model', '=', 'mail.channel'), - ('date', '>=', fields.Datetime.to_string(month_date)), - ('message_type', '!=', 'notification'), - ('res_id', 'in', groups.ids), - ], ['res_id'], ['res_id']) - message_data = dict((message['res_id'], message['res_id_count']) for message in messages) - - group_data = dict( - (group.id, {'monthly_message_nbr': message_data.get(group.id, 0), - 'members_count': len(group.channel_partner_ids)}) - for group in groups.sudo()) - return request.render('website_mail_channel.mail_channels', {'groups': groups, 'group_data': group_data}) - - @http.route(["/groups/is_member"], type='json', auth="public", website=True) - def is_member(self, channel_id=0, **kw): - """ Determine if the current user is member of the given channel_id - :param channel_id : the channel_id to check - """ - current_user = request.env.user - session_partner_id = request.session.get('partner_id') - public_user = request.website.user_id - partner = None - # find the current partner - if current_user != public_user: - partner = current_user.partner_id - elif session_partner_id: - partner = request.env['res.partner'].sudo().browse(session_partner_id) - - values = { - 'is_user': current_user != public_user, - 'email': partner.email if partner else "", - 'is_member': False, - 'alias_name': False, - } - # check if the current partner is member or not - channel = request.env['mail.channel'].browse(int(channel_id)) - if channel.exists() and partner is not None: - values['is_member'] = bool(partner in channel.sudo().channel_partner_ids) - return values - - @http.route(["/groups/subscription"], type='json', auth="public", website=True) - def subscription(self, channel_id=0, subscription="on", email='', **kw): - """ Subscribe to a mailing list : this will create a partner with its email address (if public user not - registered yet) and add it as channel member - :param channel_id : the channel id to join/quit - :param subscription : 'on' to unsubscribe the user, 'off' to subscribe - """ - unsubscribe = subscription == 'on' - channel = request.env['mail.channel'].browse(int(channel_id)) - if not channel.exists(): - return False - - partner_ids = [] - - # search partner_id - if request.env.user != request.website.user_id: - # connected users are directly (un)subscribed - partner_ids = request.env.user.partner_id.ids - - # add or remove channel members - if unsubscribe: - channel.check_access_rule('read') - channel.sudo().write({'channel_partner_ids': [(3, partner_id) for partner_id in partner_ids]}) - return "off" - else: # add partner to the channel - request.session['partner_id'] = partner_ids[0] - channel.check_access_rule('read') - channel.sudo().write({'channel_partner_ids': [(4, partner_id) for partner_id in partner_ids]}) - return "on" - - else: - # public users will recieve confirmation email - partner_ids = [p.id for p in request.env['mail.thread'].sudo()._mail_find_partner_from_emails([email], records=channel.sudo()) if p] - if not partner_ids or not partner_ids[0]: - name = email.split('@')[0] - partner_ids = [request.env['res.partner'].sudo().create({'name': name, 'email': email}).id] - - channel.sudo()._send_confirmation_email(partner_ids, unsubscribe) - return "email" - - @http.route([ - '''/groups/''', - '''/groups//page/''' - ], type='http', auth="public", website=True, sitemap=True) - def thread_headers(self, group, page=1, mode='thread', date_begin=None, date_end=None, **post): - if group.channel_type != 'channel': - raise werkzeug.exceptions.NotFound() - - Message = request.env['mail.message'] - - domain = [('model', '=', 'mail.channel'), ('res_id', '=', group.id), ('message_type', '!=', 'notification')] - if mode == 'thread': - domain += [('parent_id', '=', False)] - if date_begin and date_end: - domain += [('date', '>=', date_begin), ('date', '<=', date_end)] - - pager = request.website.pager( - url='/groups/%s' % slug(group), - total=Message.search_count(domain), - page=page, - step=self._thread_per_page, - url_args={'mode': mode, 'date_begin': date_begin or '', 'date_end': date_end or ''}, - ) - messages = Message.search(domain, limit=self._thread_per_page, offset=pager['offset']) - values = { - 'messages': messages, - 'group': group, - 'pager': pager, - 'mode': mode, - 'archives': self._get_archives(group.id), - 'date_begin': date_begin, - 'date_end': date_end, - 'replies_per_page': self._replies_per_page, - } - return request.render('website_mail_channel.group_messages', values) - - @http.route([ - '''/groups//', message.date)], order="date", limit=1) or None - - # handle access to attachments for public / portal - if request.env.user.has_group('base.group_user'): - attachments = message.attachment_ids - else: - # portal / external people cannot access attachments -> grant access - # as message is ok, generate access tokens - attachments = message.sudo().attachment_ids - attachments.generate_access_token() - - values = { - 'message': message, - 'attachments': attachments, - 'group': group, - 'mode': mode, - 'archives': self._get_archives(group.id), - 'date_begin': date_begin, - 'date_end': date_end, - 'replies_per_page': self._replies_per_page, - 'next_message': next_message, - 'prev_message': prev_message, - } - return request.render('website_mail_channel.group_message', values) - - @http.route( - '''/groups///get_alias_info", type='json', auth='public', website=True) - def get_alias_info(self, group_id, **post): - group = request.env['mail.channel'].search([('id', '=', group_id)]) - if not group: # doesn't exist or doesn't have the right to access it - return {} - - return { - 'alias_name': group.alias_id and group.alias_id.alias_name and group.alias_id.alias_domain and '%s@%s' % (group.alias_id.alias_name, group.alias_id.alias_domain) or False - } - - @http.route("/groups/subscribe///", type='http', auth='public', website=True) - def confirm_subscribe(self, channel, partner_id, token, **kw): - subscriber = request.env['mail.channel.partner'].search([('channel_id', '=', channel.id), ('partner_id', '=', partner_id)]) - if subscriber: - # already registered, maybe clicked twice - return request.render('website_mail_channel.invalid_token_subscription') - - subscriber_token = channel._generate_action_token(partner_id, action='subscribe') - if token != subscriber_token: - return request.render('website_mail_channel.invalid_token_subscription') - - # add partner - channel.sudo().write({'channel_partner_ids': [(4, partner_id)]}) - - return request.render("website_mail_channel.confirmation_subscription", {'subscribing': True}) - - @http.route("/groups/unsubscribe///", type='http', auth='public', website=True) - def confirm_unsubscribe(self, channel, partner_id, token, **kw): - subscriber = request.env['mail.channel.partner'].search([('channel_id', '=', channel.id), ('partner_id', '=', partner_id)]) - if not subscriber: - partner = request.env['res.partner'].browse(partner_id).sudo().exists() - # FIXME: remove try/except in master - try: - response = request.render( - 'website_mail_channel.not_subscribed', - {'partner_id': partner}) - # make sure the rendering (and thus error if template is - # missing) happens inside the try block - response.flatten() - return response - except ValueError: - return _("The address %s is already unsubscribed or was never subscribed to any mailing list") % ( - partner.email - ) - - subscriber_token = channel._generate_action_token(partner_id, action='unsubscribe') - if token != subscriber_token: - return request.render('website_mail_channel.invalid_token_subscription') - - # remove partner - channel.sudo().write({'channel_partner_ids': [(3, partner_id)]}) - - return request.render("website_mail_channel.confirmation_subscription", {'subscribing': False}) diff --git a/addons/website_mail_channel/data/mail_template_data.xml b/addons/website_mail_channel/data/mail_template_data.xml deleted file mode 100644 index 88fc73cb9f6..00000000000 --- a/addons/website_mail_channel/data/mail_template_data.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - Channel: Mailing list subscription - - Confirm subscription to ${object.name} - -
- Hello,

- You have requested to be subscribed to the mailing list ${object.name}. -

- To confirm, please visit the following link: ${ctx['token_url']} -

- If this was a mistake or you did not requested this action, please ignore this message. - % if user.signature -
- ${user.signature | safe} - % endif -
- -
- - - Channel: Mailing list unsubscription - - Confirm unsubscription to ${object.name} - -
- Hello,

- You have requested to be unsubscribed to the mailing list ${object.name}. -

- To confirm, please visit the following link: ${ctx['token_url']}. -

- If this was a mistake or you did not requested this action, please ignore this message. - % if user.signature: -
- ${user.signature | safe} - % endif -
- -
-
- -
diff --git a/addons/website_mail_channel/models/__init__.py b/addons/website_mail_channel/models/__init__.py deleted file mode 100644 index f5c2bbb5e3c..00000000000 --- a/addons/website_mail_channel/models/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import mail_channel -from . import mail_mail -from . import website diff --git a/addons/website_mail_channel/models/mail_channel.py b/addons/website_mail_channel/models/mail_channel.py deleted file mode 100644 index 3cae5bd50c8..00000000000 --- a/addons/website_mail_channel/models/mail_channel.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from werkzeug import urls - -from odoo import models, tools -from odoo.addons.http_routing.models.ir_http import slug - - -class MailGroup(models.Model): - _inherit = 'mail.channel' - - def _notify_email_header_dict(self): - headers = super(MailGroup, self)._notify_email_header_dict() - base_url = self.get_base_url() - headers['List-Archive'] = '<%s/groups/%s>' % (base_url, slug(self)) - headers['List-Subscribe'] = '<%s/groups>' % (base_url) - headers['List-Unsubscribe'] = '<%s/groups?unsubscribe>' % (base_url,) - return headers - - def _send_confirmation_email(self, partner_ids, unsubscribe=False): - website = self.env['website'].get_current_website() - base_url = website.get_base_url() - - route = "/groups/%(action)s/%(channel)s/%(partner)s/%(token)s" - if unsubscribe: - template = self.env.ref('website_mail_channel.mail_template_list_unsubscribe') - action = 'unsubscribe' - else: - template = self.env.ref('website_mail_channel.mail_template_list_subscribe') - action = 'subscribe' - - for partner_id in partner_ids: - # generate a new token per subscriber - token = self._generate_action_token(partner_id, action=action) - - token_url = urls.url_join(base_url, route % { - 'action': action, - 'channel': self.id, - 'partner': partner_id, - 'token': token, - }) - template.with_context(token_url=token_url).send_mail( - self.id, - force_send=True, - email_values={ - 'recipient_ids': [(4, partner_id)], - 'email_from': website.company_id.email_formatted, - 'author_id': self.create_uid.partner_id.id, - 'message_type': 'user_notification', - }, - notif_layout='mail.mail_notification_light', - ) - - return True - - def _generate_action_token(self, partner_id, action='unsubscribe'): - self.ensure_one() - data = '$'.join([ - str(self.id), - str(partner_id), - action]) - return tools.hmac(self.env(su=True), 'website_mail_channel-email-subscription', data) diff --git a/addons/website_mail_channel/models/mail_mail.py b/addons/website_mail_channel/models/mail_mail.py deleted file mode 100644 index b8a157a133a..00000000000 --- a/addons/website_mail_channel/models/mail_mail.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import api, models, tools, _ -from odoo.addons.http_routing.models.ir_http import slug - - -class MailMail(models.Model): - _inherit = 'mail.mail' - - def _send_prepare_body(self): - """ Short-circuit parent method for mail groups, replace the default - footer with one appropriate for mailing-lists.""" - if self.model == 'mail.channel' and self.res_id: - # no super() call on purpose, no private links that could be quoted! - channel = self.env['mail.channel'].browse(self.res_id) - base_url = channel.get_base_url() - vals = { - 'maillist': _('Mailing-List'), - 'post_to': _('Post to'), - 'unsub': _('Unsubscribe'), - 'mailto': 'mailto:%s@%s' % (channel.alias_name, channel.alias_domain), - 'group_url': '%s/groups/%s' % (base_url, slug(channel)), - 'unsub_url': '%s/groups?unsubscribe' % (base_url,), - } - footer = """_______________________________________________ - %(maillist)s: %(group_url)s - %(post_to)s: %(mailto)s - %(unsub)s: %(unsub_url)s - """ % vals - body = tools.append_content_to_html(self.body, footer, container_tag='div') - return body - else: - return super(MailMail, self)._send_prepare_body() diff --git a/addons/website_mail_channel/models/website.py b/addons/website_mail_channel/models/website.py deleted file mode 100644 index 854e99bdbe8..00000000000 --- a/addons/website_mail_channel/models/website.py +++ /dev/null @@ -1,14 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - -from odoo import models, _ -from odoo.addons.http_routing.models.ir_http import url_for - - -class Website(models.Model): - _inherit = "website" - - def get_suggested_controllers(self): - suggested_controllers = super(Website, self).get_suggested_controllers() - suggested_controllers.append((_('Mailing Lists'), url_for('/groups'), 'website_mail_channel')) - return suggested_controllers diff --git a/addons/website_mail_channel/static/description/icon.png b/addons/website_mail_channel/static/description/icon.png deleted file mode 100644 index 2c737fbe1d4f543240d4ac80b6443c45e39d92af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7319 zcmX9@cQ{+`+c#>K5~C&5Zk4LlP&8u2su8PIO6-x^vqo%!+M{;kt5vB@X_cxKVg)7C zE;VYzti9j#_nzxI=lSD&p6j0Hem?ho;tljQ8R>!aWMpKF+FDQ}(wg}1rllr5tJ+i` zWMtfMZK#S#0C_={Ox{fo=FYH#$vLW5bn;|U<8AU}_V(P7u4*&0@il_hbX9;Y;V1ARZ(rm)4#l(#paQ#3y2nvcQxZ55a@Sz$XlS&yrL@@XO~S&kNzuQY-x z7nVbl>ydmSj?IJSIve>&+=cZb$T%rU!VhkrV&Aw_w9v7;4drv;53 zFGbJI8^(niD0ynWF8}CvnzDNcm_N8RiVa!G=@|X>_Hz0KUlv8@E7!7QDtFq5?aAj9 z9W@<&_-vZed1KS>Umm}Zus*Tk<}>R!w+%>7?QgNqiS6!w)AAwVvpV!xuC6lM5B{Wb ztWBS6b}|fjO7k-%rF*LOQUz7mY`xUwf|Gx}#ZjZg?uMLg#?>h3Q5M|&i;Dn-=)Jwi zaICL}O~sL!6`D|NpuN_@6at@rq*-`ODddpz{SGoVD10wNj*S)Fk<>ksCNOb;gkvXd(#bl$eR~S9$R$IxsI)MR%_!$=w zG7bWhS-Bs6K2lDFE_9xBT^7m+_OXH(C+;foW<;@vo(P2=T`aV&H9*kSN-s|>PirPh zYJF4;x+Pw?8wg5yJ8T2=&)ySfLcd_#m44gqxJK%J6XKmH^7DNN09#xWbMD@?Ucftka9m&XB2c`1A3C z`9CAHFgf31jgNHE^)sg(yTG6g{?J_4i%oAX`r_xD)M@qT75iA(>J>1#|a3S8e)UP>f7%*>h2QO?Wu?)XXL((IFSaj~yDux|e1BA4Sqy zHB_WiSr*(4>bKNJ-((OW*FC3@ZhfRW)eaeXF0fR5XlPr6Q|+(3g9*@N|K_kzaGdtR zYa8^rJLR(fA_Uo@U+vue&mT$rIY1ZF~#A$7L$S9l#eFZ_94nol#*w_hjX{d=Gt&cX^$++b-F>qni9%IbCX$Ih1c= zC$aZ%SYmSo5{tBcyrKD{tF==1WIvD>L_EVBqG;1BWL`+e)N{99KE;F(uhSnp@*=)BJcS-4s&x!a)<9PC_fnZ!iJ?KH{y2GFg;oWU7|F& z%amf+K>|L<{--7Pn*SHIUn*vDitv@4+UeG6=y+w-!TkVWAkZZT@s1;y;XFf{v<=sa zWzMX5u_m?t@0F`I2ngmY?*6!dSVEX9!R^NE*#3h4f-dB`L6PWcX$JJK&9_v(T#bh~ zr6iFrYJNugP5A%6bYmPG9UV)$@te|Fje7j6oy^$P!nXv=x2s|AwK#*5hbB*cO}k|z zrf?56n40DlZaol$5njVL4myR-&Fg*F#l(;svrm=~(KgYmlI1-0NU)wMB!Q}nO+R!O zer`T0>vrQ0uxyu&f|D4N zIoJH{6R70qsXeFqj~2(@WoYzV{e zQN_N`s3!E9EyYNqE;YVPRFrlswmdbi)9_Zj0;&{>#z`eYQdE?lNl?KEX+zfVlIv;f zazCdW@cLbloVF$`4xS-sKEFqlP_PE@np+ znVJ4*4L}4YZrSqG5jF?M5A@!99)BNK>lr_4fF!u;xTx=t42#pvp8yTR!u103bZf&o z*JLN|i&tL)~${GHJ%N!h+mm#%`aNXMY%x8>0T133mVCptJf`zA6S9>5?VwT^sw-e-0X@NJS zl3ToV1M}o_Z}=|zNW-F5KWcCv%?r_<gg9;uSGDp-Navgv19tX-fQQDL_u5d*%*juS-1mDzAEz{`lJ6;G5nb!PF;VXK z_s$i@l{pv+u&9mFA0+&7NpV&MajbW9u4KLXFJ~YSUPuZBSsF(KxIiEIeEq}oi0Q$< z^4$sZBgFhiW=z4BKH|t+7o44k;0e}sh)9SNi6@RfBF{)v-vbT8`zv&5jJm*_he+&K z*~FCt1UI%PJ|i%MH4l@UzX^3Jx>di1#AdchqQ@~_3~HtUEY-z~MGy}{gRg(q4+FAi zcCv7qGx#eANya+XgHOf}J$`_IMgyvgi21bd0sXQfBlU+RHIm~GXxg$t$&G5J0Z@uTM7@IlT?$&hbVD6)*c-o?iNa- zABI~$=!xhmiGjnKpcSP?MqGWeO zrqiWQ6vdCo7G%PS5-Z&tbIf$W)i6N;h81(qB*C@$vkh0_rt9*wrM0xi*riWq7GKVa zGR;<5$rOa(wPgL}&CHeN0q0ZK<(vUuCLF$jww;%8x zEy`8S?jMrtkG1mQUe-M^_tZxGruuC;05;~}%75~#J?WL@g0vwqcN*Df5xXEpV)hS7 zTL$w#u!e(_8rq0K;U^wBLuU+8|5Ffqmsbf*9DS75y>(3Yw8tO7%d#tuK;!OpfCD-w zK_BL|EDKRMMsocD=OAcwXbAAf0b+?qBiOi)W!YJv-e?dR$AgtTHHSng@3oJvN9J&KLo z2k4_M5a}%0S5n0@~P9f0%>6RGQ?O z%(+*DZG`?bi!U8EoZLD2r=YXhl5pd%9!DYDF&>hw0(eII5DxK{81?Up&I1@W9q9*X zRGcIy9${5BA)dydCMdVwTrzrrrX^&)nnesIKJ*~$iJe$J{n(J-L*Mn^QvNgd%=jjW6I&IcasY^%dVDVIzFVvC>7L0Hp?=P|>N(lU zc{WwIxr`w57YfRj2v5m41HO5`Rt&o_OHZiEU~OvSWEDBhU8s=xKC*6l*-7p*(Lx76 zKJr%koY*^VGp&AffgS~*5<&5A@@gj2&M5I4sk%M%d_dX=V}fYsXMae_B<%b4(^lcM zeWQ!W5r6WBb(=Nv(S3dd5~+3!8>)ZYsU#v#q-JBPTa~#)kE0X3@~cw36MT~A z<_hhu1((9pQ55g zD5PG>=PJ7ePo+J7RrvOI%%@(S=2y#`TAyEi-99RQEsciWEOH1t4(98e~PK{!u{{#9K}dB z%A*kX?Q8yPc+t#*a+F#@6kNP@fduft%TxRL31f>N zKOVa=O&QD`b`8Jm()XgU?Q+qSmYPC(Q2^>Tp`w6y>><=(ZYX59?26&lPsCY9$zL{@ zGikyDA^2sY1XF8x-uA8XK<-*q0S@>I(C#1G3T+iK#(qRQQX-cDa*Jqf$?R&F@JtGz zU)tn~Ol0KVGlTgOa8jJ)zA798pZf9Wq{)ul;_nESggY84jQeA2--f|^>p1C`WZ+XV z0F;*(TwO;9RwtCv`MI!}q5spoj@8VU-N9W`>*XfgW#Xp*+sZ-Bu8!Uu64>zf^{VVy zU)7nsCkqv~wz_N5u)lSzX8Wgi#uK*Na;9t+o~caY-#YJ!71*^Am{I)1aq02Mm=V5OxA0n|5`6xB)~m-;bLS6j+qIP1EOXQpUTCP_23Ru$02MlzH6qR!6;)-!YtLL0 zE(YZQE&B)Cx8~G$td#hyso3PMch&uHu+R+v0&Jkl56OyVl!9NoHv^No!sL-_M5b3t zF`f8jfph~}YA-Oy!gi-$9ym!dv3HN3o`-WvF#3Eos9>*WbLT^KN>vl9UDN9Ya6?Z} zeB`osi>lD)CU83&PN{~=gB4C>{vfX9%zh>Qkz0yfzcy1q0B&_a{D17Dx zC5T7w+cH8r{+@WiDdZSv!3+0(h%0%pfNS~)`)3IN^*2W2j#~qG;IAt6IP#bR$yoIY z)j}d#0Bz(n(AT0Cq^O zyMJ0LbPvq)Z6ST`-etHn)+=Z2{yJWMp0an>JreNhUZlYSA@yH~l$Rt;3=GMBkM|l2UE-gA z;I+hFCMeu;dH!SX0t~+o$1diJ*9?h1r)9w2XzHK8ztaszy>S7O;n;}R0gTaJadq0^oG`&V z-&OJIt$eq@dM;&L`M1NE1$OWCRT~}XL^_rA`G|#Fd2m=-!fdjVmj+~Oxv9S|$^Id= zUp@+^U+8SiH#aQyK)rB7_L+oJP}PgGwZR^IO&8bjwg~O@fnkLTrFV4k&PgVatbh(N zp{M6d-itSk(Ha~Y`A+<=Txa({ld3mJ-HfM#hG97_G?;a%H-Ap@kPDB98Mm9VROuu&n-p;efXCvI!peq>vOhoMN` zh-l&5-cc40xO;(K8p~)N@aX%OQ8SD(Yx6R&#TH1?$uaN`+p~AEkJgUZ>cuM9d6Sv# zw$2m*4BI~ffFiK~>HFKiIsYN`w9gdDXU;EN4uj2Qo~1NdKNTUt%J2L9EA58on6M3! z322k7uX7pj5Oy<#3$#Y`A_r?J`Sad0MeUM@%cN0-u8RAq^mZUHq>*@JuRuLpsD?Gz zRpuz~j%|;8+7}Az#1+WH)L`1a#lwFykHATdGl#(=v|K>;;kExb$*|^QjI?!pwJ$|T zEYt_Bp{osiWf``-pa^>}K_W)FM@F5*Wi2%hr)6iw^{A(Pahp|h8606f-~r>aLY#U~ zrH{{==7(Q)<<_fq}q6fjLQ#7b|`a18%Dv%oXOHK(i2 z5lU5ZT#bfUgy{Wyif2XLw+uT%{--ksZZ`cZMF23)BXDH97u-CO=4$cu0kA{LGpYFr zG?(Qlcw~uG=dS68IcpfU1*35Z(nsq@FfJ{E+~C7^UQhk{Lhh}MEzu9Fw+i3-SM0w= zW(~$JD#8}|Z>Yd7o6@sq05{vrcdv;#0t}-kss#?cJ3lX68kXOc7xu!Ej_gC$av{0* z1}T$c-+$kazySXCDEq?S>Be>GEk76h8J@#Ff}j$E>*dm<@+kBjF?AB${wD^UdY!M6 zq|PEKNN2*PKKrBNY^54@au8Y=Hq%fe5hm2Ju-w@f*SLTvD9$eEUt@T!|NMS9X18jN zm3{jl<71P-wQ^|eLCO-|8mTTsCYM$xIce`608GPbp?+uyb@{#NAjDPQ&%n@KMT>O; z0oJ-17@PUmyJruI9Mpb*lU>lb-1M2YFU#$WF>ullA@PQ(oxPCwtfw&=6<-h)VAZ*AVvfeyQXQU?JKf#$ zuSH!-j)GCYjNJ<{rF765b6*ar7AcsTAR7o`7=%Xg_wr2c72o-7;8~pKWRnMejZ7ON zL_a5U!LiVqkxwxL9sl!K-%4Z2%VM8 z&rh z9YvtatvwLSCu^HZXNup-24&R()EN*ZA2doH+rb$w`+s&(Z50r1{Up8x;= diff --git a/addons/website_mail_channel/static/description/icon.svg b/addons/website_mail_channel/static/description/icon.svg deleted file mode 100644 index 779be8054e2..00000000000 --- a/addons/website_mail_channel/static/description/icon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/addons/website_mail_channel/static/src/css/website_mail_channel.css b/addons/website_mail_channel/static/src/css/website_mail_channel.css deleted file mode 100644 index 2365860f8fb..00000000000 --- a/addons/website_mail_channel/static/src/css/website_mail_channel.css +++ /dev/null @@ -1,7 +0,0 @@ -.o_mg_link_show { - display: none; -} - -.o_mg_link_content { - display: none; -} diff --git a/addons/website_mail_channel/static/src/js/website_mail_channel.js b/addons/website_mail_channel/static/src/js/website_mail_channel.js deleted file mode 100644 index 30928d781dc..00000000000 --- a/addons/website_mail_channel/static/src/js/website_mail_channel.js +++ /dev/null @@ -1,71 +0,0 @@ -odoo.define('website_mail_channel', function (require) { -'use strict'; - -var publicWidget = require('web.public.widget'); - -publicWidget.registry.websiteMailChannel = publicWidget.Widget.extend({ - selector: '#wrapwrap', - events: { - 'click .o_mg_link_hide': '_onHideLinkClick', - 'click .o_mg_link_show': '_onShowLinkClick', - 'click button.o_mg_read_more': '_onReadMoreClick', - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - * @param {Event} ev - */ - _onHideLinkClick: function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - var $link = $(ev.currentTarget); - var $container = $link.parents('div').first(); - $container.find('.o_mg_link_hide').first().hide(); - $container.find('.o_mg_link_show').first().show(); - $container.find('.o_mg_link_content').first().show(); - }, - /** - * @private - * @param {Event} ev - */ - _onShowLinkClick: function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - var $link = $(ev.currentTarget); - var $container = $link.parents('div').first(); - $container.find('.o_mg_link_hide').first().show(); - $container.find('.o_mg_link_show').first().hide(); - $container.find('.o_mg_link_content').first().hide(); - }, - /** - * @private - * @param {Event} ev - */ - _onReadMoreClick: function (ev) { - var $link = $(ev.target); - this._rpc({ - route: $link.data('href'), - params: { - last_displayed_id: $link.data('msg-id'), - }, - }).then(function (data) { - if (!data) { - return; - } - var $threadContainer = $link.parents('.o_mg_replies').first().find('ul.list-unstyled'); - if ($threadContainer) { - var $lastMsg = $threadContainer.find('li.media').last(); - $(data).find('li.media').insertAfter($lastMsg); - $(data).find('.o_mg_read_more').parent().appendTo($threadContainer); - } - var $showMore = $link.parent(); - $showMore.remove(); - return; - }); - }, -}); -}); diff --git a/addons/website_mail_channel/static/src/snippets/s_channel/000.js b/addons/website_mail_channel/static/src/snippets/s_channel/000.js deleted file mode 100644 index afcd22c638e..00000000000 --- a/addons/website_mail_channel/static/src/snippets/s_channel/000.js +++ /dev/null @@ -1,148 +0,0 @@ -odoo.define('website_mail_channel.s_channel', function (require) { -'use strict'; - -var publicWidget = require('web.public.widget'); - -publicWidget.registry.Channel = publicWidget.Widget.extend({ - selector: '.s_channel', - disabledInEditableMode: false, - read_events: { - 'click .js_follow_btn, .js_unfollow_btn': '_onFollowUnFollowBtnClick', - 'click .js_follow_btn': '_onFollowBtnClick', - }, - - /** - * @override - */ - start: function () { - var self = this; - this.is_user = false; - var unsubscribePage = window.location.search.slice(1).split('&').indexOf("unsubscribe") >= 0; - - var always = function (data) { - self.is_user = data.is_user; - self.email = data.email; - self.$target.find('.js_mg_link').attr('href', '/groups/' + self.$target.data('id')); - if (unsubscribePage && self.is_user) { - self.$target.find(".js_mg_follow_form").remove(); - } - self._toggleSubscription(data.is_member ? 'on' : 'off', data.email); - self.$target.removeClass('d-none'); - }; - - this._rpc({ - route: '/groups/is_member', - params: { - model: this.$target.data('object'), - channel_id: this.$target.data('id'), - get_alias_info: true, - }, - }).then(always).guardedCatch(always); - - // not if editable mode to allow designer to edit alert field - if (!this.editableMode) { - this.$('> .alert').addClass('d-none'); - this.$('> .input-group-append.d-none').removeClass('d-none'); - } - return this._super.apply(this, arguments); - }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * @private - */ - _getAliasInfo: function () { - var self = this; - if (! this.$target.data('id')) { - return Promise.resolve(); - } - return this._rpc({route: '/groups/' + this.$target.data('id') + '/get_alias_info'}).then(function (data) { - if (data.alias_name) { - self.$target.find('.js_mg_email').attr('href', 'mailto:' + data.alias_name); - self.$target.find('.js_mg_email').removeClass('d-none'); - } else { - self.$target.find('.js_mg_email').addClass('d-none'); - } - }); - }, - /** - * @private - */ - _toggleSubscription: function (follow, email) { - // .js_mg_follow_form contains subscribe form - // .js_mg_details contains send/archives/unsubscribe links - // .js_mg_confirmation contains message warning has been sent - var aliasDone = this._getAliasInfo(); - if (follow === "on") { - // user is connected and can unsubscribe - this.$target.find(".js_mg_follow_form").addClass('d-none'); - this.$target.find(".js_mg_details").removeClass('d-none'); - this.$target.find(".js_mg_confirmation").addClass('d-none'); - } else if (follow === "off") { - // user is connected and can subscribe - this.$target.find(".js_mg_follow_form").removeClass('d-none'); - this.$target.find(".js_mg_details").addClass('d-none'); - this.$target.find(".js_mg_confirmation").addClass('d-none'); - } else if (follow === "email") { - // a confirmation email has been sent - this.$target.find(".js_mg_follow_form").addClass('d-none'); - this.$target.find(".js_mg_details").addClass('d-none'); - this.$target.find(".js_mg_confirmation").removeClass('d-none'); - } else { - console.error("Unknown subscription action", follow); - } - this.$target.find('input.js_follow_email') - .val(email ? email : "") - .attr("disabled", follow === "on" || (email.length && this.is_user) ? "disabled" : false); - this.$target.attr("data-follow", follow); - return Promise.resolve(aliasDone); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - */ - _onFollowBtnClick: function (ev) { - if ($(ev.currentTarget).closest('.js_mg_follow_form').length) { - this.$('.js_follow_email').val($(ev.currentTarget).closest('.js_mg_follow_form').find('.js_follow_email').val()); - } - }, - /** - * @private - */ - _onFollowUnFollowBtnClick: function (ev) { - ev.preventDefault(); - var self = this; - var $email = this.$target.find(".js_follow_email"); - - if ($email.length && !$email.val().match(/.+@.+/)) { - this.$target.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid'); - return false; - } - this.$target.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid'); - - var subscriptionAction = this.$target.attr("data-follow") || "off"; - if (window.location.search.slice(1).split('&').indexOf("unsubscribe") >= 0) { - // force unsubscribe mode via URI /groups?unsubscribe - subscriptionAction = 'on'; - } - this._rpc({ - route: '/groups/subscription', - params: { - 'channel_id': +this.$target.data('id'), - 'object': this.$target.data('object'), - 'subscription': subscriptionAction, - 'email': $email.length ? $email.val() : false, - }, - }).then(function (follow) { - self._toggleSubscription(follow, self.email); - }); - }, -}); -}); diff --git a/addons/website_mail_channel/static/src/snippets/s_channel/options.js b/addons/website_mail_channel/static/src/snippets/s_channel/options.js deleted file mode 100644 index 858ba8715cd..00000000000 --- a/addons/website_mail_channel/static/src/snippets/s_channel/options.js +++ /dev/null @@ -1,102 +0,0 @@ -odoo.define('website_mail_channel.s_channel_options', function (require) { -'use strict'; - -var core = require('web.core'); -var options = require('web_editor.snippets.options'); -var wUtils = require('website.utils'); - -var _t = core._t; - -options.registry.Channel = options.Class.extend({ - /** - * @override - */ - async start() { - await this._super(...arguments); - this.publicChannels = await this._getPublicChannels(); - }, - /** - * @override - */ - cleanForSave: function () { - this.$target.addClass('d-none'); - }, - /** - * If we have already created channels => select the first one - * else => modal prompt (create a new channel) - * - * @override - */ - onBuilt() { - if (this.publicChannels.length) { - this.$target[0].dataset.id = this.publicChannels[0][0]; - } else { - const widget = this._requestUserValueWidgets('create_mail_channel_opt')[0]; - widget.$el.click(); - } - }, - - //-------------------------------------------------------------------------- - // Options - //-------------------------------------------------------------------------- - - /** - * Creates a new mail.channel through a modal prompt. - * - * @see this.selectClass for parameters - */ - createChannel: function (previewMode, widgetValue, params) { - var self = this; - return wUtils.prompt({ - id: "editor_new_mail_channel_subscribe", - window_title: _t("New Mail Channel"), - input: _t("Name"), - }).then(function (result) { - var name = result.val; - if (!name) { - return; - } - return self._rpc({ - model: 'mail.channel', - method: 'create', - args: [{ - name: name, - public: 'public', - }], - }).then(function (id) { - self.$target.attr("data-id", id); - return self._rerenderXML(); - }); - }); - }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * @override - */ - async _renderCustomXML(uiFragment) { - const channels = await this._getPublicChannels(); - const menuEl = uiFragment.querySelector('.select_discussion_list'); - for (const channel of channels) { - const el = document.createElement('we-button'); - el.dataset.selectDataAttribute = channel[0]; - el.textContent = channel[1]; - menuEl.appendChild(el); - } - }, - /** - * @private - * @return {Promise} - */ - _getPublicChannels() { - return this._rpc({ - model: 'mail.channel', - method: 'name_search', - args: ['', [['public', '=', 'public']]], - }); - }, -}); -}); diff --git a/addons/website_mail_channel/tests/__init__.py b/addons/website_mail_channel/tests/__init__.py deleted file mode 100644 index 2e3364d701d..00000000000 --- a/addons/website_mail_channel/tests/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -from . import test_unsubscribe diff --git a/addons/website_mail_channel/tests/test_unsubscribe.py b/addons/website_mail_channel/tests/test_unsubscribe.py deleted file mode 100644 index 8da7bb5b08b..00000000000 --- a/addons/website_mail_channel/tests/test_unsubscribe.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo.tests import common, tagged -from odoo.tools.misc import mute_logger, ustr - - -@tagged('-at_install', 'post_install') -class TestConfirmUnsubscribe(common.HttpCase): - def setUp(self): - super(TestConfirmUnsubscribe, self).setUp() - self.partner = self.env['res.partner'].create({ - 'name': 'Bob', - 'email': 'bob@bob.bob' - }) - self.mailing_list = self.env['mail.channel'].create({ - 'name': 'Test Mailing List', - 'public': 'public', - }) - self.token = self.mailing_list._generate_action_token(self.partner.id, action='unsubscribe') - - def test_not_subscribed(self): - """Test warning works""" - self._unsubscribe_check("The address %s is already unsubscribed" % self.partner.email) - - @mute_logger('odoo.addons.website.models.ir_ui_view') - def test_not_subscribed_no_template(self): - """ Test warning works on db without template (code update w/o module update) """ - self.env.ref('website_mail_channel.not_subscribed').unlink() - self.assertEqual( - self.env['ir.model.data'].search_count([ - ('module', '=', 'website_mail_channel'), - ('name', '=', 'not_subscribed'), - ]), 0, 'XID for template should have been deleted') - - self._unsubscribe_check("The address %s is already unsubscribed or was never subscribed to any mailing list" % self.partner.email) - - def test_wrong_token(self): - self.mailing_list.sudo().write({ - 'channel_partner_ids': [(4, self.partner.id, False)] - }) - self.token = 'XXX' - - self._unsubscribe_check("Invalid or expired confirmation link.") - - def test_successful_unsubscribe(self): - self.mailing_list.sudo().write({ - 'channel_partner_ids': [(4, self.partner.id, False)] - }) - - self._unsubscribe_check("You have been correctly unsubscribed") - - def _unsubscribe_check(self, text): - url = "/groups/unsubscribe/{}/{}/{}".format( - self.mailing_list.id, self.partner.id, - self.token - ) - r = self.url_open(url) - body = ustr(r.content) - # normalize space to make matching simpler - self.assertIn(text, u' '.join(body.split())) diff --git a/addons/website_mail_channel/views/snippets/s_channel.xml b/addons/website_mail_channel/views/snippets/s_channel.xml deleted file mode 100644 index 13d6d8723ec..00000000000 --- a/addons/website_mail_channel/views/snippets/s_channel.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - Channel 000 JS - web.assets_frontend - website_mail_channel/static/src/snippets/s_channel/000.js - - - diff --git a/addons/website_mail_channel/views/snippets/snippets.xml b/addons/website_mail_channel/views/snippets/snippets.xml deleted file mode 100644 index 6ea512167b1..00000000000 --- a/addons/website_mail_channel/views/snippets/snippets.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - diff --git a/addons/website_mail_channel/views/website_mail_channel_templates.xml b/addons/website_mail_channel/views/website_mail_channel_templates.xml deleted file mode 100644 index 6d6d103356c..00000000000 --- a/addons/website_mail_channel/views/website_mail_channel_templates.xml +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - - - - - - - - - - - - -