[IMP] website_blog : allow multi tags and date filter, clean all the routes, remove group_comment from website_mail (only user and portal can post comment on blog.post, but the form is visible for all), modify the redirect controller to the login form when posting comment, and remove the description field of blog.blog

This commit is contained in:
Jérome Maes
2014-12-26 16:04:29 +01:00
parent e4fd9737e4
commit aaf37d8e87
11 changed files with 115 additions and 103 deletions
+2 -4
View File
@@ -364,10 +364,8 @@
<template id="publish_short">
<t groups="base.group_website_publisher" t-ignore="true">
<div t-attf-class="btn-group pull-right js_publish_management #{object.website_published and 'css_published' or 'css_unpublished'}" t-att-data-id="object.id" t-att-data-object="object._name" t-att-data-controller="publish_controller">
<button t-attf-class="btn btn-sm btn-#{object.website_published and 'success' or 'danger'} js_publish_btn">
<span class="css_publish">Not Published</span>
<span class="css_unpublish">Published</span>
</button>
<button class="btn btn-danger js_publish_btn">Not Published</button>
<button class="btn btn-success js_publish_btn">Published</button>
</div>
</t>
</template>
+67 -51
View File
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
import datetime
import urllib
import werkzeug
from openerp import tools
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models.website import slug
from openerp.osv import osv
from openerp.osv.orm import browse_record
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
@@ -47,8 +49,9 @@ class WebsiteBlog(http.Controller):
_blog_post_per_page = 20
_post_comment_per_page = 10
def nav_list(self, domain=[]):
def nav_list(self, blog=None):
blog_post_obj = request.registry['blog.post']
domain = blog and [('blog_id', '=', blog.id)] or []
groups = blog_post_obj.read_group(
request.cr, request.uid, domain, ['name', 'create_date'],
groupby="create_date", orderby="create_date desc", context=request.context)
@@ -85,8 +88,8 @@ class WebsiteBlog(http.Controller):
@http.route([
'/blog/<model("blog.blog"):blog>',
'/blog/<model("blog.blog"):blog>/page/<int:page>',
'/blog/<model("blog.blog"):blog>/tag/<model("blog.tag"):tag>',
'/blog/<model("blog.blog"):blog>/tag/<model("blog.tag"):tag>/page/<int:page>',
'/blog/<model("blog.blog"):blog>/tag/<string:tag>',
'/blog/<model("blog.blog"):blog>/tag/<string:tag>/page/<int:page>',
], type='http', auth="public", website=True)
def blog(self, blog=None, tag=None, page=1, **opt):
""" Prepare all values to display the blog.
@@ -96,7 +99,8 @@ class WebsiteBlog(http.Controller):
- 'blog': current blog
- 'blogs': all blogs for navigation
- 'pager': pager of posts
- 'tag': current tag
- 'active_tag_ids' : list of active tag ids,
- 'tags_list' : function to built the comma-separated tag list ids (for the url),
- 'tags': all tags, for navigation
- 'nav_list': a dict [year][month] for archives navigation
- 'date': date_begin optional parameter, used in archives navigation
@@ -111,18 +115,17 @@ class WebsiteBlog(http.Controller):
blog_ids = blog_obj.search(cr, uid, [], order="create_date asc", context=context)
blogs = blog_obj.browse(cr, uid, blog_ids, context=context)
# build the domain for blog post to display
domain = []
active_tag_ids = tag and map(int, tag.split(',')) or []
if active_tag_ids:
domain += [('tag_ids', 'in', active_tag_ids)]
if blog:
domain += [('blog_id', '=', blog.id)]
if tag:
domain += [('tag_ids', 'in', tag.id)]
blogs_by_month = self.nav_list(domain)
if date_begin and date_end:
domain += [("create_date", ">=", date_begin), ("create_date", "<=", date_end)]
blog_url = QueryURL('', ['blog', 'tag'], blog=blog, tag=tag, date_begin=date_begin, date_end=date_end)
post_url = QueryURL('', ['blogpost'], tag_id=tag and tag.id or None, date_begin=date_begin, date_end=date_end)
blog_post_ids = blog_post_obj.search(cr, uid, domain, order="create_date desc", context=context)
blog_posts = blog_post_obj.browse(cr, uid, blog_post_ids, context=context)
@@ -137,18 +140,28 @@ class WebsiteBlog(http.Controller):
pager_end = page * self._blog_post_per_page
blog_posts = blog_posts[pager_begin:pager_end]
tags = blog.all_tags()[blog.id]
all_tags = blog.all_tags()[blog.id]
# function to create the string list of tag ids, and toggle a given one.
# used in the 'Tags Cloud' template.
def tags_list(tag_ids, current_tag):
tag_ids = list(tag_ids) # required to avoid using the same list
if current_tag in tag_ids:
tag_ids.remove(current_tag)
else:
tag_ids.append(current_tag)
return ','.join(map(str, tag_ids))
values = {
'blog': blog,
'blogs': blogs,
'tags': tags,
'tag': tag,
'tags': all_tags,
'active_tag_ids': active_tag_ids,
'tags_list' : tags_list,
'blog_posts': blog_posts,
'pager': pager,
'nav_list': blogs_by_month,
'blog_url': blog_url,
'post_url': post_url,
'nav_list': self.nav_list(blog),
'blog_url': blog_url,
'date': date_begin,
}
response = request.website.render("website_blog.blog_post_short", values)
@@ -192,7 +205,6 @@ class WebsiteBlog(http.Controller):
tag = None
if tag_id:
tag = request.registry['blog.tag'].browse(request.cr, request.uid, int(tag_id), context=request.context)
post_url = QueryURL('', ['blogpost'], blogpost=blog_post, tag_id=tag_id, date_begin=date_begin, date_end=date_end)
blog_url = QueryURL('', ['blog', 'tag'], blog=blog_post.blog_id, tag=tag, date_begin=date_begin, date_end=date_end)
if not blog_post.blog_id.id == blog.id:
@@ -219,11 +231,10 @@ class WebsiteBlog(http.Controller):
'blog': blog,
'blog_post': blog_post,
'main_object': blog_post,
'nav_list': self.nav_list([('blog_id', '=', blog.id)]),
'enable_editor': enable_editor,
'nav_list': self.nav_list(blog),
'enable_editor': enable_editor,
'next_post': next_post,
'date': date_begin,
'post_url': post_url,
'blog_url': blog_url,
'pager': pager,
'comments': comments,
@@ -240,38 +251,44 @@ class WebsiteBlog(http.Controller):
},context=context)
return response
def _blog_post_message(self, user, blog_post_id=0, **post):
def _blog_post_message(self, uid, blog_post_id, message_content, **post):
cr, uid, context = request.cr, request.uid, request.context
blog_post = request.registry['blog.post']
partner_obj = request.registry['res.partner']
BlogPost = request.registry['blog.post']
User = request.registry['res.users']
# for now, only portal and user can post comment on blog post.
if uid == request.website.user_id.id:
raise osv.except_osv(_('Error!'), _('Public user cannot post comments on blog post.'))
# get the partner of the current user
user = User.browse(cr, uid, uid, context=context)
partner_id = user.partner_id.id
if uid != request.website.user_id.id:
partner_ids = [user.partner_id.id]
else:
partner_ids = blog_post._find_partner_from_emails(
cr, SUPERUSER_ID, 0, [post.get('email')], context=context)
if not partner_ids or not partner_ids[0]:
partner_ids = [partner_obj.create(cr, SUPERUSER_ID, {'name': post.get('name'), 'email': post.get('email')}, context=context)]
message_id = blog_post.message_post(
cr, SUPERUSER_ID, int(blog_post_id),
body=post.get('comment'),
message_id = BlogPost.message_post(
cr, uid, int(blog_post_id),
body=message_content,
type='comment',
subtype='mt_comment',
author_id=partner_ids[0],
author_id=partner_id,
path=post.get('path', False),
context=context)
return message_id
@http.route(['/blogpost/comment'], type='http', auth="public", methods=['POST'], website=True)
def blog_post_comment(self, blog_post_id=0, **post):
@http.route(['/blog/post_comment'], type='http', auth="public", methods=['GET','POST'], website=True)
def blog_post_comment(self, blog_post_id=0, **kw):
cr, uid, context = request.cr, request.uid, request.context
if post.get('comment'):
user = request.registry['res.users'].browse(cr, uid, uid, context=context)
blog_post = request.registry['blog.post']
blog_post.check_access_rights(cr, uid, 'read')
self._blog_post_message(user, blog_post_id, **post)
return werkzeug.utils.redirect(request.httprequest.referrer + "#comments")
redirect_url = request.httprequest.referrer + "#comments"
if kw.get('comment'):
if not request.session.uid: # if not logged, redirect to the login form, keeping the url to post the comment
kw['comment'] = kw.get('comment').encode('utf8') # avoid crash from urlencode if accent
url = '/blog/post_comment/?blog_post_id=%s&%s' % (blog_post_id, urllib.urlencode(kw))
redirect_url = '/web/login?redirect=%s' % urllib.quote(url)
else:
blog_post_id = int(blog_post_id)
blog_post = request.registry['blog.post']
post = blog_post.browse(cr, uid, blog_post_id, context=context)
self._blog_post_message(uid, blog_post_id, kw.get('comment'), **kw)
redirect_url = "/blog/%s/post/%s#comments" % (slug(post.blog_id), slug(post))
return werkzeug.utils.redirect(redirect_url)
def _get_discussion_detail(self, ids, publish=False, **post):
cr, uid, context = request.cr, request.uid, request.context
@@ -291,15 +308,14 @@ class WebsiteBlog(http.Controller):
})
return values
@http.route(['/blogpost/post_discussion'], type='json', auth="public", website=True)
@http.route(['/blog/post_discussion'], type='json', auth="public", website=True)
def post_discussion(self, blog_post_id, **post):
cr, uid, context = request.cr, request.uid, request.context
publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher')
user = request.registry['res.users'].browse(cr, uid, uid, context=context)
id = self._blog_post_message(user, blog_post_id, **post)
id = self._blog_post_message(uid, blog_post_id, post.get('comment'), **post)
return self._get_discussion_detail([id], publish, **post)
@http.route('/blogpost/new', type='http', auth="public", website=True)
@http.route('/blog/<int:blog_id>/post/new', type='http', auth="public", website=True)
def blog_post_create(self, blog_id, **post):
cr, uid, context = request.cr, request.uid, request.context
new_blog_post_id = request.registry['blog.post'].create(cr, uid, {
@@ -312,7 +328,7 @@ class WebsiteBlog(http.Controller):
new_blog_post = request.registry['blog.post'].browse(cr, uid, new_blog_post_id, context=context)
return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(new_blog_post.blog_id), slug(new_blog_post)))
@http.route('/blogpost/duplicate', type='http', auth="public", website=True)
@http.route('/blog/post_duplicate', type='http', auth="public", website=True)
def blog_post_copy(self, blog_post_id, **post):
""" Duplicate a blog.
@@ -322,12 +338,12 @@ class WebsiteBlog(http.Controller):
"""
cr, uid, context = request.cr, request.uid, request.context
create_context = dict(context, mail_create_nosubscribe=True)
nid = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
nid = request.registry['blog.post'].copy(cr, uid, int(blog_post_id), {}, context=create_context)
new_blog_post = request.registry['blog.post'].browse(cr, uid, nid, context=context)
post = request.registry['blog.post'].browse(cr, uid, nid, context)
return werkzeug.utils.redirect("/blog/%s/post/%s?enable_editor=1" % (slug(post.blog_id), slug(new_blog_post)))
@http.route('/blogpost/get_discussion/', type='json', auth="public", website=True)
@http.route('/blog/post_get_discussion/', type='json', auth="public", website=True)
def discussion(self, post_id=0, path=None, count=False, **post):
cr, uid, context = request.cr, request.uid, request.context
mail_obj = request.registry.get('mail.message')
@@ -341,7 +357,7 @@ class WebsiteBlog(http.Controller):
return ids
return self._get_discussion_detail(ids, publish, **post)
@http.route('/blogpost/get_discussions/', type='json', auth="public", website=True)
@http.route('/blog/post_get_discussions/', type='json', auth="public", website=True)
def discussions(self, post_id=0, paths=None, count=False, **post):
ret = []
for path in paths:
@@ -349,7 +365,7 @@ class WebsiteBlog(http.Controller):
ret.append({"path": path, "val": result})
return ret
@http.route('/blogpost/change_background', type='json', auth="public", website=True)
@http.route('/blog/post_change_background', type='json', auth="public", website=True)
def change_bg(self, post_id=0, image=None, **post):
if not post_id:
return False
@@ -4,7 +4,6 @@
<record id="blog_blog_1" model="blog.blog">
<field name="name">Our News</field>
<field name="subtitle">Sharing our evolution with passion</field>
<field name="description">Presentation of new Odoo features</field>
</record>
<record id="menu_news" model="website.menu">
+3 -1
View File
@@ -20,7 +20,6 @@ class Blog(osv.Model):
_columns = {
'name': fields.char('Blog Name', required=True),
'subtitle': fields.char('Blog Subtitle'),
'description': fields.text('Description'),
}
def all_tags(self, cr, uid, ids, min_limit=1, context=None):
@@ -69,6 +68,9 @@ class BlogPost(osv.Model):
_inherit = ['mail.thread', 'website.seo.metadata']
_order = 'id DESC'
_mail_post_access = 'read'
def _compute_ranking(self, cr, uid, ids, name, arg, context=None):
res = {}
for blog_post in self.browse(cr, uid, ids, context=context):
@@ -15,7 +15,7 @@ $(document).ready(function() {
.call('name_search', [], { context: website.get_context() });
},
}).then(function (cat_id) {
document.location = '/blogpost/new?blog_id=' + cat_id;
document.location = '/blog/' + cat_id + '/post/new';
});
},
});
@@ -32,7 +32,7 @@ $(document).ready(function() {
save : function() {
var res = this._super();
if ($('.cover').length) {
openerp.jsonRpc("/blogpost/change_background", 'call', {
openerp.jsonRpc("/blog/post_change_background", 'call', {
'post_id' : $('#blog_post_name').attr('data-oe-id'),
'image' : $('.cover').css('background-image').replace(/url\(|\)|"|'/g,''),
});
@@ -1,8 +1,8 @@
// Inspired from https://github.com/tsi/inlineDisqussions
(function () {
'use strict';
var website = openerp.website,
qweb = openerp.qweb;
@@ -51,7 +51,7 @@
},
prepare_data : function(identifier, comment_count) {
var self = this;
return openerp.jsonRpc("/blogpost/get_discussion/", 'call', {
return openerp.jsonRpc("/blog/post_get_discussion/", 'call', {
'post_id': self.settings.post_id,
'path': identifier,
'count': comment_count, //if true only get length of total comment, display on discussion thread.
@@ -59,7 +59,7 @@
},
prepare_multi_data : function(identifiers, comment_count) {
var self = this;
return openerp.jsonRpc("/blogpost/get_discussions/", 'call', {
return openerp.jsonRpc("/blog/post_get_discussions/", 'call', {
'post_id': self.settings.post_id,
'paths': identifiers,
'count': comment_count, //if true only get length of total comment, display on discussion thread.
@@ -136,7 +136,7 @@
comment += qweb.render("website.blog_discussion.comment", {'res': res});
});
$('.discussion_history').html('<ul class="media-list">'+comment+'</ul>');
self.create_popover(elt, identifier);
self.create_popover(elt, identifier);
// Add 'active' class.
$('a.discussion-link, a.main-discussion-link').removeClass('active').filter(source).addClass('active');
elt.popover('hide').filter(source).popover('show');
@@ -162,9 +162,9 @@
var author_name = $('.popover input#author_name').val();
var author_email = $('.popover input#author_email').val();
if(!comment || !author_name || !author_email){
if (!author_name)
if (!author_name)
$('div#author_name').addClass('has-error');
else
else
$('div#author_name').removeClass('has-error');
if (!author_email)
$('div#author_email').addClass('has-error');
@@ -193,7 +193,7 @@
var self = this;
var val = self.validate(self.settings.public_user)
if(!val) return
openerp.jsonRpc("/blogpost/post_discussion", 'call', {
openerp.jsonRpc("/blog/post_discussion", 'call', {
'blog_post_id': self.settings.post_id,
'path': self.discus_identifier,
'comment': val[0],
@@ -211,7 +211,7 @@
$('a[data-discus-identifier="'+ self.discus_identifier+'"]').popover('destroy');
$('a.discussion-link').removeClass('active');
}
});
})();
@@ -19,7 +19,6 @@ class TestWebsiteBlogFlow(TestWebsiteBlogCommon):
# Create a new blog, subscribe the employee to the blog
test_blog = self.env['blog.blog'].sudo(self.user_blogmanager).create({
'name': 'New Blog',
'description': 'Presentation of new Odoo features'
})
self.assertIn(
self.user_blogmanager.partner_id, test_blog.message_follower_ids,
@@ -102,13 +102,15 @@
<!-- Blog Post List: Displaying a list of Blog Posts -->
<template id="blog_post_short" name="Blog Posts">
<t t-call="website_blog.index">
<div class="container">
<t t-call="website.pager" >
<t t-set="classname">pull-right</t>
</t>
</div>
<div class="oe_structure">
<section class="mb0">
<div class="container">
<div class="row">
<t t-call="website.pager" >
<t t-set="classname">pull-right</t>
</t>
<div class="col-md-12 mb32 mt16 text-center">
<h1 t-field="blog.name"/>
<h3 class="text-muted" t-field="blog.subtitle"/>
@@ -151,6 +153,11 @@
<t t-if="len(blog_post.message_ids) &lt;= 1" >comment</t>
<t t-if="len(blog_post.message_ids) > 1">comments</t>
</span>
<span t-if="blog_post.visits &gt; 0">
&#5760; <t t-esc="blog_post.visits"/>
<t t-if="blog_post.visits &lt;= 1" >view</t>
<t t-if="blog_post.visits > 1">views</t>
</span>
<span t-if="not blog_post.website_published" class="label label-danger">not published</span>
</div>
@@ -172,7 +179,7 @@
<p class="post-meta text-muted text-center" t-if="len(blog_post.tag_ids)">
<span class="fa fa-tags"/>
<t t-foreach="blog_post.tag_ids" t-as="tag">
<a t-attf-href="#{blog_url(tag=tag)}" t-esc="tag.name"/> &amp;nbsp;
<a t-attf-href="#{blog_url(tag=tag.id, date_begin=False, date_end=False)}" t-esc="tag.name"/> &amp;nbsp;
</t>
</p>
</xpath>
@@ -198,7 +205,7 @@
<t t-set="object" t-value="blog_post"/>
<t t-set="publish_edit" t-value="True"/>
<li>
<form class="duplicate hidden" action="/blogpost/duplicate">
<form class="duplicate hidden" action="/blog/post_duplicate">
<input name="blog_post_id" t-att-value="blog_post.id"/>
</form>
<a href="#" class="duplicate" onclick="$(this).prev('form').submit()">Duplicate</a>
@@ -291,11 +298,10 @@
<!-- Options: Blog Post: user can reply -->
<template id="opt_blog_post_complete_comment" name="Allow blog post comment"
inherit_id="website_blog.blog_post_complete" active="False" customize_show="True"
groups="website_mail.group_comment">
inherit_id="website_blog.blog_post_complete" active="False" customize_show="True">
<xpath expr="//ul[@id='comments-list']" position="before">
<section class="mb32 read_width css_editable_mode_hidden">
<form id="comment" t-attf-action="/blogpost/comment" method="POST">
<form id="comment" t-attf-action="/blog/post_comment" method="POST">
<div class="media">
<span class="pull-left">
<img class="img img-circle media-object" t-att-src="website.image_url(user_id.partner_id, 'image_small')" style="width: 30px"/>
@@ -337,7 +343,7 @@
<p class="post-meta text-muted text-center" t-if="len(blog_post.tag_ids)">
<span class="fa fa-tags"/>
<t t-foreach="blog_post.tag_ids" t-as="tag">
<a t-attf-href="#{blog_url(tag=tag)}" t-esc="tag.name"/> &amp;nbsp;
<a t-attf-href="#{blog_url(tag=tag.id)}" t-esc="tag.name"/> &amp;nbsp;
</t>
</p>
</xpath>
@@ -372,8 +378,10 @@
<h4>Tags</h4>
<ul class="nav nav-pills nav-stacked">
<t t-foreach="tags" t-as="nav_tag">
<li t-att-class="tag and tag.id == nav_tag.id and 'active' or None" style="display: inline-block;">
<a t-attf-href="#{blog_url(tag=nav_tag)}"><span t-field="nav_tag.name"/></a>
<li t-att-class="nav_tag.id in active_tag_ids and 'active' or None" style="display: inline-block;">
<a t-attf-href="#{blog_url(tag=tags_list(active_tag_ids, nav_tag.id))}">
<span t-field="nav_tag.name"/>
</a>
</li>
</t>
</ul>
@@ -389,9 +397,16 @@
<h4>Archives</h4>
<ul class="nav nav-pills nav-stacked">
<t t-foreach="nav_list" t-as="months">
<li t-att-class="months['date_begin'] == date and 'active' or None">
<a t-ignore="True" t-attf-href="#{blog_url(date_begin=months['date_begin'], date_end=months['date_end'])}"><t t-esc="months['create_date']"/><span class="pull-right badge" t-esc="months['create_date_count']"/></a>
</li>
<t t-if="months['date_begin'] == date">
<li class="active">
<a t-ignore="True" t-attf-href="#{blog_url(date_begin=False, date_end=False)}"><t t-esc="months['create_date']"/><span class="pull-right badge" t-esc="months['create_date_count']"/></a>
</li>
</t>
<t t-if="months['date_begin'] != date">
<li>
<a t-ignore="True" t-attf-href="#{blog_url(date_begin=months['date_begin'], date_end=months['date_end'])}"><t t-esc="months['create_date']"/><span class="pull-right badge" t-esc="months['create_date_count']"/></a>
</li>
</t>
</t>
</ul>
</section>
@@ -451,7 +466,7 @@
<ul class="nav nav-pills nav-stacked">
<t t-foreach="blogs" t-as="nav_blog">
<li t-att-class="nav_blog.id == blog.id and 'active' or ''">
<a t-attf-href="#{blog_url(blog=nav_blog)}">
<a t-attf-href="#{blog_url(blog=nav_blog, tag=False, date_begin=False, date_end=False)}">
<span t-field="nav_blog.name"/>
</a>
</li>
@@ -22,12 +22,11 @@
<sheet>
<group>
<field name="name"/>
<field name="description"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}' placeholder="Send a message to the group"/>
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}'/>
</div>
</form>
</field>
@@ -74,7 +73,7 @@
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}' placeholder="Send a message to the group"/>
<field name="message_ids" widget="mail_thread" options='{"thread_level": 1}'/>
</div>
</form>
</field>
-1
View File
@@ -33,7 +33,6 @@
'views/website_email_designer.xml',
'views/email_template_view.xml',
'data/mail_groups.xml',
'security/website_mail.xml',
],
'qweb': [
'static/src/xml/website_mail.xml'
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="group_comment" model="res.groups">
<field name="name">Website Comments</field>
<field name="comment">Allows website visitors to post comments on blogs, etc.</field>
</record>
<record id="base.group_user" model="res.groups">
<field name="implied_ids" eval="[(4, ref('website_mail.group_comment'))]"/>
</record>
</data>
</openerp>