[MERGE] [CLEAN] website_mail: clean merging of trunk-archive (revid fp@tinyerp.com-20140316123800-bqbk34ixeiure75d) introducing Mailing List Archives. Featuring :

- uses already-existing template for subscription instead of copy-and-pasting the subscription button code;
- fixes several issues in the layout to ease the reading;
- fixes the broken pager;
- adds the Archives nav that was planned but not really usable

bzr revid: tde@openerp.com-20140326110042-tu9cdtca6sc2iv4r
This commit is contained in:
Thibault Delavallée 2014-03-26 12:00:42 +01:00
commit 158b6554c8
4 changed files with 94 additions and 87 deletions

View File

@ -126,7 +126,7 @@ class mail_group(osv.Model):
vals['menu_id'] = menu_id
# Create group and alias
create_context = dict(context, alias_model_name=self._name, alias_parent_model_name=self._name)
create_context = dict(context, alias_model_name=self._name, alias_parent_model_name=self._name, mail_create_nolog=True)
mail_group_id = super(mail_group, self).create(cr, uid, vals, context=create_context)
group = self.browse(cr, uid, mail_group_id, context=context)
self.pool.get('mail.alias').write(cr, uid, [group.alias_id.id], {"alias_force_thread_id": mail_group_id, 'alias_parent_thread_id': mail_group_id}, context)

View File

