diff options
| author | Thibault Delavallée <tde@openerp.com> | 2013-09-20 15:56:43 +0200 |
|---|---|---|
| committer | Thibault Delavallée <tde@openerp.com> | 2013-09-20 15:56:43 +0200 |
| commit | 4c3b516a7b988d758a67ff19242e8ed0837d756c (patch) | |
| tree | fee4ac0cf6e7c312b8b55e5abd66c6b083f7d732 | |
| parent | 6cf170312716c2a85611e9f1ff5dc838431872cb (diff) | |
[REF] website_mail refactoring
It is now called website_blog, and not based on mail.group anymore. It uses
document_page module, previously renamed blog.post (see previous commits).
Refactored controllers and views to work with the new model.
Added website_mail module, that holds mail-related stuff necessary
for the website. This is an auto-install module.
bzr revid: tde@openerp.com-20130920135643-rey5bwza2e96v7h5
21 files changed, 594 insertions, 314 deletions
diff --git a/addons/website_blog/__init__.py b/addons/website_blog/__init__.py new file mode 100644 index 00000000000..85599508fdd --- /dev/null +++ b/addons/website_blog/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +import controllers +import document_page +import res_config diff --git a/addons/website_blog/__openerp__.py b/addons/website_blog/__openerp__.py new file mode 100644 index 00000000000..67a176df083 --- /dev/null +++ b/addons/website_blog/__openerp__.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +{ + 'name': 'Blogs', + 'category': 'Website', + 'summary': 'News, Blogs, Announces, Discussions', + 'version': '1.0', + 'description': """ +OpenERP Blog +============ + + """, + 'author': 'OpenERP SA', + 'depends': ['website_mail', 'document_page'], + 'data': [ + 'website_mail_data.xml', + 'views/website_mail.xml', + 'views/res_config.xml', + 'security/website_mail.xml', + ], + 'qweb': [ + 'static/src/xml/*.xml' + ], + 'installable': True, +} diff --git a/addons/website_mail/controllers/__init__.py b/addons/website_blog/controllers/__init__.py index 8ee9bae18d9..8ee9bae18d9 100644 --- a/addons/website_mail/controllers/__init__.py +++ b/addons/website_blog/controllers/__init__.py diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py new file mode 100644 index 00000000000..564beeaed39 --- /dev/null +++ b/addons/website_blog/controllers/main.py @@ -0,0 +1,183 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +from openerp import SUPERUSER_ID +from openerp.addons.web import http +from openerp.addons.web.http import request +from openerp.addons.website import website +from openerp.tools.translate import _ +from openerp.tools.safe_eval import safe_eval + +import simplejson +import werkzeug + + +class website_mail(http.Controller): + _category_post_per_page = 2 + _post_comment_per_page = 2 + + @website.route([ + '/blog/', + '/blog/<int:category_id>/', + '/blog/<int:category_id>/<int:blog_post_id>/', + '/blog/<int:category_id>/page/<int:page>/', + '/blog/<int:category_id>/<int:blog_post_id>/page/<int:page>/' + ], type='http', auth="public") + def blog(self, category_id=None, blog_post_id=None, page=1, **post): + cr, uid, context = request.cr, request.uid, request.context + blog_post_obj = request.registry['blog.post'] + category_obj = request.registry['blog.category'] + + values = { + 'blog_ids': None, + 'blog_id': None, + 'nav_list': dict(), + 'unable_editor': post.get('unable_editor') + } + + # no category chosen: display categories + categories = None + category = None + blog_post = None + blog_posts = None + pager = None + if not category_id: + category_ids = category_obj.search(cr, uid, [], context=context) + categories = category_obj.browse(cr, uid, category_ids, context=context) + # category but no post chosen: display the last ones, create pager + elif category_id and not blog_post_id: + pager_begin = (page - 1) * self._category_post_per_page + pager_end = page * self._category_post_per_page + category = category_obj.browse(cr, uid, category_id, context=context) + blog_posts = category.blog_ids[pager_begin:pager_end] + pager = request.website.pager(url="/blog/%s/" % category_id, total=len(category.blog_ids), page=page, step=self._category_post_per_page, scope=7) + elif category_id and blog_post_id: + category = category_obj.browse(cr, uid, category_id, context=context) + blog_post = blog_post_obj.browse(cr, uid, blog_post_id, context=context) + + values.update({ + 'blog_post': blog_post, + 'blog_posts': blog_posts, + 'categories': categories, + 'category': category, + 'pager': pager, + }) + + for group in blog_post_obj.read_group(cr, uid, [], ['name', 'create_date'], groupby="create_date", orderby="create_date asc", context=context): + print 'group', group + year = group['create_date'].split(" ")[1] + if not values['nav_list'].get(year): + values['nav_list'][year] = {'name': year, 'create_date_count': 0, 'months': []} + values['nav_list'][year]['create_date_count'] += group['create_date_count'] + values['nav_list'][year]['months'].append(group) + + print values + return request.website.render("website_blog.index", values) + + # @website.route(['/blog/nav'], type='http', auth="public") + # def nav(self, **post): + # comment_ids = request.registry['mail.group'].get_public_message_ids(request.cr, request.uid, domain=safe_eval(post.get('domain')), order="create_date asc", limit=None, context=request.context) + # return simplejson.dumps(request.registry['mail.message'].read(request.cr, request.uid, comment_ids, ['website_published', 'subject', 'res_id'], request.context)) + + @website.route(['/blog/<int:category_id>/<int:blog_post_id>/post'], type='http', auth="public") + def blog_comment(self, category_id=None, blog_post_id=None, **post): + cr, uid, context = request.cr, request.uid, request.context + url = request.httprequest.host_url + request.session.body = post.get('body') + print category_id, blog_post_id, post + if request.context['is_public_user']: # purpose of this ? + return '%s/admin#action=redirect&url=%s/blog/%s/%s/post' % (url, url, category_id, blog_post_id) + + if request.session.get('body') and blog_post_id: + request.registry['blog.post'].message_post( + cr, uid, blog_post_id, + body=request.session.body, + type='comment', + subtype='mt_comment', + context=dict(context, mail_create_nosubcribe=True)) + request.session.body = False + + return self.blog(category_id=category_id, blog_post_id=blog_post_id) + + @website.route(['/blog/<int:category_id>/new'], type='http', auth="public") + def create_blog_post(self, category_id=None, **post): + cr, uid, context = request.cr, request.uid, request.context + create_context = dict(context, mail_create_nosubscribe=True) + blog_id = request.registry['blog.post'].create( + request.cr, request.uid, { + 'category_id': category_id, + 'name': _("Blog title"), + 'content': '', + 'website_published': False, + }, context=create_context) + return werkzeug.utils.redirect("/blog/%s/%s/?unable_editor=1" % (category_id, blog_id)) + + def _find_or_create_partner(self, email, context=None): + partner_obj = request.registry['res.partner'] + user_obj = request.registry['res.users'] + partner_ids = [] + if request.context['is_public_user'] and email: + partner_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("email", "=", email)], context=request.context) + if not partner_ids: + partner_ids = [partner_obj.create(request.cr, SUPERUSER_ID, {"email": email, "name": email}, request.context)] + else: + partner_ids = [user_obj.browse(request.cr, request.uid, request.uid, request.context).partner_id.id] + return partner_ids + + @website.route(['/blog/<int:category_id>/subscribe'], type='http', auth="public") + def category_subscribe(self, category_id=None, **post): + partner_ids = self._find_or_create_partner(post.get('email'), request.context) + category_obj = request.registry['blog.category'] + + category_obj.check_access_rule(request.cr, request.uid, [category_id], 'read', request.context) + category_obj.message_subscribe(request.cr, SUPERUSER_ID, [category_id], partner_ids, context=request.context) + + return self.blog(category_id=category_id) + + @website.route(['/blog/<int:category_id>/unsubscribe'], type='http', auth="public") + def category_unsubscribe(self, category_id=None, **post): + partner_ids = self._find_or_create_partner(post.get('email'), request.context) + category_obj = request.registry['blog.category'] + + category_obj.check_access_rule(request.cr, request.uid, [category_id], 'read', request.context) + category_obj.message_unsubscribe(request.cr, SUPERUSER_ID, [category_id], partner_ids, context=request.context) + + return self.blog(category_id=category_id) + + @website.route(['/blog/<int:category_id>/<int:blog_post_id>/subscribe'], type='http', auth="public") + def blog_post_subscribe(self, category_id=None, blog_post_id=None, **post): + partner_ids = self._find_or_create_partner(post.get('email'), request.context) + blog_post_obj = request.registry['blog.post'] + + blog_post_obj.check_access_rule(request.cr, request.uid, [blog_post_id], 'read', request.context) + blog_post_obj.message_subscribe(request.cr, SUPERUSER_ID, [blog_post_id], partner_ids, context=request.context) + + return self.blog(category_id=category_id, blog_post_id=blog_post_id) + + @website.route(['/blog/<int:category_id>/<int:blog_post_id>/unsubscribe'], type='http', auth="public") + def blog_post_unsubscribe(self, category_id=None, blog_post_id=None, **post): + partner_ids = self._find_or_create_partner(post.get('email'), request.context) + blog_post_obj = request.registry['blog.post'] + + blog_post_obj.check_access_rule(request.cr, request.uid, [blog_post_id], 'read', request.context) + blog_post_obj.message_unsubscribe(request.cr, SUPERUSER_ID, [blog_post_id], partner_ids, context=request.context) + + return self.blog(category_id=category_id, blog_post_id=blog_post_id) diff --git a/addons/website_blog/document_page.py b/addons/website_blog/document_page.py new file mode 100644 index 00000000000..994e1df028c --- /dev/null +++ b/addons/website_blog/document_page.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +from openerp import tools +from openerp import SUPERUSER_ID +from openerp.osv import osv, fields + + +class WebsiteDocumentPage(osv.Model): + """ Inherit document.page to add website-related columns + + - website_published: standard publish column + - website_message_ids: messages to display on website, aka comments + + """ + _inherit = "blog.post" + # maximum number of characters to display in summary + _shorten_max_char = 10 + + def get_shortened_content(self, cr, uid, ids, name, arg, context=None): + res = {} + for page in self.browse(cr, uid, ids, context=context): + try: + body_short = tools.html_email_clean(page.content, remove=True, shorten=True, max_length=self._shorten_max_char) + except Exception: + body_short = False + res[page.id] = body_short + return res + + _columns = { + 'website_published': fields.boolean( + 'Publish', help="Publish on the website" + ), + 'website_published_datetime': fields.datetime( + 'Publish Date' + ), + 'website_message_ids': fields.one2many( + 'mail.message', 'res_id', + domain=lambda self: [ + '&', ('model', '=', self._name), ('type', '=', 'comment') + ], + auto_join=True, + string='Website Messages', + help="Website communication history", + ), + 'shortened_content': fields.function( + get_shortened_content, + type='text', + string='Shortened Content', + help="Shortened content of the page that serves as a summary" + ), + } + + def img(self, cr, uid, ids, field='image_small', context=None): + post = self.browse(cr, SUPERUSER_ID, ids[0], context=context) + return "/website/image?model=%s&field=%s&id=%s" % ('res.users', field, post.create_uid.id) diff --git a/addons/website_mail/res_config.py b/addons/website_blog/res_config.py index 1b6e02e691d..1b6e02e691d 100644 --- a/addons/website_mail/res_config.py +++ b/addons/website_blog/res_config.py diff --git a/addons/website_mail/security/website_mail.xml b/addons/website_blog/security/website_mail.xml index 057329e7903..8910db80099 100644 --- a/addons/website_mail/security/website_mail.xml +++ b/addons/website_blog/security/website_mail.xml @@ -6,7 +6,7 @@ <field name="category_id" ref="base.module_category_hidden"/> </record> - <record id="website_mail_public" model="ir.rule"> +<!-- <record id="website_mail_public" model="ir.rule"> <field name="name">website_mail: Public message</field> <field name="model_id" ref="model_mail_message"/> <field name="domain_force">[('website_published', '=', True), ("model", "=", 'mail.group')]</field> @@ -15,6 +15,6 @@ <field name="perm_write" eval="False"/> <field name="perm_create" eval="False"/> <field name="perm_unlink" eval="False"/> - </record> + </record> --> </data> </openerp> diff --git a/addons/website_mail/static/description/index.html b/addons/website_blog/static/description/index.html index a900da51e24..a900da51e24 100644 --- a/addons/website_mail/static/description/index.html +++ b/addons/website_blog/static/description/index.html diff --git a/addons/website_mail/static/src/css/Makefile b/addons/website_blog/static/src/css/Makefile index 5042d6d8f54..5042d6d8f54 100644 --- a/addons/website_mail/static/src/css/Makefile +++ b/addons/website_blog/static/src/css/Makefile diff --git a/addons/website_mail/static/src/css/blog.css b/addons/website_blog/static/src/css/blog.css index 5850483761f..5850483761f 100644 --- a/addons/website_mail/static/src/css/blog.css +++ b/addons/website_blog/static/src/css/blog.css diff --git a/addons/website_blog/static/src/css/blog.sass b/addons/website_blog/static/src/css/blog.sass new file mode 100644 index 00000000000..b176996ca80 --- /dev/null +++ b/addons/website_blog/static/src/css/blog.sass @@ -0,0 +1,42 @@ +@import "compass/css3" + +.css_website_mail + .has-error + border-color: red + .css_nav_month + display: none + &:first-of-type + display: block + +/* ---- PUBLISH ---- */ +/ a[data-publish] +/ text-decoration: none !important +/ z-index: 2 +/ .label +/ padding: 5px 8px +/ .css_unpublish, .css_publish, .css_unpublished, .css_published +/ display: none +/ &[data-publish='off'] +/ .css_unpublished, &:hover .css_publish +/ display: inline +/ &:hover .css_unpublished +/ display: none +/ &[data-publish='on'] +/ .css_published, &:hover .css_unpublish +/ display: inline +/ &:hover .css_published +/ display: none + +/ [data-publish='off']:not(a) +/ >:not([data-publish]) +/ opacity: 0.5 +/ [data-publish]:not(a) +/ position: relative +/ overflow: visible +/ >[data-publish] +/ position: absolute +/ right: -6px +/ top: -10px +/ display: none + /*&:hover > [data-publish]*/ + /* display: block*/ diff --git a/addons/website_mail/static/src/js/blog.js b/addons/website_blog/static/src/js/blog.js index 4db3726123a..4db3726123a 100644 --- a/addons/website_mail/static/src/js/blog.js +++ b/addons/website_blog/static/src/js/blog.js diff --git a/addons/website_mail/views/res_config.xml b/addons/website_blog/views/res_config.xml index f4525c3411f..f4525c3411f 100644 --- a/addons/website_mail/views/res_config.xml +++ b/addons/website_blog/views/res_config.xml diff --git a/addons/website_blog/views/website_mail.xml b/addons/website_blog/views/website_mail.xml new file mode 100644 index 00000000000..c6fbbb28b38 --- /dev/null +++ b/addons/website_blog/views/website_mail.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> +<data> + + <!-- Layout add nav and footer --> + <template id="header_footer_custom" inherit_id="website.layout"> + <xpath expr="//body/header//ul[@id='top_menu']/li[last()]" position="before"> + <li><a href="/blog/%(document_page.blog_category_1)d/">News</a></li> + </xpath> + <xpath expr="//body/footer//div[@name='info']/ul" position="inside"> + <li><a href="/blog/%(document_page.blog_category_1)d/">News</a></li> + </xpath> + </template> + + <!-- Follow button --> + <template id="blog_post_unfollow" name="Follow"> + <form t-attf-action="/blog/#{object.category_id.id}/#{object.id}/unsubscribe" method="POST" class="form-inline" t-if="object.message_is_follower"> + <input type="hidden" name="email" t-att-value="subscribe" style="display: none"/> + <button type="submit" class="btn btn-sm btn-default pull-right" name="unsubscribe">Unfollow</button> + </form> + </template> + <template id="blog_post_follow" name="Follow"> + <form t-attf-action="/blog/#{object.category_id.id}/#{object.id}/subscribe" method="POST" class="form-inline" t-if="not object.message_is_follower"> + <div class="col-lg-7"> + <input placeholder="Email Address" type="email" name="email" class="form-control" t-if="is_public_user"/> + </div> + <button type="submit" class="btn btn-sm btn-primary pull-right" name="subscribe">Follow</button> + </form> + </template> + + <!-- Post --> + <template id="blog_post_short" name="Blog Post"> + <div class="media-body"> + <t t-call="website_blog.blog_post_follow"><t t-set="object" t-value="blog_post"/></t> + <t t-call="website_blog.blog_post_unfollow"><t t-set="object" t-value="blog_post"/></t> + <t t-call="website.publish"><t t-set="object" t-value="blog_post"/></t> + <small class="text-muted"> + <t t-field="blog_post.create_uid"/> on <t t-field="blog_post.create_date"/> + </small> + <h4 class="media-heading" ><a t-attf-href="/blog_post/#{blog_post.category_id.id}/#{blog_post.id}#comment" t-field="blog_post.name"></a></h4> + <div class="media"> + <div t-field="blog_post.shortened_content"/> + <small class="pull-left muted text-right"> + <a t-if="len(blog_post.message_ids) <= 1" t-attf-href="/blog/#{blog_post.category_id.id}/#{blog_post.id}#comment"><t t-esc="len(blog_post.message_ids)"/> Comment</a> + <a t-if="len(blog_post.message_ids) > 1" t-attf-href="/blog/#{blog_post.category_id.id}/#{blog_post.id}#comment"><t t-esc="len(blog_post.message_ids)"/> Comments</a> + </small> + </div> + </div> + </template> + + <template id="blog_post" name="Blog Post"> + <div class="media"> + <div class="media-body"> + <t t-call="website_blog.blog_post_follow"><t t-set="object" t-value="blog_post"/></t> + <t t-call="website_blog.blog_post_unfollow"><t t-set="object" t-value="blog_post"/></t> + <t t-call="website.publish"><t t-set="object" t-value="blog_post"/></t> + <small class="text-muted"> + <t t-field="blog_post.create_uid"/> on <t t-field="blog_post.create_date"/> + </small> + <h3 t-field="blog_post.name"/> + <div t-field="blog_post.content"/> + </div> + <ul class="media-list" id="comment"> + <li t-foreach="blog_post.website_message_ids" t-as="message" class="media"> + <div class="media-body"> + <t t-call="website.publish"><t t-set="object" t-value="message"/></t> + <t t-raw="message.body"/> + <small class="pull-right muted text-right"> + <div t-field="message.author_id"/> + <div t-field="message.date"/> + </small> + </div> + </li> + </ul> + <form id="blog" t-attf-action="/blog/#{blog_post.category_id.id}/#{blog_post.id}/post#post" + method="POST" class="form-horizontal text-center" + groups="group_website_mail_reply"> + <textarea rows="4" placeholder="Your comment" class="col-md-7 form-control"></textarea> + <button type="submit" class="btn btn-default">Post your comment</button> + </form> + </div> + </template> + + + <!-- Page --> + <template id="index" name="Blogs" page="True"> + <t t-call="website.layout"> + <t t-set="head"> + <script type="text/javascript" src="/website_blog/static/src/js/blog.js"></script> + <link rel='stylesheet' href='/website_blog/static/src/css/blog.css'/> + <t t-raw="head or ''"/> + </t> + <t t-set="title">Blog</t> + <div id="wrap"> + <div class="container mt48 js_website_mail"> + <div class="row"> + <div class="col-md-3" id="left_column"> + <t t-if="category"> + Latests posts on <t t-field="category.name"/> + <a t-if="editable" t-attf-href="/blog/new" class="btn btn-default">New Blog Post</a> + <div> + <form t-attf-action="/blog/#{category.id}/subscribe" + method="POST" class="form-inline" + t-if="not category.message_is_follower"> + <div class="col-lg-7"> + <input placeholder="Email Address" type="email" name="email" class="form-control" t-if="is_public_user"/> + </div> + <button type="submit" class="btn btn-primary" name="subscribe">Follow</button> + </form> + <form t-attf-action="/blog/#{category.id}/unsubscribe" + method="POST" class="form-inline" + t-if="category.message_is_follower"> + <input type="hidden" name="email" t-att-value="subscribe" style="display: none"/> + <button type="submit" class="btn btn-default" name="unsubscribe">Unfollow</button> + </form> + </div> + </t> + </div> + <div class="col-md-9" t-if="blog_post"> + <t t-call="website_blog.blog_post"><t t-set="blog_post" t-value="blog_post"/></t> + </div> + + <div class="col-md-8" t-if="not blog_post and blog_posts"> + <ul class="media-list"> + <li t-foreach="blog_posts" t-as="blog_post" data-publish=""> + <t t-call="website_blog.blog_post_short"><t t-set="blog_post" t-value="blog_post"/></t> + </li> + </ul> + <div class="text-center"> + <t t-call="website.pager"/> + </div> + </div> + </div> + </div> + </div> + </t> + </template> + + <template id="blog_author" inherit_id="website_blog.index" inherit_option_id="website_blog.index" name="Author"> +<!-- <xpath expr="//div[@t-field='document_page.create_date']" position="before"> + <div t-field="document_page.author_id"/> + </xpath> + <xpath expr="//div[@t-field='blog.create_date']" position="before"> + <div t-field="blog.author_id"/> + </xpath> --> + </template> + + + <template id="blog_history" inherit_id="website_blog.index" inherit_option_id="website_blog.index" name="History"> + <xpath expr="//div[@id='left_column']" position="inside"> + <ul class="nav nav-pills nav-stacked"> + <li class="nav-header"><a t-attf-href="/blog/#{category_id}/">Archives</a></li> + <!-- TODO: check qweb iteration --> + <li t-foreach="nav_list" t-as="year" class="js_nav_year"> + <t t-set="year" t-value="nav_list[year]"/> + <a href="#"><t t-esc="year['name']"/> <small>(<t t-esc="year['create_date_count']"/>)</small></a> + <ul class="nav list-group css_nav_month nav-stacked nav-hierarchy"> + <t t-foreach="year['months']"> + <li class="js_nav_month"><a href="#" t-att-data-domain="__domain"><t t-esc="create_date"/> <small>(<t t-esc="create_date_count"/>)</small></a> + <ul class="nav list-group nav-stacked nav-hierarchy"/> + </li> + </t> + </ul> + </li> + </ul> + </xpath> + </template> + </data> +</openerp> diff --git a/addons/website_mail/website_mail_data.xml b/addons/website_blog/website_mail_data.xml index cb5db2e250d..cb5db2e250d 100644 --- a/addons/website_mail/website_mail_data.xml +++ b/addons/website_blog/website_mail_data.xml diff --git a/addons/website_mail/__init__.py b/addons/website_mail/__init__.py index 7a2828a3906..f452f9f142e 100644 --- a/addons/website_mail/__init__.py +++ b/addons/website_mail/__init__.py @@ -1,3 +1,22 @@ -import controllers +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + import mail_message -import res_config
\ No newline at end of file diff --git a/addons/website_mail/__openerp__.py b/addons/website_mail/__openerp__.py index 1f30992aaa9..df01cb69ca1 100644 --- a/addons/website_mail/__openerp__.py +++ b/addons/website_mail/__openerp__.py @@ -1,21 +1,35 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + { - 'name': 'Blogs', + 'name': 'Website Mail', 'category': 'Website', - 'summary': 'News, Blogs, Announces, Discussions', - 'version': '1.0', - 'description': """ -OpenERP Blog -============ - + 'summary': 'Glue Module', + 'version': '0.1', + 'description': """Glue module holding mail improvements for website. """, 'author': 'OpenERP SA', 'depends': ['website', 'mail'], - 'data': [ - 'website_mail_data.xml', - 'views/website_mail.xml', - 'views/res_config.xml', - 'security/website_mail.xml', - ], - 'qweb': ['static/src/xml/*.xml'], + 'data': [], + 'qweb': [], 'installable': True, + 'auto_install': True, } diff --git a/addons/website_mail/controllers/main.py b/addons/website_mail/controllers/main.py deleted file mode 100644 index 939493c14fd..00000000000 --- a/addons/website_mail/controllers/main.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- - -from openerp import SUPERUSER_ID -from openerp.addons.web import http -from openerp.addons.web.http import request -from openerp.addons.website import website -import werkzeug -from openerp.tools.translate import _ -from openerp.tools.safe_eval import safe_eval -import simplejson - -_months = {1:_("January"), 2:_("February"), 3:_("March"), 4:_("April"), 5:_("May"), 6:_("June"), 7:_("July"), 8:_("August"), 9:_("September"), 10:_("October"), 11:_("November"), 12:_("December")} - - -class website_mail(http.Controller): - - @website.route(['/blog/', '/blog/<int:mail_group_id>/', '/blog/<int:mail_group_id>/<int:blog_id>/', - '/blog/page/<int:page>/', '/blog/<int:mail_group_id>/page/<int:page>/', '/blog/<int:mail_group_id>/<int:blog_id>/page/<int:page>/'], type='http', auth="public") - def blog(self, mail_group_id=None, blog_id=None, page=0, **post): - group_obj = request.registry['mail.group'] - message_obj = request.registry['mail.message'] - user_obj = request.registry['res.users'] - - values = { - 'blog_ids': None, - 'blog_id': None, - 'nav_list': dict(), - 'mail_group_id': mail_group_id, - 'subscribe': post.get('subscribe'), - 'unable_editor': post.get('unable_editor') - } - - if not request.context['is_public_user'] and mail_group_id: - message_follower_ids = group_obj.read(request.cr, request.uid, [mail_group_id], ['message_follower_ids'], request.context)[0]['message_follower_ids'] - parent_id = user_obj.browse(request.cr, SUPERUSER_ID, request.uid, request.context).partner_id.id - values['subscribe'] = parent_id in message_follower_ids - - domain = mail_group_id and [("res_id", "=", mail_group_id)] or [] - - for group in message_obj.read_group(request.cr, request.uid, domain + group_obj.get_domain_public_blog(request.cr, request.uid), ['subject', 'date'], groupby="date", orderby="create_date asc", context=request.context): - year = group['date'].split(" ")[1] - if not values['nav_list'].get(year): - values['nav_list'][year] = {'name': year, 'date_count': 0, 'months': []} - values['nav_list'][year]['date_count'] += group['date_count'] - values['nav_list'][year]['months'].append(group) - - if blog_id: - values['blog_id'] = message_obj.browse(request.cr, request.uid, blog_id, request.context) - else: - step = 20 - message_count = len(group_obj.get_public_message_ids(request.cr, request.uid, domain=domain, order="create_date desc", context=request.context)) - pager = request.website.pager(url="/blog/%s/" % mail_group_id, total=message_count, page=page, step=step, scope=7) - message_ids = group_obj.get_public_message_ids(request.cr, request.uid, domain=domain, order="create_date desc", limit=step, offset=pager['offset'], context=request.context) - values['pager'] = pager - values['blog_ids'] = message_obj.browse(request.cr, request.uid, message_ids, request.context) - - return request.website.render("website_mail.index", values) - - @website.route(['/blog/nav'], type='http', auth="public") - def nav(self, **post): - comment_ids = request.registry['mail.group'].get_public_message_ids(request.cr, request.uid, domain=safe_eval(post.get('domain')), order="create_date asc", limit=None, context=request.context) - return simplejson.dumps(request.registry['mail.message'].read(request.cr, request.uid, comment_ids, ['website_published', 'subject', 'res_id'], request.context)) - - @website.route(['/blog/<int:mail_group_id>/<int:blog_id>/post'], type='http', auth="public") - def blog_post(self, mail_group_id=None, blog_id=None, **post): - url = request.httprequest.host_url - if post.get('body'): - request.session.body = post.get('body') - if request.context['is_public_user']: - return '%s/admin#action=redirect&url=%s/blog/%s/%s/post' % (url, url, mail_group_id, blog_id) - - if 'body' in request.session and request.session.body: - request.registry['mail.group'].message_post(request.cr, request.uid, mail_group_id, - body=request.session.body, - parent_id=blog_id, - website_published=blog_id and True or False, - type='comment', - subtype='mt_comment', - context=dict(request.context, mail_create_nosubcribe=True)) - request.session.body = False - - if post.get('body'): - return '%s/blog/%s/%s/' % (url, mail_group_id, blog_id) - else: - return werkzeug.utils.redirect("/blog/%s/%s/" % (mail_group_id, blog_id)) - - @website.route(['/blog/<int:mail_group_id>/new'], type='http', auth="public") - def new_blog_post(self, mail_group_id=None, **post): - blog_id = request.registry['mail.group'].message_post(request.cr, request.uid, mail_group_id, - body="", - subject=_("Blog title"), - website_published=False, - type='comment', - subtype='mt_comment', - context=dict(request.context, mail_create_nosubscribe=True)) - return werkzeug.utils.redirect("/blog/%s/%s/?unable_editor=1" % (mail_group_id, blog_id)) - - @website.route(['/blog/<int:mail_group_id>/subscribe', '/blog/<int:mail_group_id>/<int:blog_id>/subscribe'], type='http', auth="public") - def subscribe(self, mail_group_id=None, blog_id=None, **post): - partner_obj = request.registry['res.partner'] - group_obj = request.registry['mail.group'] - user_obj = request.registry['res.users'] - - if mail_group_id and 'subscribe' in post and (post.get('email') or not request.context['is_public_user']): - if request.context['is_public_user']: - partner_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("email", "=", post.get('email'))], context=request.context) - if not partner_ids: - partner_ids = [partner_obj.create(request.cr, SUPERUSER_ID, {"email": post.get('email'), "name": "Subscribe: %s" % post.get('email')}, request.context)] - else: - partner_ids = [user_obj.browse(request.cr, request.uid, request.uid, request.context).partner_id.id] - group_obj.check_access_rule(request.cr, request.uid, [mail_group_id], 'read', request.context) - group_obj.message_subscribe(request.cr, SUPERUSER_ID, [mail_group_id], partner_ids, request.context) - - return self.blog(mail_group_id=mail_group_id, blog_id=blog_id, subscribe=post.get('email')) - - @website.route(['/blog/<int:mail_group_id>/unsubscribe', '/blog/<int:mail_group_id>/<int:blog_id>/unsubscribe'], type='http', auth="public") - def unsubscribe(self, mail_group_id=None, blog_id=None, **post): - partner_obj = request.registry['res.partner'] - group_obj = request.registry['mail.group'] - user_obj = request.registry['res.users'] - - if mail_group_id and 'unsubscribe' in post and (post.get('email') or not request.context['is_public_user']): - if request.context['is_public_user']: - partner_ids = partner_obj.search(request.cr, SUPERUSER_ID, [("email", "=", post.get('email'))], context=request.context) - else: - partner_ids = [user_obj.browse(request.cr, request.uid, request.uid, request.context).partner_id.id] - group_obj.check_access_rule(request.cr, request.uid, [mail_group_id], 'read', request.context) - group_obj.message_unsubscribe(request.cr, SUPERUSER_ID, [mail_group_id], partner_ids, request.context) - - return self.blog(mail_group_id=mail_group_id, blog_id=blog_id, subscribe=None) diff --git a/addons/website_mail/mail_message.py b/addons/website_mail/mail_message.py index 09e5f456f9f..54af1a3a618 100644 --- a/addons/website_mail/mail_message.py +++ b/addons/website_mail/mail_message.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). +# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -22,22 +22,11 @@ from openerp.osv import osv, fields -class mail_message(osv.osv): - _inherit = "mail.message" +class MailMessage(osv.Model): + _inherit = 'mail.message' + _columns = { - 'website_published': fields.boolean('Publish', help="Publish on the website as a blog"), + 'website_published': fields.boolean( + 'Publish', help="Publish on the website as a blog" + ), } - - -class mail_group(osv.Model): - _inherit = 'mail.group' - - def get_domain_public_blog(self, cr, uid, context=None): - mail_group_ids = self.search(cr, uid, [('public', '=', 'public')], context=context) - return [ ("type", "in", ['comment']), - ("parent_id", "=", False), - ("model", "=", 'mail.group'), ("res_id", "in", mail_group_ids)] - - def get_public_message_ids(self, cr, uid, domain=None, order="create_date desc", limit=None, offset=0, context=None): - domain += self.get_domain_public_blog(cr, uid, context=context) - return self.pool.get('mail.message').search(cr, uid, domain, order=order, limit=limit, offset=offset, context=context) diff --git a/addons/website_mail/static/src/css/blog.sass b/addons/website_mail/static/src/css/blog.sass deleted file mode 100644 index c23585eae75..00000000000 --- a/addons/website_mail/static/src/css/blog.sass +++ /dev/null @@ -1,9 +0,0 @@ -@import "compass/css3" - -.css_website_mail - .has-error - border-color: red - .css_nav_month - display: none - &:first-of-type - display: block
\ No newline at end of file diff --git a/addons/website_mail/views/website_mail.xml b/addons/website_mail/views/website_mail.xml deleted file mode 100644 index 30dd04bce98..00000000000 --- a/addons/website_mail/views/website_mail.xml +++ /dev/null @@ -1,139 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<openerp> -<data> - - <!-- Mail group for the company's news --> - - <record id="website_mail_blog" model="mail.group"> - <field name="name">News</field> - <field name="public">public</field> - <field name="description">News displayed on your website</field> - </record> - - <!-- Layout add nav and footer --> - - <template id="header_footer_custom" inherit_id="website.layout"> - <xpath expr="//body/header//ul[@id='top_menu']/li[last()]" position="before"> - <li><a href="/blog/%(website_mail.website_mail_blog)d/">News</a></li> - </xpath> - <xpath expr="//body/footer//div[@name='info']/ul" position="inside"> - <li><a href="/blog/%(website_mail.website_mail_blog)d/">News</a></li> - </xpath> - </template> - - <!-- Page --> - - <template id="index" name="Blogs" page="True"> - <t t-call="website.layout"> - <t t-set="head"> - <script type="text/javascript" src="/website_mail/static/src/js/blog.js"></script> - <link rel='stylesheet' href='/website_mail/static/src/css/blog.css'/> - <t t-raw="head or ''"/> - </t> - <t t-set="title">Blog</t> - <div id="wrap"> - <div class="container mt48 js_website_mail"> - <div class="row"> - <div class="col-md-3" id="left_column"> - <a t-if="mail_group_id and editable" t-attf-href="/blog/#{ mail_group_id }/new" class="btn btn-default">New Blog Post</a> - <div> - <form action="./subscribe" method="POST" class="form-inline" t-if="not subscribe"> - <div class="col-lg-7"> - <input placeholder="Email Address" type="email" name="email" class="form-control" t-if="is_public_user"/> - </div> - <button type="submit" class="btn btn-primary" name="subscribe">Subscribe</button> - </form> - <form action="./unsubscribe" method="POST" class="form-inline" t-if="subscribe"> - <input type="hidden" name="email" t-att-value="subscribe" style="display: none"/> - <button type="submit" class="btn btn-default" name="unsubscribe">Unsubscribe</button> - </form> - </div> - </div> - <div class="col-md-9" t-if="blog_id"> - <div class="media"> - <div class="media-body"> - <t t-call="website.publish"><t t-set="object" t-value="blog_id"/></t> - <h3 t-field="blog_id.subject"/> - <div t-field="blog_id.body"/> - <small class="pull-right muted text-right"> - <div t-field="blog_id.date"/> - </small> - </div> - <ul class="media-list" id="comment" t-if="not unable_editor"> - <li t-foreach="blog_id.child_ids" t-as="comment" class="media"> - <div class="media-body"> - <t t-call="website.publish"><t t-set="object" t-value="comment"/></t> - <t t-raw="comment.body"/> - <small class="pull-right muted text-right"> - <div t-field="comment.author_id"/> - <div t-field="comment.date"/> - </small> - </div> - </li> - </ul> - <form id="post" t-if="not unable_editor" t-attf-action="/blog/#{ blog_id.res_id }/#{ blog_id.id }/post#post" method="POST" class="form-horizontal text-center" groups="group_website_mail_reply"> - <textarea rows="4" placeholder="Your comment" class="col-md-7 form-control"></textarea> - <button type="submit" class="btn btn-default">Post your comment</button> - </form> - </div> - </div> - - <div class="col-md-8" t-if="not blog_id and blog_ids"> - <ul class="media-list"> - <li t-foreach="blog_ids" t-as="blog" class="media well thumbnail" data-publish=""> - <div class="media-body"> - <t t-call="website.publish"><t t-set="object" t-value="blog"/></t> - <h4 class="media-heading" ><a t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment" t-field="blog.subject"></a></h4> - <div class="media"> - <div t-field="blog.body"/> - <small class="pull-left muted text-right" t-if="len(blog.child_ids)"> - <a t-if="len(blog.child_ids) <= 1" t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment"><t t-esc="len(blog.child_ids)"/> Comment</a> - <a t-if="len(blog.child_ids) > 1" t-attf-href="/blog/#{ blog.res_id }/#{ blog.id }#comment"><t t-esc="len(blog.child_ids)"/> Comments</a> - </small> - <small class="pull-right muted text-right"> - <div t-field="blog.date"/> - </small> - </div> - </div> - </li> - </ul> - <div class="text-center"> - <t t-call="website.pager" /> - </div> - </div> - </div> - </div> - </div> - </t> - </template> - - <template id="blog_author" inherit_id="website_mail.index" inherit_option_id="website_mail.index" name="Author"> - <xpath expr="//div[@t-field='blog_id.date']" position="before"> - <div t-field="blog_id.author_id"/> - </xpath> - <xpath expr="//div[@t-field='blog.date']" position="before"> - <div t-field="blog.author_id"/> - </xpath> - </template> - - <template id="blog_history" inherit_id="website_mail.index" inherit_option_id="website_mail.index" name="History"> - <xpath expr="//div[@id='left_column']" position="inside"> - <ul class="nav nav-pills nav-stacked"> - <li class="nav-header"><a t-attf-href="/blog/#{ mail_group_id }/">BLOG ARCHIVE</a></li> - <!-- TODO: check qweb iteration --> - <li t-foreach="nav_list" t-as="year" class="js_nav_year"> - <t t-set="year" t-value="nav_list[year]"/> - <a href="#"><t t-esc="year['name']"/> <small>(<t t-esc="year['date_count']"/>)</small></a> - <ul class="nav list-group css_nav_month nav-stacked nav-hierarchy"> - <t t-foreach="year['months']"> - <li class="js_nav_month"><a href="#" t-att-data-domain="__domain"><t t-esc="date"/> <small>(<t t-esc="date_count"/>)</small></a> - <ul class="nav list-group nav-stacked nav-hierarchy"/> - </li> - </t> - </ul> - </li> - </ul> - </xpath> - </template> - </data> -</openerp> |
