[IMP] website_blog: path computation (unique key) for paragraphs in medium-like blogs
is now done server-side and stored directly in the html content, as post processing. The front-end attaches messages based on the attribute data-chatter-id, but do not compute the attribute itself anymore. Misc cleaning of code. bzr revid: tde@openerp.com-20140403112656-ane3ovhh70qdc8b4
This commit is contained in:
parent
eccbb272ee
commit
8f105b6624
|
@ -210,7 +210,6 @@ class WebsiteBlog(http.Controller):
|
||||||
('id', 'not in', visited_ids),
|
('id', 'not in', visited_ids),
|
||||||
], order='ranking desc', limit=1, context=context)
|
], order='ranking desc', limit=1, context=context)
|
||||||
next_post = next_post_id and blog_post_obj.browse(cr, uid, next_post_id[0], context=context) or False
|
next_post = next_post_id and blog_post_obj.browse(cr, uid, next_post_id[0], context=context) or False
|
||||||
print next_post
|
|
||||||
|
|
||||||
values = {
|
values = {
|
||||||
'tags': tags,
|
'tags': tags,
|
||||||
|
@ -259,7 +258,7 @@ class WebsiteBlog(http.Controller):
|
||||||
type='comment',
|
type='comment',
|
||||||
subtype='mt_comment',
|
subtype='mt_comment',
|
||||||
author_id=partner_ids[0],
|
author_id=partner_ids[0],
|
||||||
discussion=post.get('discussion'),
|
path=post.get('path', False),
|
||||||
context=dict(context, mail_create_nosubcribe=True))
|
context=dict(context, mail_create_nosubcribe=True))
|
||||||
return message_id
|
return message_id
|
||||||
|
|
||||||
|
@ -327,10 +326,10 @@ class WebsiteBlog(http.Controller):
|
||||||
return werkzeug.utils.redirect("/blog/%s/post/%s/?enable_editor=1" % (post.blog_id.id, nid))
|
return werkzeug.utils.redirect("/blog/%s/post/%s/?enable_editor=1" % (post.blog_id.id, nid))
|
||||||
|
|
||||||
@http.route('/blogpost/get_discussion/', type='json', auth="public", website=True)
|
@http.route('/blogpost/get_discussion/', type='json', auth="public", website=True)
|
||||||
def discussion(self, post_id=0, discussion=None, count=False, **post):
|
def discussion(self, post_id=0, path=None, count=False, **post):
|
||||||
cr, uid, context = request.cr, request.uid, request.context
|
cr, uid, context = request.cr, request.uid, request.context
|
||||||
mail_obj = request.registry.get('mail.message')
|
mail_obj = request.registry.get('mail.message')
|
||||||
domain = [('res_id', '=', int(post_id)) ,('model','=','blog.post'), ('discussion_key', '=', discussion)]
|
domain = [('res_id', '=', int(post_id)), ('model', '=', 'blog.post'), ('path', '=', path)]
|
||||||
#check current user belongs to website publisher group
|
#check current user belongs to website publisher group
|
||||||
publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher')
|
publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher')
|
||||||
if not publish:
|
if not publish:
|
||||||
|
|
|
@ -7,6 +7,7 @@ class MailMessage(osv.Model):
|
||||||
_inherit = 'mail.message'
|
_inherit = 'mail.message'
|
||||||
|
|
||||||
_columns = {
|
_columns = {
|
||||||
'discussion_key': fields.char('Discussion Key',
|
'path': fields.char(
|
||||||
help='Used in Blogs to display messages in a group based on their discussion key.'),
|
'Discussion Path', select=1,
|
||||||
|
help='Used to display messages in a paragraph-based chatter using a unique path;'),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import difflib
|
import difflib
|
||||||
|
import lxml
|
||||||
import random
|
import random
|
||||||
|
|
||||||
from openerp import tools
|
from openerp import tools
|
||||||
|
from openerp import SUPERUSER_ID
|
||||||
from openerp.osv import osv, fields
|
from openerp.osv import osv, fields
|
||||||
from openerp.tools.translate import _
|
from openerp.tools.translate import _
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ class BlogPost(osv.Model):
|
||||||
'website_message_ids': fields.one2many(
|
'website_message_ids': fields.one2many(
|
||||||
'mail.message', 'res_id',
|
'mail.message', 'res_id',
|
||||||
domain=lambda self: [
|
domain=lambda self: [
|
||||||
'&', '&', ('model', '=', self._name), ('type', '=', 'comment'), ('discussion_key', '=', False)
|
'&', '&', ('model', '=', self._name), ('type', '=', 'comment'), ('path', '=', False)
|
||||||
],
|
],
|
||||||
string='Website Messages',
|
string='Website Messages',
|
||||||
help="Website communication history",
|
help="Website communication history",
|
||||||
|
@ -103,6 +105,59 @@ class BlogPost(osv.Model):
|
||||||
'author_id': lambda self, cr, uid, ctx=None: self.pool['res.users'].browse(cr, uid, uid, context=ctx).partner_id.id,
|
'author_id': lambda self, cr, uid, ctx=None: self.pool['res.users'].browse(cr, uid, uid, context=ctx).partner_id.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def html_tag_nodes(self, html, attribute=None, tags=None, context=None):
|
||||||
|
""" Processing of html content to tag paragraphs and set them an unique
|
||||||
|
ID.
|
||||||
|
:return result: (html, mappin), where html is the updated html with ID
|
||||||
|
and mapping is a list of (old_ID, new_ID), where old_ID
|
||||||
|
is None is the paragraph is a new one. """
|
||||||
|
mapping = []
|
||||||
|
if not html:
|
||||||
|
return html, mapping
|
||||||
|
if tags is None:
|
||||||
|
tags = ['p']
|
||||||
|
if attribute is None:
|
||||||
|
attribute = 'data-unique-id'
|
||||||
|
counter = 0
|
||||||
|
|
||||||
|
# form a tree
|
||||||
|
root = lxml.html.fragment_fromstring(html, create_parent='div')
|
||||||
|
if not len(root) and root.text is None and root.tail is None:
|
||||||
|
return html, mapping
|
||||||
|
|
||||||
|
# check all nodes, replace :
|
||||||
|
# - img src -> check URL
|
||||||
|
# - a href -> check URL
|
||||||
|
for node in root.iter():
|
||||||
|
if not node.tag in tags:
|
||||||
|
continue
|
||||||
|
ancestor_tags = [parent.tag for parent in node.iterancestors()]
|
||||||
|
ancestor_tags.pop()
|
||||||
|
new_attribute = '/'.join(reversed(ancestor_tags))
|
||||||
|
old_attribute = node.get(attribute)
|
||||||
|
node.set(attribute, new_attribute)
|
||||||
|
mapping.append((old_attribute, counter))
|
||||||
|
counter += 1
|
||||||
|
|
||||||
|
html = lxml.html.tostring(root, pretty_print=False, method='html')
|
||||||
|
# this is ugly, but lxml/etree tostring want to put everything in a 'div' that breaks the editor -> remove that
|
||||||
|
if html.startswith('<div>') and html.endswith('</div>'):
|
||||||
|
html = html[5:-6]
|
||||||
|
return html, mapping
|
||||||
|
|
||||||
|
def _postproces_content(self, cr, uid, id, content=None, context=None):
|
||||||
|
if content is None:
|
||||||
|
content = self.browse(cr, uid, id, context=context).content
|
||||||
|
if content is False:
|
||||||
|
return content
|
||||||
|
content, mapping = self.html_tag_nodes(content, attribute='data-chatter-id', tags=['p'], context=context)
|
||||||
|
for old_attribute, new_attribute in mapping:
|
||||||
|
if not old_attribute:
|
||||||
|
continue
|
||||||
|
msg_ids = self.pool['mail.message'].search(cr, SUPERUSER_ID, [('path', '=', old_attribute)], context=context)
|
||||||
|
self.pool['mail.message'].write(cr, SUPERUSER_ID, msg_ids, {'path': new_attribute}, context=context)
|
||||||
|
return content
|
||||||
|
|
||||||
def create_history(self, cr, uid, ids, vals, context=None):
|
def create_history(self, cr, uid, ids, vals, context=None):
|
||||||
for i in ids:
|
for i in ids:
|
||||||
history = self.pool.get('blog.post.history')
|
history = self.pool.get('blog.post.history')
|
||||||
|
@ -116,12 +171,16 @@ class BlogPost(osv.Model):
|
||||||
def create(self, cr, uid, vals, context=None):
|
def create(self, cr, uid, vals, context=None):
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
if 'content' in vals:
|
||||||
|
vals['content'] = self._postproces_content(cr, uid, None, vals['content'], context=context)
|
||||||
create_context = dict(context, mail_create_nolog=True)
|
create_context = dict(context, mail_create_nolog=True)
|
||||||
post_id = super(BlogPost, self).create(cr, uid, vals, context=create_context)
|
post_id = super(BlogPost, self).create(cr, uid, vals, context=create_context)
|
||||||
self.create_history(cr, uid, [post_id], vals, context)
|
self.create_history(cr, uid, [post_id], vals, context)
|
||||||
return post_id
|
return post_id
|
||||||
|
|
||||||
def write(self, cr, uid, ids, vals, context=None):
|
def write(self, cr, uid, ids, vals, context=None):
|
||||||
|
if 'content' in vals:
|
||||||
|
vals['content'] = self._postproces_content(cr, uid, None, vals['content'], context=context)
|
||||||
result = super(BlogPost, self).write(cr, uid, ids, vals, context)
|
result = super(BlogPost, self).write(cr, uid, ids, vals, context)
|
||||||
self.create_history(cr, uid, ids, vals, context)
|
self.create_history(cr, uid, ids, vals, context)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
var self = this ;
|
var self = this ;
|
||||||
self.discus_identifier;
|
self.discus_identifier;
|
||||||
var defaults = {
|
var defaults = {
|
||||||
identifier: 'name',
|
|
||||||
position: 'right',
|
position: 'right',
|
||||||
post_id: $('#blog_post_name').attr('data-blog-id'),
|
post_id: $('#blog_post_name').attr('data-blog-id'),
|
||||||
content : false,
|
content : false,
|
||||||
|
@ -23,7 +22,7 @@
|
||||||
do_render: function(data) {
|
do_render: function(data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if ($('#discussions_wrapper').length === 0 && self.settings.content.length > 0) {
|
if ($('#discussions_wrapper').length === 0 && self.settings.content.length > 0) {
|
||||||
$('<div id="discussions_wrapper"></div>').appendTo($('#blog_content'));
|
$('<div id="discussions_wrapper"></div>').insertAfter($('#blog_content'));
|
||||||
}
|
}
|
||||||
// Attach a discussion to each paragraph.
|
// Attach a discussion to each paragraph.
|
||||||
$(self.settings.content).each(function(i) {
|
$(self.settings.content).each(function(i) {
|
||||||
|
@ -36,8 +35,8 @@
|
||||||
}
|
}
|
||||||
if(!$(event.target).hasClass('discussion-link') && !$(event.target).parents('.popover').length){
|
if(!$(event.target).hasClass('discussion-link') && !$(event.target).parents('.popover').length){
|
||||||
if($('.move_discuss').length){
|
if($('.move_discuss').length){
|
||||||
$('.js_discuss').next().removeClass('move_discuss');
|
$('[enable_chatter_discuss=True]').removeClass('move_discuss');
|
||||||
$('.js_discuss').next().animate({
|
$('[enable_chatter_discuss=True]').animate({
|
||||||
'marginLeft': "+=40%"
|
'marginLeft': "+=40%"
|
||||||
});
|
});
|
||||||
$('#discussions_wrapper').animate({
|
$('#discussions_wrapper').animate({
|
||||||
|
@ -47,30 +46,22 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
prepare_data : function(identifier,comment_count) {
|
prepare_data : function(identifier, comment_count) {
|
||||||
var self = this;
|
var self = this;
|
||||||
return openerp.jsonRpc("/blogpost/get_discussion/", 'call', {
|
return openerp.jsonRpc("/blogpost/get_discussion/", 'call', {
|
||||||
'post_id': self.settings.post_id,
|
'post_id': self.settings.post_id,
|
||||||
'discussion':identifier,
|
'path': identifier,
|
||||||
'count' : comment_count, //if true only get length of total comment, display on discussion thread.
|
'count': comment_count, //if true only get length of total comment, display on discussion thread.
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
discussion_handler : function(i, node) {
|
discussion_handler : function(i, node) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var identifier;
|
var identifier = node.attr('data-chatter-id');
|
||||||
// You can force a specific identifier by adding an attribute to the paragraph.
|
if (identifier) {
|
||||||
if (node.attr('data-discus-identifier')) {
|
self.prepare_data(identifier, true).then( function (data) {
|
||||||
identifier = node.attr('data-discus-identifier');
|
self.prepare_discuss_link(data, identifier, node);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
while ($('[data-discus-identifier="' + self.settings.identifier + '-' + i + '"]').length > 0) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
identifier = self.settings.identifier + '-' + i;
|
|
||||||
}
|
|
||||||
self.prepare_data(identifier,true).then(function(data){
|
|
||||||
self.prepare_discuss_link(data,identifier,node)
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
prepare_discuss_link : function(data, identifier, node) {
|
prepare_discuss_link : function(data, identifier, node) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -79,7 +70,7 @@
|
||||||
.attr('data-discus-identifier', identifier)
|
.attr('data-discus-identifier', identifier)
|
||||||
.attr('data-discus-position', self.settings.position)
|
.attr('data-discus-position', self.settings.position)
|
||||||
.text(data > 0 ? data : '+')
|
.text(data > 0 ? data : '+')
|
||||||
.attr('data-contentwrapper','.mycontent')
|
.attr('data-contentwrapper', '.mycontent')
|
||||||
.wrap('<div class="discussion" />')
|
.wrap('<div class="discussion" />')
|
||||||
.parent()
|
.parent()
|
||||||
.appendTo('#discussions_wrapper');
|
.appendTo('#discussions_wrapper');
|
||||||
|
@ -87,7 +78,8 @@
|
||||||
'top': node.offset().top,
|
'top': node.offset().top,
|
||||||
'left': self.settings.position == 'right' ? node.outerWidth() + node.offset().left: node.offset().left - a.outerWidth()
|
'left': self.settings.position == 'right' ? node.outerWidth() + node.offset().left: node.offset().left - a.outerWidth()
|
||||||
});
|
});
|
||||||
node.attr('data-discus-identifier', identifier).mouseover(function() {
|
// node.attr('data-discus-identifier', identifier)
|
||||||
|
node.mouseover(function() {
|
||||||
a.addClass("hovered");
|
a.addClass("hovered");
|
||||||
}).mouseout(function() {
|
}).mouseout(function() {
|
||||||
a.removeClass("hovered");
|
a.removeClass("hovered");
|
||||||
|
@ -96,8 +88,8 @@
|
||||||
a.delegate('a.discussion-link', "click", function(e) {
|
a.delegate('a.discussion-link', "click", function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if(!$('.move_discuss').length){
|
if(!$('.move_discuss').length){
|
||||||
$('.js_discuss').next().addClass('move_discuss');
|
$('[enable_chatter_discuss=True]').addClass('move_discuss');
|
||||||
$('.js_discuss').next().animate({
|
$('[enable_chatter_discuss=True]').animate({
|
||||||
'marginLeft': "-=40%"
|
'marginLeft': "-=40%"
|
||||||
});
|
});
|
||||||
$('#discussions_wrapper').animate({
|
$('#discussions_wrapper').animate({
|
||||||
|
@ -185,7 +177,7 @@
|
||||||
if(!val) return
|
if(!val) return
|
||||||
openerp.jsonRpc("/blogpost/post_discussion", 'call', {
|
openerp.jsonRpc("/blogpost/post_discussion", 'call', {
|
||||||
'blog_post_id': self.settings.post_id,
|
'blog_post_id': self.settings.post_id,
|
||||||
'discussion': self.discus_identifier,
|
'path': self.discus_identifier,
|
||||||
'comment': val[0],
|
'comment': val[0],
|
||||||
'name' : val[1],
|
'name' : val[1],
|
||||||
'email': val[2],
|
'email': val[2],
|
||||||
|
|
|
@ -24,8 +24,8 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = $(".js_discuss").next().find('p');
|
var content = $("div[enable_chatter_discuss='True']").find('p[data-chatter-id]');
|
||||||
if(content){
|
if (content) {
|
||||||
openerp.jsonRpc("/blog/get_user/", 'call', {}).then(function(data){
|
openerp.jsonRpc("/blog/get_user/", 'call', {}).then(function(data){
|
||||||
$('#discussions_wrapper').empty();
|
$('#discussions_wrapper').empty();
|
||||||
new openerp.website.blog_discussion({'content' : content, 'public_user':data[0]});
|
new openerp.website.blog_discussion({'content' : content, 'public_user':data[0]});
|
||||||
|
|
|
@ -318,8 +318,8 @@
|
||||||
<!-- Options: Blog Post: user can add Inline Discussion -->
|
<!-- Options: Blog Post: user can add Inline Discussion -->
|
||||||
<template id="opt_blog_post_inline_discussion" name="Allow comment in text"
|
<template id="opt_blog_post_inline_discussion" name="Allow comment in text"
|
||||||
inherit_option_id="website_blog.blog_post_complete">
|
inherit_option_id="website_blog.blog_post_complete">
|
||||||
<xpath expr="//div[@id='blog_content']" position="before">
|
<xpath expr="//div[@id='blog_content']" position="attributes">
|
||||||
<div class="js_discuss"/>
|
<attribute name="enable_chatter_discuss">True</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue