Merge remote-tracking branch 'odoo/saas-4' into saas-4-report-fixes-sle
This commit is contained in:
commit
2d7c890939
15
.bzrignore
15
.bzrignore
|
@ -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
|
|
|
@ -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/
|
|
@ -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='[]'):
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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&' % 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&' % 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&' % 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&' % current_grade.id}#{current_country and 'country_id=%s' % current_country.id}">
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
.o_mg_avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_mg_link_show {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_mg_link_content {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -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&field=image_small&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&date_begin=#{ month_archive['date_begin'] }&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&field=image_small&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}&date_begin=#{date_begin}&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&field=author_avatar&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&id='+str(message.id)+'&method=download_attachment&attachment_id='+str(attachment.id)" target="_blank">
|
|
||||||
<t t-if="attachment.file_type == 'webimage'">
|
|
||||||
<img t-att-src="'/web/binary/image?model=ir.attachment&field=datas&id=' + str(attachment.id) + '&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 '&date_begin=%s' % date_begin or ''}#{date_end and '&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&date_begin=#{ month_archive['date_begin'] }&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 '&date_begin=%s' % date_begin or ''}#{date_end and '&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&date_begin=#{ month_archive['date_begin'] }&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&field=author_avatar&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&id='+str(message.id)+'&method=download_attachment&attachment_id='+str(attachment.id)" target="_blank">
|
||||||
|
<t t-if="attachment.file_type == 'webimage'">
|
||||||
|
<img t-att-src="'/web/binary/image?model=ir.attachment&field=datas&id=' + str(attachment.id) + '&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&field=author_avatar&id='+str(thread.id)"/>
|
t-att-src="'/website/image?model=mail.message&field=author_avatar&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>
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Loading…
Reference in New Issue