@ -19,6 +19,7 @@
#
##############################################################################
from openerp.tools import html2plaintext
from openerp.tools.translate import _
from openerp.osv import osv, fields
@ -26,7 +27,21 @@ from openerp.osv import osv, fields
class MailMessage(osv.Model):
_inherit = 'mail.message'
def _get_description_short(self, cr, uid, ids, name, arg, context=None):
res = dict.fromkeys(ids, False)
for message in self.browse(cr, uid, ids, context=context):
if message.subject:
res[message.id] = message.subject
else:
plaintext_ct = html2plaintext(message.body)
res[message.id] = plaintext_ct + '%s' % (' [...]' if len(plaintext_ct) >= 20 else '')
return res
_columns = {
'description': fields.function(
_get_description_short, type='char',
help='Message description: either the subject, or the beginning of the body'
),
'website_published': fields.boolean(
'Published', help="Visible on the website as a comment"
),

View File

@ -1,34 +1,29 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
from openerp import tools
from openerp.addons.web import http
from openerp.addons.website.models.website import slug
from openerp.addons.web.http import request
class MailGroup(http.Controller):
_thread_per_page = 10
@http.route([
"/groups",
], type='http', auth="public", website=True)
def _get_archives(self, group_id):
MailMessage = request.registry['mail.message']
groups = MailMessage.read_group(
request.cr, request.uid, [('model', '=', 'mail.group'), ('res_id', '=', group_id)], ['subject', 'date'],
groupby="date", orderby="date asc", context=request.context)
for group in groups:
begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
end_date = datetime.datetime.strptime(group['__domain'][1][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
group['date_begin'] = '%s' % datetime.date.strftime(begin_date, tools.DEFAULT_SERVER_DATE_FORMAT)
group['date_end'] = '%s' % datetime.date.strftime(end_date, tools.DEFAULT_SERVER_DATE_FORMAT)
return groups
@http.route("/groups", type='http', auth="public", website=True)
def view(self, **post):
cr, uid, context = request.cr, request.uid, request.context
group_obj = request.registry.get('mail.group')
@ -37,7 +32,7 @@ class MailGroup(http.Controller):
return request.website.render('website_mail_group.mail_groups', values)
@http.route(["/groups/subscription/"], type='json', auth="user")
def subscription(self, group_id=0, action=False ,**post):
def subscription(self, group_id=0, action=False, **post):
cr, uid, context = request.cr, request.uid, request.context
group_obj = request.registry.get('mail.group')
if action:
@ -47,45 +42,50 @@ class MailGroup(http.Controller):
return []
@http.route([
"/groups/<model('mail.group'):group>/<any(thread,list):mode>",
"/groups/<model('mail.group'):group>/<any(thread,list):mode>/page/<int:page>"
"/groups/<model('mail.group'):group>",
"/groups/<model('mail.group'):group>/page/<int:page>"
], type='http', auth="public", website=True)
def thread(self, group, mode='thread', page=1, **post):
def thread_headers(self, group, page=1, mode='thread', date_begin=None, date_end=None, **post):
cr, uid, context = request.cr, request.uid, request.context
thread_obj = request.registry.get('mail.message')
domain = [('model','=','mail.group'), ('res_id','=',group.id)]
if mode=='thread':
domain.append(('parent_id','=',False))
domain = [('model', '=', 'mail.group'), ('res_id', '=', group.id)]
if mode == 'thread':
domain += [('parent_id', '=', False)]
if date_begin and date_end:
domain += [('date', '>=', date_begin), ('date', '<=', date_end)]
thread_count = thread_obj.search_count(cr, uid, domain, context=context)
pager = request.website.pager(
url='/groups/%s/%s/' % (group.id, mode),
url='/groups/%s' % slug(group),
total=thread_count,
page=page,
step=self._thread_per_page,
url_args={'mode': mode, 'date_begin': date_begin or '', 'date_end': date_end or ''},
)
thread_ids = thread_obj.search(cr, uid, domain, limit=self._thread_per_page, offset=pager['offset'])
messages = thread_obj.browse(cr, uid, thread_ids, context)
for m in messages:
print m.subject
values = {
'messages': messages,
'group': group,
'pager': pager,
'mode': mode
'mode': mode,
'archives': self._get_archives(group.id),
'date_begin': date_begin,
'date_end': date_end,
}
return request.website.render('website_mail_group.group_messages', values)
@http.route([
"/groups/<model('mail.group'):group>/message/<model('mail.message'):message>",
"/groups/<model('mail.group'):group>/<model('mail.message'):message>",
], type='http', auth="public", website=True)
def get_thread(self, group, message, mode='thread', page=1, **post):
def thread_discussion(self, group, message, mode='thread', date_begin=None, date_end=None, **post):
cr, uid, context = request.cr, request.uid, request.context
values = {
'message': message,
'group': group,
'mode': mode,
'page': page,
'date_begin': date_begin,
'date_end': date_end,
}
return request.website.render('website_mail_group.group_message', values)

View File

@ -16,24 +16,9 @@
<div class="col-sm-4" style="height: 140px" t-foreach="groups" t-as="group">
<img t-att-src="'/website/image?model=mail.group&amp;field=image_small&amp;id='+str(group['id'])" class="pull-left"/>
<div>
<strong><a t-attf-href="/groups/#{ slug(group) }/thread" t-esc="group.name"/></strong>
<strong><a t-attf-href="/groups/#{ slug(group) }" t-esc="group.name"/></strong>
<div t-esc="group.description" class="text-muted"/>
<div class="input-group js_follow"
t-att-data-id="group.id"
data-object="mail.group"
data-follow="off">
<input
type="email"
name="email"
class="js_follow_email form-control"
placeholder="your email..."/>
<span class="input-group-btn">
<a href="#" class="btn btn-default js_unfollow_btn">unsubscribe</a>
<a href="#" class="btn btn-primary js_follow_btn">subscribe</a>
</span>
<div class="alert alert-success hidden">You have been subscribed!</div>
</div>
<t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
</div>
</div>
</div>
@ -63,10 +48,20 @@
<div class="col-md-3">
<ul class="nav nav-pills nav-stacked" id="group_mode">
<li t-attf-class="#{mode=='thread' and 'active' or ''}">
<a t-attf-href="/groups/#{ slug(group) }/thread">By thread</a>
<a t-attf-href="/groups/#{ slug(group) }?mode=thread">By thread</a>
</li>
<li t-attf-class="#{mode=='list' and 'active' or ''}">
<a t-attf-href="/groups/#{ slug(group) }/list">By date</a>
<li t-attf-class="#{mode=='date' and not date_begin and 'active' or ''}">
<a t-attf-href="/groups/#{ slug(group) }?mode=date">By date</a>
<ul class="nav nav-pills nav-stacked" style="margin-left: 8px;">
<t t-foreach="archives" t-as="month_archive">
<li t-att-class="month_archive['date_begin'] == date_begin and 'active' or None">
<a t-ignore="True" t-attf-href="/groups/#{ slug(group) }?mode=date&amp;date_begin=#{ month_archive['date_begin'] }&amp;date_end=#{month_archive['date_end']}">
<t t-esc="month_archive['date']"/>
<span class="pull-right badge" t-esc="month_archive['date_count']"/>
</a>
</li>
</t>
</ul>
</li>
</ul>
</div>
@ -86,7 +81,7 @@
<ol class="breadcrumb mb8">
<li><a href="/groups">Mailing Lists</a></li>
<li>
<a t-attf-href="/groups/#{ slug(group) }/#{mode}/page/#{str(page)}">
<a t-attf-href="/groups/#{slug(group)}?mode=#{mode}&amp;date_begin=#{date_begin}&amp;date_end=#{date_end}">
<span t-field="group.name"/>
</a>
</li>
@ -98,7 +93,13 @@
<h1 t-field="message.subject"/>
<img class="img-rounded pull-left" t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(message.id)" style="width : 30px"/>
<h4 class="mt0 mb32">
<span t-field="message.author_id.name"/>
<t t-if="message.author_id">
<span t-field="message.author_id" style="display: inline-block;" t-field-options='{
"widget": "contact",
"fields": ["name"]
}'/>
</t>
<t t-if="not message.author_id"><t t-esc="message.email_from"/></t>
on <span t-field="message.date"/>
</h4>
<div t-raw="message.body"/>
@ -136,25 +137,7 @@
Join this mailing list to follow or participate to this discussion.<br/>
<span t-field="group.name"/>: <i t-field="group.description"/>
</p>
<div style="max-width: 400px">
<div class="input-group js_follow"
t-att-data-id="group.id"
data-object="mail.group"
data-follow="off">
<input
type="email"
name="email"
class="js_follow_email form-control"
placeholder="your email..."/>
<span class="input-group-btn">
<a href="#" class="btn btn-default js_unfollow_btn">unsubscribe</a>
<a href="#" class="btn btn-primary js_follow_btn">subscribe</a>
</span>
<div class="alert alert-success hidden">You have been subscribed!</div>
</div>
</div>
<t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
</div>
</div>
</t>
@ -163,16 +146,25 @@
<template id="messages_short">
<ul class="media-list">
<li t-foreach="messages" t-as="thread" class="media">
<a t-attf-href="/groups/#{group.id}/message/#{ slug(thread) }?mode=#{mode}" class="pull-left">
<img class="img-rounded pull-right mt0" style="height: 40px"
t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(thread.id)"/>
</a>
<img class="img-rounded pull-left mt0 media-object" style="height: 40px"
t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(thread.id)"/>
<div class="media-body">
<h4 class="media-heading">
<a t-attf-href="/groups/#{ slug(group) }/message/#{ slug(thread) }" t-esc="thread.subject"/>
<br/>
<small>by <t t-esc="thread.author_id.name and thread.author_id.name or thread.email_from"/> on <t t-esc="thread.date"/></small>
<a t-attf-href="/groups/#{slug(group)}/#{slug(thread)}?mode=#{mode}&amp;date_begin=#{date_begin}&amp;date_end=#{date_end}" t-esc="thread.description"/>
</h4>
<small>
by
<t t-if="thread.author_id">
<span t-field="thread.author_id" style="display: inline-block;" t-field-options='{
"widget": "contact",
"fields": ["name"]
}'/>
</t>
<t t-if="not thread.author_id"><t t-esc="thread.email_from"/></t>
<span class="fa fa-comment-o">
<t t-raw="len(thread.child_ids)"/> replies
</span>
</small>
</div>
</li>
</ul>