Merge remote-tracking branch 'odoo/saas-4' into saas-4-report-fixes-sle

This commit is contained in:
Simon Lejeune 2014-05-23 15:38:56 +02:00
commit 2d7c890939
15 changed files with 415 additions and 176 deletions

View File

@ -1,15 +0,0 @@
.*
*.egg-info
*.orig
*.vim
build/
RE:^bin/
RE:^dist/
RE:^include/
RE:^share/
RE:^man/
RE:^lib/
RE:^addons/\w+/doc/_build/
RE:^.*?/node_modules

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# sphinx build directories
_build/
# dotfiles
.*
# compiled python files
*.py[co]
# setup.py egg_info
*.egg-info
# emacs backup files
*~
# hg stuff
*.orig
status
# generated for windows installer?
install/win32/*.bat
install/win32/meta.py
# various virtualenv
/bin/
/build/
/dist/
/include/
/lib/
/man/
/share/
/src/

View File

@ -126,6 +126,7 @@ class ir_http(orm.AbstractModel):
return response return response
def _handle_exception(self, exception=None, code=500): def _handle_exception(self, exception=None, code=500):
res = super(ir_http, self)._handle_exception(exception)
if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response: if isinstance(exception, werkzeug.exceptions.HTTPException) and hasattr(exception, 'response') and exception.response:
return exception.response return exception.response
@ -168,7 +169,7 @@ class ir_http(orm.AbstractModel):
html = request.website._render('website.http_error', values) html = request.website._render('website.http_error', values)
return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8') return werkzeug.wrappers.Response(html, status=code, content_type='text/html;charset=utf-8')
return super(ir_http, self)._handle_exception(exception) return res
class ModelConverter(ir.ir_http.ModelConverter): class ModelConverter(ir.ir_http.ModelConverter):
def __init__(self, url_map, model=False, domain='[]'): def __init__(self, url_map, model=False, domain='[]'):

View File

@ -15,6 +15,7 @@ import urllib2
import urlparse import urlparse
import re import re
import werkzeug.urls
import werkzeug.utils import werkzeug.utils
from dateutil import parser from dateutil import parser
from lxml import etree, html from lxml import etree, html
@ -265,10 +266,19 @@ class Image(orm.AbstractModel):
if options is None: options = {} if options is None: options = {}
classes = ['img', 'img-responsive'] + options.get('class', '').split() classes = ['img', 'img-responsive'] + options.get('class', '').split()
return ir_qweb.HTMLSafe('<img class="%s" src="/website/image?model=%s&field=%s&id=%s"/>' % ( url_params = {
'model': record._model._name,
'field': field_name,
'id': record.id,
}
for options_key in ['max_width', 'max_height']:
if options.get(options_key):
url_params[options_key] = options[options_key]
return ir_qweb.HTMLSafe('<img class="%s" src="/website/image?%s"/>' % (
' '.join(itertools.imap(werkzeug.utils.escape, classes)), ' '.join(itertools.imap(werkzeug.utils.escape, classes)),
record._model._name, werkzeug.urls.url_encode(url_params)
field_name, record.id)) ))
local_url_re = re.compile(r'^/(?P<module>[^]]+)/static/(?P<rest>.+)$') local_url_re = re.compile(r'^/(?P<module>[^]]+)/static/(?P<rest>.+)$')
def from_html(self, cr, uid, model, column, element, context=None): def from_html(self, cr, uid, model, column, element, context=None):

View File

@ -555,8 +555,10 @@ class website(osv.osv):
if record.get(presized): if record.get(presized):
response.data = data response.data = data
return response return response
try:
fit = int(max_width), int(max_height) fit = int(max_width), int(max_height)
except TypeError:
fit = (maxint, maxint)
w, h = image.size w, h = image.size
max_w, max_h = fit max_w, max_h = fit

View File

@ -86,8 +86,8 @@
</t> </t>
<div class="media"> <div class="media">
<a class="pull-left" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}" <a class="pull-left" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}"
t-field="partner.image_small" t-field="partner.image"
t-field-options='{"widget": "image", "class": "media-object"}' t-field-options='{"widget": "image", "class": "media-object", "max_width": 128}'
></a> ></a>
<div class="media-body o_partner_body" style="min-height: 64px;"> <div class="media-body o_partner_body" style="min-height: 64px;">
<a class="media-heading" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}"> <a class="media-heading" t-attf-href="/partners/#{slug(partner)}?#{current_grade and 'grade_id=%s&amp;' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}">

View File

@ -88,10 +88,21 @@ class website_event(http.Controller):
days_tracks_count[day] = len(tracks) days_tracks_count[day] = len(tracks)
days[day] = self._prepare_calendar(event, tracks) days[day] = self._prepare_calendar(event, tracks)
cr, uid, context = request.cr, request.uid, request.context
track_obj = request.registry['event.track']
tracks_ids = track_obj.search(cr, openerp.SUPERUSER_ID, [('event_id', '=', event.id)], context=context)
speakers = dict()
for t in track_obj.browse(cr, openerp.SUPERUSER_ID, tracks_ids, context=context):
acc = ""
for speaker in t.speaker_ids:
acc = speaker.name + u" " + acc if acc else speaker.name
speakers[t.id] = acc
return request.website.render("website_event_track.agenda", { return request.website.render("website_event_track.agenda", {
'event': event, 'event': event,
'days': days, 'days': days,
'days_nbr': days_tracks_count, 'days_nbr': days_tracks_count,
'speakers': speakers,
'tag': tag 'tag': tag
}) })

View File

@ -85,8 +85,8 @@
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }"> <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
<span t-esc="track and track.name"/> <span t-esc="track and track.name"/>
</a> </a>
<div class="text-muted" t-foreach="track.speaker_ids" t-as="speaker"> <div class="text-muted">
<small t-esc="speaker.display_name"/> <small t-esc="speakers[track.id]"/>
</div> </div>
</t> </t>
</td> </td>
@ -98,11 +98,11 @@
<t t-set="track" t-value="dt[1][False][0]"/> <t t-set="track" t-value="dt[1][False][0]"/>
<td t-att-colspan="len(locations)-1" t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''}"> <td t-att-colspan="len(locations)-1" t-attf-class="text-center event_color_#{track.color} #{track and 'event_track' or ''}">
<a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }"> <a t-attf-href="/event/#{ slug(event) }/track/#{ slug(track) }">
<span t-esc="track.name"/><br/> <span t-esc="track.name"/>
<div class="text-muted" t-foreach="track.speaker_ids" t-as="speaker">
<small t-esc="speaker.display_name"/>
</div>
</a> </a>
<div class="text-muted">
<small t-esc="speakers[track.id]"/>
</div>
</td> </td>
</t> </t>
</tr> </tr>

View File

@ -34,7 +34,7 @@ class MailMessage(osv.Model):
res[message.id] = message.subject res[message.id] = message.subject
else: else:
plaintext_ct = html2plaintext(message.body) plaintext_ct = html2plaintext(message.body)
res[message.id] = plaintext_ct + '%s' % (' [...]' if len(plaintext_ct) >= 20 else '') res[message.id] = plaintext_ct[:30] + '%s' % (' [...]' if len(plaintext_ct) >= 30 else '')
return res return res
_columns = { _columns = {

View File

@ -9,13 +9,14 @@ from openerp.addons.web.http import request
class MailGroup(http.Controller): class MailGroup(http.Controller):
_thread_per_page = 10 _thread_per_page = 20
_replies_per_page = 10
def _get_archives(self, group_id): def _get_archives(self, group_id):
MailMessage = request.registry['mail.message'] MailMessage = request.registry['mail.message']
groups = MailMessage.read_group( groups = MailMessage.read_group(
request.cr, request.uid, [('model', '=', 'mail.group'), ('res_id', '=', group_id)], ['subject', 'date'], request.cr, request.uid, [('model', '=', 'mail.group'), ('res_id', '=', group_id)], ['subject', 'date'],
groupby="date", orderby="date asc", context=request.context) groupby="date", orderby="date desc", context=request.context)
for group in groups: for group in groups:
begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date() 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() end_date = datetime.datetime.strptime(group['__domain'][1][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
@ -27,7 +28,7 @@ class MailGroup(http.Controller):
def view(self, **post): def view(self, **post):
cr, uid, context = request.cr, request.uid, request.context cr, uid, context = request.cr, request.uid, request.context
group_obj = request.registry.get('mail.group') group_obj = request.registry.get('mail.group')
group_ids = group_obj.search(cr, uid, [], context=context) group_ids = group_obj.search(cr, uid, [('alias_id', '!=', False), ('alias_id.alias_name', '!=', False)], context=context)
values = {'groups': group_obj.browse(cr, uid, group_ids, context)} values = {'groups': group_obj.browse(cr, uid, group_ids, context)}
return request.website.render('website_mail_group.mail_groups', values) return request.website.render('website_mail_group.mail_groups', values)
@ -73,6 +74,7 @@ class MailGroup(http.Controller):
'archives': self._get_archives(group.id), 'archives': self._get_archives(group.id),
'date_begin': date_begin, 'date_begin': date_begin,
'date_end': date_end, 'date_end': date_end,
'replies_per_page': self._replies_per_page,
} }
return request.website.render('website_mail_group.group_messages', values) return request.website.render('website_mail_group.group_messages', values)
@ -81,11 +83,49 @@ class MailGroup(http.Controller):
], type='http', auth="public", website=True) ], type='http', auth="public", website=True)
def thread_discussion(self, group, message, mode='thread', date_begin=None, date_end=None, **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 cr, uid, context = request.cr, request.uid, request.context
Message = request.registry['mail.message']
if mode == 'thread':
base_domain = [('model', '=', 'mail.group'), ('res_id', '=', group.id), ('parent_id', '=', message.parent_id and message.parent_id.id or False)]
else:
base_domain = [('model', '=', 'mail.group'), ('res_id', '=', group.id)]
next_message = None
next_message_ids = Message.search(cr, uid, base_domain + [('date', '<', message.date)], order="date DESC", limit=1, context=context)
if next_message_ids:
next_message = Message.browse(cr, uid, next_message_ids[0], context=context)
prev_message = None
prev_message_ids = Message.search(cr, uid, base_domain + [('date', '>', message.date)], order="date ASC", limit=1, context=context)
if prev_message_ids:
prev_message = Message.browse(cr, uid, prev_message_ids[0], context=context)
values = { values = {
'message': message, 'message': message,
'group': group, 'group': group,
'mode': mode, 'mode': mode,
'archives': self._get_archives(group.id),
'date_begin': date_begin, 'date_begin': date_begin,
'date_end': date_end, 'date_end': date_end,
'replies_per_page': self._replies_per_page,
'next_message': next_message,
'prev_message': prev_message,
} }
return request.website.render('website_mail_group.group_message', values) return request.website.render('website_mail_group.group_message', values)
@http.route(
'''/groups/<model('mail.group'):group>/<model('mail.message', "[('model','=','mail.group'), ('res_id','=',group[0])]"):message>/get_replies''',
type='json', auth="public", methods=['POST'], website=True)
def render_messages(self, group, message, **post):
last_displayed_id = post.get('last_displayed_id')
if not last_displayed_id:
return False
Message = request.registry['mail.message']
replies_domain = [('id', '<', int(last_displayed_id)), ('parent_id', '=', message.id)]
msg_ids = Message.search(request.cr, request.uid, replies_domain, limit=self._replies_per_page, context=request.context)
msg_count = Message.search(request.cr, request.uid, replies_domain, count=True, context=request.context)
messages = Message.browse(request.cr, request.uid, msg_ids, context=request.context)
values = {
'group': group,
'thread_header': message,
'messages': messages,
'msg_more_count': msg_count - self._replies_per_page,
'replies_per_page': self._replies_per_page,
}
return request.registry['ir.ui.view'].render(request.cr, request.uid, 'website_mail_group.messages_short', values, engine='ir.qweb', context=request.context)

View File

@ -0,0 +1,12 @@
.o_mg_avatar {
width: 40px;
height: 40px;
}
.o_mg_link_show {
display: none;
}
.o_mg_link_content {
display: none;
}

View File

@ -0,0 +1,42 @@
$(document).ready(function () {
$('.o_mg_link_hide').on('click', function (ev) {
ev.preventDefault();
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();
return false;
});
$('.o_mg_link_show').on('click', function (ev) {
ev.preventDefault();
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();
return false;
});
$('body').on('click', 'button.o_mg_read_more', function (ev) {
var $link = $(ev.target);
return openerp.jsonRpc($link.data('href'), 'call', {
'last_displayed_id': $link.data('msg-id'),
}).then(function (data) {
if (! data) {
return true;
}
var $thread_container = $link.parents('.o_mg_replies').first().find('ul.media-list');
if ($thread_container) {
var $last_msg = $thread_container.find('li.media').last();
$(data).find('li.media').insertAfter($last_msg);
$(data).find('p.well').appendTo($thread_container);
}
var $show_more = $link.parents('p.well').first();
$show_more.remove();
return true;
});
});
});

View File

@ -1,152 +1,240 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data> <data>
<template id="footer_mailing_list" inherit_id="website.layout" name="Footer Mailing List Link">
<xpath expr="//footer//div[@name='info']/ul" position="inside">
<li><a t-attf-href="/groups">Mailing List</a></li>
</xpath>
</template>
<template id="mail_groups" name="Mailing Lists">
<t t-call="website.layout">
<div class="container">
<h1>
Our Mailing Lists
</h1>
<div class="row">
<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) }" t-esc="group.name"/></strong>
<div t-esc="group.description" class="text-muted"/>
<t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
</div>
</div>
</div>
</div>
</t>
</template>
<template id="group_messages" name="Message Threads"> <template id="footer_mailing_list" inherit_id="website.layout" name="Footer Mailing List Link">
<t t-call="website.layout"> <xpath expr="//footer//div[@name='info']/ul" position="inside">
<section class="container"> <li><a t-attf-href="/groups">Mailing List</a></li>
<div class="row mt8"> </xpath>
<div class="col-md-5 mt16"> </template>
<ol class="breadcrumb">
<li><a href="/groups">Mailing Lists</a></li> <template id="mail_groups" name="Mailing Lists">
<li class="active" t-esc="group.name"/> <t t-call="website.layout">
</ol> <div id="wrap" class="oe_structure oe_empty">
</div> <section class="bg-primary jumbotron mt0 mb0">
<div class="col-md-5 pull-right"> <div class="container">
<t t-call="website.pager"/> <h1>Stay in touch with our Community</h1>
</div> <p>Alone we can do so little, together we can do so much</p>
</div>
<h1 class="mt8 mb32">
<span t-field="group.name"/>
<small>List Archive</small>
</h1>
<div class="row">
<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) }?mode=thread">By thread</a>
</li>
<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>
<div class="col-md-9">
<t t-call="website_mail_group.messages_short"/>
</div>
</div> </div>
</section> </section>
</t> </div>
</template> <div class="container mt32">
<div class="row mt8" t-foreach="groups" t-as="group">
<template id="group_message"> <div class="col-md-3">
<t t-call="website.layout"> <img t-att-src="'/website/image?model=mail.group&amp;field=image_small&amp;id='+str(group['id'])" class="pull-left"/>
<div class="container"> <strong><a t-attf-href="/groups/#{ slug(group) }" t-esc="group.name"/></strong><br />
<div class="row mt8"> <i class='fa fa-envelope-o'/>
<div class="col-md-5"> <a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
<ol class="breadcrumb mb8">
<li><a href="/groups">Mailing Lists</a></li>
<li>
<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>
<li class="active" t-esc="message.subject or 'Message'"/>
</ol>
</div>
</div> </div>
<div class="col-md-4">
<h1 t-field="message.subject"/> <div t-esc="group.description" class="text-muted"/>
<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">
<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"/>
<div class="row" t-if="message.attachment_ids">
<h3 class="col-sm-12">Attachment(s):</h3>
<div class="col-md-2 col-sm-3 text-center" t-foreach='message.attachment_ids' t-as='attachment'>
<a t-att-href="'/mail/download_attachment?model=mail.message&amp;id='+str(message.id)+'&amp;method=download_attachment&amp;attachment_id='+str(attachment.id)" target="_blank">
<t t-if="attachment.file_type == 'webimage'">
<img t-att-src="'/web/binary/image?model=ir.attachment&amp;field=datas&amp;id=' + str(attachment.id) + '&amp;resize=100,80'"
class='oe_attachment_embedded'></img>
</t>
<t t-if="attachment.file_type != 'webimage'">
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.file_type + '.png'"
class='oe_attachment_webimage'></img>
</t>
<div class='oe_attachment_name'><t t-raw='attachment.name' /></div>
</a>
</div>
</div> </div>
<div t-if="message.child_ids"> <div class="col-md-2">
<h2 class="page-header">Follow ups</h2> <i class='fa fa-user'/> <t t-esc="len(group.message_follower_ids)"/> participants<br />
<t t-set="messages" t-value="message.child_ids"/> <i class='fa fa-envelope-o'/> <t t-esc="len(group.message_ids)"/> messages
<t t-call="website_mail_group.messages_short"/>
</div> </div>
<div t-if="message.parent_id"> <div class="col-md-3">
<h2 class="page-header">Reference</h2>
<t t-set="messages" t-value="[message.parent_id]"/>
<t t-call="website_mail_group.messages_short"/>
</div>
<div class="jumbotron mt64">
<h1>Join the discussion</h1>
<p>
Join this mailing list to follow or participate to this discussion.<br/>
<span t-field="group.name"/>: <i t-field="group.description"/>
</p>
<t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t> <t t-call="website_mail.follow"><t t-set="object" t-value="group"/></t>
</div> </div>
</div> </div>
</t> </div>
</template> </t>
</template>
<template id="messages_short"> <template id="group_messages" name="Message Threads">
<t t-call="website.layout">
<t t-set="head">
<link rel='stylesheet' href="/website_mail_group/static/src/css/website_mail_group.css"/>
<script type="text/javascript" src="/website_mail_group/static/src/js/website_mail_group.js"/>
</t>
<section class="container">
<div class="row mt8">
<ol class="breadcrumb pull-left">
<li><a href="/groups">Mailing Lists</a></li>
<li>
<a t-attf-href="/groups/#{slug(group)}?#{mode and 'mode=%s' % mode or ''}#{date_begin and '&amp;date_begin=%s' % date_begin or ''}#{date_end and '&amp;date_end=%s' % date_end or ''}"><t t-esc="group.name"/></a>
</li>
</ol>
</div>
<div class="row">
<h1 class="text-center">
<t t-esc="group.name"/> mailing list archives
</h1><h4 class="text-center text-muted">
<i class='fa fa-envelope-o'/>
<a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
</h4>
</div>
<div class="row">
<div class="col-md-3">
<h2>Archives</h2>
<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) }?mode=thread">By thread</a>
</li>
<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>
<div class="col-md-9">
<div>
<t t-call="website.pager"/>
</div>
<t t-call="website_mail_group.messages_short">
<t t-set="messages" t-value="messages"/>
<t t-set="msg_more_count" t-value="0"/>
<t t-set="thread_header" t-value="None"/>
</t>
<div>
<t t-call="website.pager"/>
</div>
</div>
</div>
</section>
</t>
</template>
<template id="group_message">
<t t-call="website.layout">
<t t-set="head">
<link rel='stylesheet' href="/website_mail_group/static/src/css/website_mail_group.css"/>
<script type="text/javascript" src="/website_mail_group/static/src/js/website_mail_group.js"/>
</t>
<section class="container">
<div class="row mt8">
<ol class="breadcrumb pull-left">
<li><a href="/groups">Mailing Lists</a></li>
<li>
<a t-attf-href="/groups/#{slug(group)}?#{mode and 'mode=%s' % mode or ''}#{date_begin and '&amp;date_begin=%s' % date_begin or ''}#{date_end and '&amp;date_end=%s' % date_end or ''}"><t t-esc="group.name"/></a>
</li>
<li t-if="message" class="active"><t t-esc="message.description"/></li>
</ol>
</div>
<div class="row">
<h1 class="text-center">
<t t-esc="group.name"/> mailing list archives
</h1><h4 class="text-center text-muted">
<i class='fa fa-envelope-o'/>
<a t-attf-href="mailto:#{group.alias_id.alias_name}@#{group.alias_id.alias_domain}"><span t-field="group.alias_id"/></a>
</h4>
</div>
<div class="row">
<div class="col-md-3">
<h4>Browse archives</h4>
<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) }?mode=thread">By thread</a>
</li>
<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>
<div class="col-md-9">
<div class="row">
<h4 class="col-md-6">
<t t-if="prev_message"><a t-attf-href='/groups/#{slug(group)}/#{slug(prev_message)}?#{mode and "mode=%s" % mode or ""}'>
<i class="fa fa-arrow-left"/> <t t-esc="prev_message.description"/>
</a></t>
</h4>
<h4 class="col-md-6">
<t t-if="next_message"><a class="pull-right" t-attf-href='/groups/#{slug(group)}/#{slug(next_message)}?#{mode and "mode=%s" % mode or ""}'>
<t t-esc="next_message.description"/> <i class="fa fa-arrow-right"/>
</a></t>
</h4>
</div>
<div class="media">
<img class="img-rounded pull-left mt0 media-object o_mg_avatar"
t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(message.id)"/>
<div class="media-body">
<h4 class="media-heading" t-esc="message.description"/>
<small>
by
<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>
- <i class="fa fa-calendar"/> <t t-esc="message.date"/>
</small>
<div t-raw="message.body"/>
<div>
<p t-if="message.attachment_ids" class="mt8">
<a href="#" class="o_mg_link_hide">
<i class="fa fa-chevron-right"/> <t t-raw="len(message.attachment_ids)"/> attachments
</a>
<a href="#" class="o_mg_link_show">
<i class="fa fa-chevron-down"/> <t t-raw="len(message.attachment_ids)"/> attachments
</a>
</p>
<div class="o_mg_link_content">
<div class="col-md-2 col-sm-3 text-center" t-foreach='message.attachment_ids' t-as='attachment'>
<a t-att-href="'/mail/download_attachment?model=mail.message&amp;id='+str(message.id)+'&amp;method=download_attachment&amp;attachment_id='+str(attachment.id)" target="_blank">
<t t-if="attachment.file_type == 'webimage'">
<img t-att-src="'/web/binary/image?model=ir.attachment&amp;field=datas&amp;id=' + str(attachment.id) + '&amp;resize=100,80'"
class='oe_attachment_embedded'
t-att-title="attachment.name"/>
</t>
<t t-if="attachment.file_type != 'webimage'">
<img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.file_type + '.png'"
class='oe_attachment_webimage'
t-att-title="attachment.name"/>
</t>
<div class='oe_attachment_name'><t t-raw='attachment.name' /></div>
</a>
</div>
</div>
</div>
</div>
</div>
<div t-if="message.child_ids" class="o_mg_replies">
<h4 class="page-header">Follow-Ups</h4>
<t t-call="website_mail_group.messages_short">
<t t-set="messages" t-value="message.child_ids[:replies_per_page]"/>
<t t-set="msg_more_count" t-value="len(message.child_ids) - replies_per_page"/>
<t t-set="thread_header" t-value="message"/>
</t>
</div>
<div t-if="message.parent_id">
<h4 class="page-header">Reference</h4>
<t t-call="website_mail_group.messages_short">
<t t-set="messages" t-value="[message.parent_id]"/>
</t>
</div>
</div>
</div>
</section>
</t>
</template>
<template id="messages_short">
<div>
<ul class="media-list"> <ul class="media-list">
<li t-foreach="messages" t-as="thread" class="media"> <li t-foreach="messages" t-as="thread" class="media">
<img class="img-rounded pull-left mt0 media-object" style="height: 40px" <img class="img-rounded pull-left mt0 media-object o_mg_avatar"
t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(thread.id)"/> t-att-src="'/website/image?model=mail.message&amp;field=author_avatar&amp;id='+str(thread.id)"/>
<div class="media-body"> <div class="media-body">
<h4 class="media-heading"> <h4 class="media-heading">
@ -161,14 +249,36 @@
}'/> }'/>
</t> </t>
<t t-if="not thread.author_id"><t t-esc="thread.email_from"/></t> <t t-if="not thread.author_id"><t t-esc="thread.email_from"/></t>
<span class="fa fa-comment-o"> - <i class="fa fa-calendar"/> <t t-esc="thread.date"/>
<t t-raw="len(thread.child_ids)"/> replies - <i class="fa fa-paperclip"/> <t t-esc="len(thread.attachment_ids)"/>
</span>
</small> </small>
<p t-if="thread.child_ids" class="mt8">
<a href="#" class="o_mg_link_hide">
<i class="fa fa-chevron-right"/> <t t-raw="len(thread.child_ids)"/> replies
</a>
<a href="#" class="o_mg_link_show">
<i class="fa fa-chevron-down"/> <t t-raw="len(thread.child_ids)"/> replies
</a>
</p>
<div class="o_mg_link_content o_mg_replies">
<t t-call="website_mail_group.messages_short">
<t t-set="messages" t-value="thread.child_ids[:replies_per_page]"/>
<t t-set="msg_more_count" t-value="len(thread.child_ids) - replies_per_page"/>
<t t-set="thread_header" t-value="thread"/>
</t>
</div>
</div> </div>
</li> </li>
</ul> </ul>
</template> <p t-if="messages and msg_more_count > 0 and thread_header" class="well well-sm">
<button class="fa btn-link o_mg_read_more"
t-attf-data-href="/groups/#{slug(group)}/#{slug(thread_header)}/get_replies"
t-attf-data-msg-id="#{messages[-1].id}">
show <t t-esc="msg_more_count"/> more replies
</button>
</p>
</div>
</template>
</data> </data>
</openerp> </openerp>

View File

@ -267,7 +267,7 @@ class WebRequest(object):
"""Called within an except block to allow converting exceptions """Called within an except block to allow converting exceptions
to abitrary responses. Anything returned (except None) will to abitrary responses. Anything returned (except None) will
be used as response.""" be used as response."""
raise self._failed = exception # prevent tx commit
def _call_function(self, *args, **kwargs): def _call_function(self, *args, **kwargs):
request = self request = self
@ -449,8 +449,8 @@ class JsonRequest(WebRequest):
"""Called within an except block to allow converting exceptions """Called within an except block to allow converting exceptions
to abitrary responses. Anything returned (except None) will to abitrary responses. Anything returned (except None) will
be used as response.""" be used as response."""
super(JsonRequest, self)._handle_exception(exception)
_logger.exception("Exception during JSON request handling.") _logger.exception("Exception during JSON request handling.")
self._failed = exception # prevent tx commit
error = { error = {
'code': 200, 'code': 200,
'message': "OpenERP Server Error", 'message': "OpenERP Server Error",

View File

@ -107,7 +107,7 @@ class NumberedCanvas(canvas.Canvas):
self.setFont("Helvetica", 8) self.setFont("Helvetica", 8)
self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40), self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40),
" %(this)i / %(total)i" % { " %(this)i / %(total)i" % {
'this': self._pageNumber+1, 'this': self._pageNumber,
'total': page_count, 'total': page_count,
} }
) )
@ -1007,8 +1007,6 @@ class _rml_template(object):
if story_cnt > 0: if story_cnt > 0:
fis.append(platypus.PageBreak()) fis.append(platypus.PageBreak())
fis += r.render(node_story) fis += r.render(node_story)
# Reset Page Number with new story tag
fis.append(PageReset())
story_cnt += 1 story_cnt += 1
try: try:
if self.localcontext and self.localcontext.get('internal_header',False): if self.localcontext and self.localcontext.get('internal_header',False):