+
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 0cfba4d14ed..a9a9173099a 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -284,6 +284,8 @@
+
+
diff --git a/addons/website_blog/__openerp__.py b/addons/website_blog/__openerp__.py
index 97c163945af..831c180d51f 100644
--- a/addons/website_blog/__openerp__.py
+++ b/addons/website_blog/__openerp__.py
@@ -30,7 +30,7 @@ OpenERP Blog
""",
'author': 'OpenERP SA',
- 'depends': ['knowledge', 'website_mail'],
+ 'depends': ['knowledge', 'website_mail', 'website_partner'],
'data': [
'data/website_blog_data.xml',
'views/website_blog_views.xml',
diff --git a/addons/website_blog/controllers/main.py b/addons/website_blog/controllers/main.py
index 5cb678b5475..e2eac59678e 100644
--- a/addons/website_blog/controllers/main.py
+++ b/addons/website_blog/controllers/main.py
@@ -1,23 +1,4 @@
# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2013-Today OpenERP SA ().
-#
-# 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 .
-#
-##############################################################################
import datetime
import werkzeug
@@ -29,6 +10,7 @@ from openerp.addons.website.models.website import slug
from openerp.osv.orm import browse_record
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
+from openerp.tools import html2plaintext
class QueryURL(object):
@@ -62,12 +44,13 @@ class QueryURL(object):
class WebsiteBlog(http.Controller):
- _blog_post_per_page = 6
- _post_comment_per_page = 6
+ _blog_post_per_page = 20
+ _post_comment_per_page = 10
def nav_list(self):
blog_post_obj = request.registry['blog.post']
- groups = blog_post_obj.read_group(request.cr, request.uid, [], ['name', 'create_date'],
+ groups = blog_post_obj.read_group(
+ request.cr, request.uid, [], ['name', 'create_date'],
groupby="create_date", orderby="create_date asc", context=request.context)
for group in groups:
begin_date = datetime.datetime.strptime(group['__domain'][0][2], tools.DEFAULT_SERVER_DATETIME_FORMAT).date()
@@ -108,35 +91,27 @@ class WebsiteBlog(http.Controller):
def blog(self, blog=None, tag=None, page=1, **opt):
""" Prepare all values to display the blog.
- :param blog: blog currently browsed.
- :param tag: tag that is currently used to filter blog posts
- :param integer page: current page of the pager. Can be the blog or
- post pager.
- :param date: date currently used to filter blog posts (dateBegin_dateEnd)
-
:return dict values: values for the templates, containing
- - 'blog_posts': list of browse records that are the posts to display
- in a given blog, if not blog_post_id
- - 'blog': browse of the current blog, if blog_id
- - 'blogs': list of browse records of blogs
- - 'pager': the pager to display posts pager in a blog
- - 'tag': current tag, if tag_id
+ - 'blog': current blog
+ - 'blogs': all blogs for navigation
+ - 'pager': pager of posts
+ - 'tag': current tag
+ - 'tags': all tags, for navigation
- 'nav_list': a dict [year][month] for archives navigation
+ - 'date': date_begin optional parameter, used in archives navigation
+ - 'blog_url': help object to create URLs
"""
date_begin, date_end = opt.get('date_begin'), opt.get('date_end')
cr, uid, context = request.cr, request.uid, request.context
blog_post_obj = request.registry['blog.post']
- blog_posts = None
-
blog_obj = request.registry['blog.blog']
blog_ids = blog_obj.search(cr, uid, [], order="create_date asc", context=context)
blogs = blog_obj.browse(cr, uid, blog_ids, context=context)
domain = []
-
if blog:
domain += [('blog_id', '=', blog.id)]
if tag:
@@ -176,35 +151,29 @@ class WebsiteBlog(http.Controller):
'post_url': post_url,
'date': date_begin,
}
- return request.website.render("website_blog.blog_post_short", values)
+ response = request.website.render("website_blog.blog_post_short", values)
+ return response
@http.route([
- '/blogpost/',
+ '/blog//post/',
], type='http', auth="public", website=True, multilang=True)
- def blog_post(self, blog_post, tag_id=None, page=1, enable_editor=None, **post):
+ def blog_post(self, blog, blog_post, tag_id=None, page=1, enable_editor=None, **post):
""" Prepare all values to display the blog.
- :param blog_post: blog post currently browsed. If not set, the user is
- browsing the blog and a post pager is calculated.
- If set the user is reading the blog post and a
- comments pager is calculated.
- :param blog: blog currently browsed.
- :param tag: tag that is currently used to filter blog posts
- :param integer page: current page of the pager. Can be the blog or
- post pager.
- :param date: date currently used to filter blog posts (dateBegin_dateEnd)
-
- - 'enable_editor': editor control
-
:return dict values: values for the templates, containing
- - 'blog_post': browse of the current post, if blog_post_id
- - 'blog': browse of the current blog, if blog_id
+ - 'blog_post': browse of the current post
+ - 'blog': browse of the current blog
- 'blogs': list of browse records of blogs
- - 'pager': the pager to display comments pager in a blog post
- - 'tag': current tag, if tag_id
+ - 'tag': current tag, if tag_id in parameters
+ - 'tags': all tags, for tag-based navigation
+ - 'pager': a pager on the comments
- 'nav_list': a dict [year][month] for archives navigation
+ - 'next_post': next blog post, to direct the user towards the next interesting post
"""
+ cr, uid, context = request.cr, request.uid, request.context
+ tag_obj = request.registry['blog.tag']
+ blog_post_obj = request.registry['blog.post']
date_begin, date_end = post.get('date_begin'), post.get('date_end')
pager_url = "/blogpost/%s" % blog_post.id
@@ -226,62 +195,125 @@ class WebsiteBlog(http.Controller):
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)
- cr, uid, context = request.cr, request.uid, request.context
- blog_obj = request.registry['blog.blog']
- blog_ids = blog_obj.search(cr, uid, [], context=context)
- blogs = blog_obj.browse(cr, uid, blog_ids, context=context)
+ if not blog_post.blog_id.id == blog.id:
+ return request.redirect("/blog/%s/post/%s" % (slug(blog_post.blog_id), slug(blog_post)))
- tag_obj = request.registry['blog.tag']
- tag_ids = tag_obj.search(cr, uid, [], context=context)
- tags = tag_obj.browse(cr, uid, tag_ids, context=context)
+ tags = tag_obj.browse(cr, uid, tag_obj.search(cr, uid, [], context=context), context=context)
+
+ # Find next Post
+ visited_blogs = request.httprequest.cookies.get('visited_blogs') or ''
+ visited_ids = filter(None, visited_blogs.split(','))
+ visited_ids = map(lambda x: int(x), visited_ids)
+ if blog_post.id not in visited_ids:
+ visited_ids.append(blog_post.id)
+ next_post_id = blog_post_obj.search(cr, uid, [
+ ('id', 'not in', visited_ids),
+ ], order='ranking desc', limit=1, context=context)
+ if not next_post_id:
+ next_post_id = blog_post_obj.search(cr, uid, [('id', '!=', blog.id)], 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
values = {
- 'blog': blog_post.blog_id,
- 'blogs': blogs,
'tags': tags,
'tag': tag,
+ 'blog': blog,
'blog_post': blog_post,
'main_object': blog_post,
- 'pager': pager,
'nav_list': self.nav_list(),
'enable_editor': enable_editor,
+ 'next_post': next_post,
'date': date_begin,
'post_url': post_url,
'blog_url': blog_url,
+ 'pager': pager,
}
- return request.website.render("website_blog.blog_post_complete", values)
+ response = request.website.render("website_blog.blog_post_complete", values)
+ response.set_cookie('visited_blogs', ','.join(map(str, visited_ids)))
+
+ request.session[request.session_id] = request.session.get(request.session_id, [])
+ if not (blog_post.id in request.session[request.session_id]):
+ request.session[request.session_id].append(blog_post.id)
+ # Increase counter
+ blog_post_obj.write(cr, SUPERUSER_ID, [blog_post.id], {
+ 'visits': blog_post.visits+1,
+ },context=context)
+ return response
+
+ def _blog_post_message(self, user, blog_post_id=0, **post):
+ cr, uid, context = request.cr, request.uid, request.context
+ blog_post = request.registry['blog.post']
+ partner_obj = request.registry['res.partner']
+ thread_obj = request.registry['mail.thread']
+ website = request.registry['website']
+
+ public_id = website.get_public_user(cr, uid, context)
+ if uid != public_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'),
+ type='comment',
+ subtype='mt_comment',
+ author_id=partner_ids[0],
+ path=post.get('path', False),
+ context=dict(context, mail_create_nosubcribe=True))
+ 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):
cr, uid, context = request.cr, request.uid, request.context
if post.get('comment'):
- user = request.registry['res.users'].browse(cr, SUPERUSER_ID, uid, context=context)
- group_ids = user.groups_id
- group_id = request.registry["ir.model.data"].get_object_reference(cr, uid, 'website_mail', 'group_comment')[1]
- if group_id in [group.id for group in group_ids]:
- blog_post = request.registry['blog.post']
- blog_post.check_access_rights(cr, uid, 'read')
- blog_post.message_post(
- cr, SUPERUSER_ID, int(blog_post_id),
- body=post.get('comment'),
- type='comment',
- subtype='mt_comment',
- author_id=user.partner_id.id,
- context=dict(context, mail_create_nosubcribe=True))
+ 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")
+ def _get_discussion_detail(self, ids, publish=False, **post):
+ cr, uid, context = request.cr, request.uid, request.context
+ values = []
+ mail_obj = request.registry.get('mail.message')
+ for message in mail_obj.browse(cr, SUPERUSER_ID, ids, context=context):
+ values.append({
+ "id": message.id,
+ "author_name": message.author_id.name,
+ "author_image": message.author_id.image and \
+ ("data:image/png;base64,%s" % message.author_id.image) or \
+ '/website_blog/static/src/img/anonymous.png',
+ "date": message.date,
+ 'body': html2plaintext(message.body),
+ 'website_published' : message.website_published,
+ 'publish' : publish,
+ })
+ return values
+
+ @http.route(['/blogpost/post_discussion'], type='json', auth="public", website=True)
+ def post_discussion(self, blog_post_id=0, **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)
+ return self._get_discussion_detail([id], publish, **post)
+
@http.route('/blogpost/new', type='http', auth="public", website=True, multilang=True)
def blog_post_create(self, blog_id, **post):
cr, uid, context = request.cr, request.uid, request.context
create_context = dict(context, mail_create_nosubscribe=True)
- new_blog_post_id = request.registry['blog.post'].create(
- request.cr, request.uid, {
- 'blog_id': blog_id,
- 'name': _("Blog Post Title"),
- 'content': '',
- 'website_published': False,
- }, context=create_context)
- return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)
+ new_blog_post_id = request.registry['blog.post'].create(cr, uid, {
+ 'blog_id': blog_id,
+ 'name': _("Blog Post Title"),
+ 'subtitle': _("Subtitle"),
+ 'content': '',
+ 'website_published': False,
+ }, context=create_context)
+ 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)
def blog_post_copy(self, blog_post_id, **post):
@@ -293,5 +325,31 @@ class WebsiteBlog(http.Controller):
"""
cr, uid, context = request.cr, request.uid, request.context
create_context = dict(context, mail_create_nosubscribe=True)
- new_blog_post_id = request.registry['blog.post'].copy(cr, uid, blog_post_id, {}, context=create_context)
- return werkzeug.utils.redirect("/blogpost/%s?enable_editor=1" % new_blog_post_id)
+ nid = request.registry['blog.post'].copy(cr, uid, 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)
+ 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')
+ domain = [('res_id', '=', int(post_id)), ('model', '=', 'blog.post'), ('path', '=', path)]
+ #check current user belongs to website publisher group
+ publish = request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher')
+ if not publish:
+ domain.append(('website_published', '=', True))
+ ids = mail_obj.search(cr, SUPERUSER_ID, domain, count=count)
+ if count:
+ return ids
+ return self._get_discussion_detail(ids, publish, **post)
+
+ @http.route('/blogpost/change_background', type='json', auth="public", website=True)
+ def change_bg(self, post_id=0, image=None, **post):
+ if not post_id:
+ return False
+ return request.registry['blog.post'].write(request.cr, request.uid, [int(post_id)], {'background_image': image}, request.context)
+
+ @http.route('/blog/get_user/', type='json', auth="public", website=True)
+ def get_user(self, **post):
+ return [False if request.session.uid else True]
diff --git a/addons/website_blog/data/website_blog_data.xml b/addons/website_blog/data/website_blog_data.xml
index a5a3aa3d8c9..efc25264633 100644
--- a/addons/website_blog/data/website_blog_data.xml
+++ b/addons/website_blog/data/website_blog_data.xml
@@ -2,7 +2,8 @@
- News
+ Our News
+ Sharing our evolution with passionPresentation of new OpenERP features
diff --git a/addons/website_blog/data/website_blog_demo.xml b/addons/website_blog/data/website_blog_demo.xml
index 913c2ddc9b1..d6827220414 100644
--- a/addons/website_blog/data/website_blog_demo.xml
+++ b/addons/website_blog/data/website_blog_demo.xml
@@ -8,329 +8,199 @@
functional
- technical
-
- website
-
- pos
-
- OpenERP v8 New Features
+ The Future of Emails
+ Ideas behing the OpenERP communication tools.
- OpenERP, Point of Sale, Hardware, Interface, Payment Terminal, Store
- Open source Point of Sale with no installation required that runs online and offline.
+ OpenERP, email
+ The Future of Emails
+ /website_blog/static/src/img/post1.jpg
-
-
-
-
-
-
-
- OpenERP's Point of Sale introduces a super clean
- interface with no installation required that runs
- online and offline on modern hardwares.
-
- It's full integration with the company inventory
- and accounting, gives you real time statistics
- without the hassle of integrating several applications.
-
-
-
-
+
+
+
+ Emails are broken.
+
+ Emails make me waste my time. But I need them.
+ Given the importance that emails have in our lives,
+ it's incredible it's still one of the only software
+ areas that did not evolve in the past 20 years!
+
+ Reading my inbox is the most unproductive task I do
+ on a daily basis. I have to spend one full hour a
+ day to process my emails. All the junk flows in the
+ same inbox; spams, information that doesn't matter,
+ quoted answers of quoted answers, etc. At the end
+ of the hour, only 10 emails actually requested an
+ answer from me. With a good tool, I could have done
+ my job in 10 minutes!
+
-
-
-
-
-
- Linked with Project Management
-
-
Infinitely flexible. Incredibly easy to use.
-
-
-
- OpenERP's collaborative and realtime project
- management helps your team get work done. Keep
- track of everything, from the big picture to the
- minute details, from the customer contract to the
- billing.
-
- Organize projects around your own processes. Work
- on tasks and issues using the kanban view, schedule
- tasks using the gantt chart and control deadlines
- in the calendar view. Every project may have it's
- own stages allowing teams to optimize their job.
-
-
-
-
+
+
+ At OpenERP, we build tools to bring productivity to
+ enterprises. As emails and information flows are one of
+ the biggest wastes of time in companies, we have to fix
+ this.
+
+ To disrupt emails, you need more than just another user
+ interface. We need to rethink the whole communication flow.
+
+
The Communication Mechanism of OpenERP
+
+ Here are the ideas behing the OpenERP communication tools:
+
+
+
+ Get Things Done: your inbox is a
+ todo list. You should be able to process (not only
+ read) the inbox and easily mark messages for future
+ actions. Every inbox should be empty after having
+ been processed; no more overload of information.
+
+
+ Keep control of what you want to receive or don't want
+ to receive. People should never receive spam. You
+ should follow/unfollow any kind of information in one
+ click.
+
+ Productivity is key: our smart user
+ interface does not require you to click on every mail
+ to read a thread. Reading a full thread, replying,
+ attaching documents is super fast.
+
+
+ A mix of push & pull: Today, people
+ are victims of what others decide to push to them.
+ OpenERP differentiates:
+
+
+ Messages "for information":
+ you can pull them when you need some specific
+ information; they are not required to be read
+ every day.You receive only what you decided
+ to follow.This accounts for 90% of your daily
+ emails.Use the "Inbox" menu for these.
+
+ Messages "for action": they
+ require your immediate attention and you need
+ to process them all. This accounts for 10%
+ of your daily emails. Use the "To: me" menu
+ for these.
+
+
+
+ Focus on the Content: Everything is
+ stripped to emphasize on the real message. No more
+ welcome introductions, greetings, signatures and legal
+ notes.We standardize the layout of each message.
+ (signatures are on the profile of a contact, not in
+ every message)
+
+ Folders and mailing lists are great tools but too
+ complex in traditional email clients. In OpenERP, a
+ group of contacts that share a discussion can be
+ created with one click. Every group should have it's
+ own email address.
+
+
-
-
-
-
-
Work with the hardware you already have...
-
-
-
-
-
-
- No installation required
-
-
- OpenERP's Point of Sale introduces a super clean
- interface with no installation required that runs
- online and offline on modern hardware. Laptops,
- tablets, industrial POS, it runs on everything.
-
-
-
]]>
- New Hardware Integration
+ Integrating your CMS and E-Commerce
+ Building your company's website and selling your products online easy.
-
-
-
-
-
-
-
-
-
-
- New Features Launched
-
-
- OpenERP's Point of Sale introduces a super clean
- interface with no installation required that runs
- online and offline on modern hardware. Laptops,
- tablets, industrial POS, it runs on everything.
-
-
-
-
-
-
-
-
-
-
Our Offers
-
-
-
-
-
-
-
Beginner
-
- Starter package
-
-
-
-
$450.00
-
per month
-
-
-
-
-
Battery: 8 hours
-
Screen: 2.5 inch
-
Weight: 1.1 ounces
-
No support
-
-
-
-
-
-
-
-
-
Professional
-
- Enterprise package
-
-
-
-
$590.00
-
per month
-
-
-
-
-
Battery: 12 hours
-
Screen: 2.8 inch
-
Weight: 1.2 ounces
-
Limited support
-
-
-
-
-
-
-
-
-
Expert
-
- The top of the top
-
-
-
-
$890.00
-
per month
-
-
-
-
-
Battery: 20 hours
-
Screen: 2.8 inch
-
Weight: 1.2 ounces
-
Unlimited support
-
-
-
-
-
-
-
-
-
-
-]]>
-
-
-
-
- Touchscreen Point of Sale for 6.1
-
-
- Point of Sale, Hardware, Interface, Payment Terminal, Store
- Point of Sale with no installation required that runs online and offline.
-
-The brand new OpenERP touchscreen point of sale is available with 6.1 which allows you
-to manage your shop sales very easily. It's fully web based so that you don't
-have to install or deploy any software and all the sales shops can be easily
-consolidated. It works in connected and disconnected modes so that you can
-continue to sell even if you lose your internet connection.
-
-
Here's a summary of its main features and benefits:
-
-
100% WEB based
-
available for any touchscreen device (ipod, ipad, any tablet)mobile (with portable devices)
-
no installation required
-
no synchronization needed, completely integrated
-
continue working even when your connection is down or if you close your browser, data won't be lost
-
fully web based with a clean interface smart interface
-
-
You have different options to select your products. You can do it through the
-barcode reader, just browse through the categories you have put in place (ie.
-drinks, snacks, meals, etc.), or text search in case neither of the other
-options work for you. For example, if you need to use the POS for your restaurant,
-your employees can record multiple tickets at the same time without having to wait
-to process one transaction at a time. In addition, you can facilitate payments,
-the application allows multiple payment methods.
-
The POS application is so simple and accessible to use that your shop or
-restaurant will never need any other tool to manage orders. Due to its smart
-and user-friendly interface you don't need any training to learn how to use it.
-Think of it as an out-of-the-box solution to boost your business' productivity.
-
-]]>
-
-
-
-
- Announcing a New Partnership
-
-
- OpenERP, Partnership, News, Accounting
- Our company partners with OpenERP to develop accounting best practices.
-
-
-
-
-
-
-
-
- We are proud to announce a new partnership with
- the company OpenERP. Their open source application suite
- will allow us to reach new markets, specifically in
- the accounting area.
-
- The full integration with the company inventory
- and accounting, will give our customers real time statistics
- without the hassle of integrating several applications.
-
-
-
+
+ /website_blog/static/src/img/post2.jpg
+
+
+
+
+
+
+
+ New Features Launched
+
+
+ To add to an already comprehensive set of OpenERP
+ features, a website content management system (CMS
+ or WMS) has been developed and a beta release is
+ available from today, 31st January 2014.
+
-
-
-
-
-
- OpenERP Project Management
-
-
Infinitely flexible. Incredibly easy to use.
-
-
-
- OpenERP's collaborative and realtime project
- management helps your team get work done. Keep
- track of everything, from the big picture to the
- minute details, from the customer contract to the
- billing.
-
- Organize projects around your own processes. Work
- on tasks and issues using the kanban view, schedule
- tasks using the gantt chart and control deadlines
- in the calendar view. Every project may have it's
- own stages allowing teams to optimize their job.
-
-
-
-
+
+
+ OpenERP claims to be 'the Open Source software that makes
+ building your company's website and selling your products
+ online easy'. So how true is this statement?
+
+ "OpenERP's latest launch will allow a business to go from
+ zero to trading online quicker than ever before,” Stuart
+ Mackintosh, MD of Open Source specialist and OpenERP
+ integration partner, OpusVL, explains. “The investment
+ required to have a fully automated business system is
+ dramatically reduced, enabling the small and medium
+ enterprise to compete at a level of functionality and
+ performance previously reserved for the big IT investors."
+
+
+
+ "Finally, the leading edge is being brought to the masses.
+ It will now be the turn of the big players to catch up to
+ the superior technologies of the SME."
+
+
+
+ "This is another clever and highly disruptive move by
+ OpenERP,which will force other technology providers to
+ take another look at the value they are providing to ensure
+ that their 'solutions' can still compete."
+
+ "OpenERP now competes on many fronts, with no real
+ competition out there to knock them off the top spot.
+ With the launch of their integrated CMS and Ecommerce
+ systems,it only elevates their position as one of the leading
+ lights in the open source revolution. It will be at least 5
+ years before another ERP or CMS provider will be able to
+ compete at this level due to the technology currently
+ employed by most industry providers."
+
+
Adding to industry leading technology
+
+ Like many modern website editors, with OpenERP you can edit
+ content in-line, enabling you to see exactly what you are
+ changing and ensure your changes suit the context.
+
+ However, unlike other web content management systems, it
+ fully integrates into the back-end database. This means
+ that when you edit a product description, image or price,
+ it updates the product database in real time, providing a
+ true self-service window into the business.
+
+ This provides a single source of data for your company and
+ removes the need to create offline synchronisation between
+ website and product database.
+
+ As it comes, there is a default website based on Bootstrap
+ 3, the latest industry standard for rapid development of
+ multi-device websites backed by Twitter, so can be directly
+ integrated with many web tools and works across all devices
+ by default.
+
]]>
-
-
diff --git a/addons/website_blog/doc/blog_blog.rst b/addons/website_blog/doc/blog_blog.rst
new file mode 100644
index 00000000000..8c5f80ab8e4
--- /dev/null
+++ b/addons/website_blog/doc/blog_blog.rst
@@ -0,0 +1,20 @@
+_blog_blog:
+
+blog.blog
+=========
+In ``blog.blog``, added field ``subtitle`` which Indicates the subtitle of blogs.
+ - ``subtitle``: fields.char('Blog Subtitle')
+
+mail.message
+============
+In ``mail.message``, added field ``discussion`` which Indicates the unique identification
+of paragraph on blog post.
+ - ``discussion``: fields.char('Discussion Unique Name')
+
+blog.post
+=========
+Fields
+++++++
+ - ``sub_title`` : contains the subtitle of every blog post.
+ - ``visits`` : Indicates the number of visits on evry blog post.
+ - ``ranking`` : Indicates the ranking on every blog post.
diff --git a/addons/website_blog/doc/changelog.rst b/addons/website_blog/doc/changelog.rst
index 8b6131b5806..42f2fd7e170 100644
--- a/addons/website_blog/doc/changelog.rst
+++ b/addons/website_blog/doc/changelog.rst
@@ -7,3 +7,29 @@ Changelog
----------------
- created ``website_blog`` menu, build on defunct document_page module.
+ - added new feature ``Inline Discussion`` , that will allow a user to comment
+ on every paragraph on blog post
+ - added new feature ``Select to Tweet``, that will alllow a user tweet a selected
+ text from blog to post , directly on twitter.
+
+
+
+WebsiteBlog(controller)
+=======================
+Methods
++++++++
+ - ``blog`` : remove routing related to date.
+ - ``blog_post`` : updated with , suggestion of next post to the user based on
+ cookie and number of views.
+ - ``discussion`` : added method , contains a detail of discussion on every paragraph,
+ if count is true it only return len of ids else return full detail.
+ def discussion(self, post_id=0, discussion=None, count=False, **post)
+ - ``post_discussion`` : added methodt, that allow to post discussion on any paragraph.
+ def post_discussion(self, blog_post_id=0, **post)
+ - ``change_bg`` : added method allow a user to change background image on blog
+ post from front-end.
+ def change_bg(self, post_id=0, image=None, **post)
+ - ``get_user`` : added method , that will return True if user is public else False.
+ def get_user(self, **post):
+ return [False if request.session.uid else True]
+
diff --git a/addons/website_blog/doc/controller.rst b/addons/website_blog/doc/controller.rst
new file mode 100644
index 00000000000..727368aab8c
--- /dev/null
+++ b/addons/website_blog/doc/controller.rst
@@ -0,0 +1,21 @@
+.. _controller:
+
+WebsiteBlog(controller)
+=======================
+Methods
++++++++
+ - ``blog`` : remove routing related to date.
+ - ``blog_post`` : updated with , suggestion of next post to the user based on
+ cookie and number of views.
+ - ``discussion`` : added method , contains a detail of discussion on every paragraph,
+ if count is true it only return len of ids else return full detail.
+ def discussion(self, post_id=0, discussion=None, count=False, **post)
+ - ``post_discussion`` : added methodt, that allow to post discussion on any paragraph.
+ def post_discussion(self, blog_post_id=0, **post)
+ - ``change_bg`` : added method allow a user to change background image on blog
+ post from front-end.
+ def change_bg(self, post_id=0, image=None, **post)
+ - ``get_user`` : added method , that will return True if user is public else False.
+ def get_user(self, **post):
+ return [False if request.session.uid else True]
+
diff --git a/addons/website_blog/models/__init__.py b/addons/website_blog/models/__init__.py
index fb5368a71c5..083e1ef6660 100644
--- a/addons/website_blog/models/__init__.py
+++ b/addons/website_blog/models/__init__.py
@@ -1 +1,2 @@
+import mail_message
import website_blog
diff --git a/addons/website_blog/models/mail_message.py b/addons/website_blog/models/mail_message.py
new file mode 100644
index 00000000000..e1b60f6ad20
--- /dev/null
+++ b/addons/website_blog/models/mail_message.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from openerp.osv import osv, fields
+
+
+class MailMessage(osv.Model):
+ _inherit = 'mail.message'
+
+ _columns = {
+ 'path': fields.char(
+ 'Discussion Path', select=1,
+ help='Used to display messages in a paragraph-based chatter using a unique path;'),
+ }
diff --git a/addons/website_blog/models/website_blog.py b/addons/website_blog/models/website_blog.py
index e132e4c5e15..031856fff10 100644
--- a/addons/website_blog/models/website_blog.py
+++ b/addons/website_blog/models/website_blog.py
@@ -1,32 +1,15 @@
# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-Today OpenERP SA ().
-#
-# 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 .
-#
-##############################################################################
+from datetime import datetime
+import difflib
+import lxml
+import random
from openerp import tools
from openerp import SUPERUSER_ID
from openerp.osv import osv, fields
from openerp.tools.translate import _
-import difflib
-
class Blog(osv.Model):
_name = 'blog.blog'
@@ -35,12 +18,9 @@ class Blog(osv.Model):
_order = 'name'
_columns = {
- 'name': fields.char('Name', required=True),
+ 'name': fields.char('Blog Name', required=True),
+ 'subtitle': fields.char('Blog Subtitle'),
'description': fields.text('Description'),
- 'blog_post_ids': fields.one2many(
- 'blog.post', 'blog_id',
- 'Blogs',
- ),
}
@@ -52,9 +32,6 @@ class BlogTag(osv.Model):
_columns = {
'name': fields.char('Name', required=True),
- 'blog_post_ids': fields.many2many(
- 'blog.post', string='Posts',
- ),
}
@@ -62,37 +39,20 @@ class BlogPost(osv.Model):
_name = "blog.post"
_description = "Blog Post"
_inherit = ['mail.thread', 'website.seo.metadata']
- _order = 'write_date DESC'
- # maximum number of characters to display in summary
- _shorten_max_char = 250
+ _order = 'id DESC'
- def get_shortened_content(self, cr, uid, ids, name, arg, context=None):
+ def _compute_ranking(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,
- expand_options={
- 'oe_expand_container_tag': 'div',
- 'oe_expand_container_class': 'oe_mail_expand text-center',
- 'oe_expand_container_content': '',
- 'oe_expand_a_href': '/blogpost/%d' % page.id,
- 'oe_expand_a_class': 'oe_mail_expand btn btn-info',
- 'oe_expand_separator_node': 'br',
- },
- protect_sections=True,
- )
- except Exception:
- body_short = False
- res[page.id] = body_short
+ for blog_post in self.browse(cr, uid, ids, context=context):
+ age = datetime.now() - datetime.strptime(blog_post.create_date, tools.DEFAULT_SERVER_DATETIME_FORMAT)
+ res[blog_post.id] = blog_post.visits * (0.5+random.random()) / max(3, age.days)
return res
_columns = {
'name': fields.char('Title', required=True, translate=True),
- 'content_image': fields.binary('Background Image'),
+ 'subtitle': fields.char('Sub Title', translate=True),
+ 'author_id': fields.many2one('res.partner', 'Author'),
+ 'background_image': fields.binary('Background Image'),
'blog_id': fields.many2one(
'blog.blog', 'Blog',
required=True, ondelete='cascade',
@@ -101,32 +61,22 @@ class BlogPost(osv.Model):
'blog.tag', string='Tags',
),
'content': fields.html('Content', translate=True),
- 'shortened_content': fields.function(
- get_shortened_content,
- type='html',
- string='Shortened Content',
- help="Shortened content of the page that serves as a summary"
- ),
# website control
'website_published': fields.boolean(
'Publish', help="Publish on the website"
),
- 'website_published_datetime': fields.datetime(
- 'Publish Date'
- ),
- # TDE TODO FIXME: when website_mail/mail_thread.py inheritance work -> this field won't be necessary
'website_message_ids': fields.one2many(
'mail.message', 'res_id',
domain=lambda self: [
- '&', ('model', '=', self._name), ('type', '=', 'comment')
+ '&', '&', ('model', '=', self._name), ('type', '=', 'comment'), ('path', '=', False)
],
string='Website Messages',
help="Website communication history",
),
- # technical stuff: history, menu (to keep ?)
'history_ids': fields.one2many(
'blog.post.history', 'post_id',
- 'History', help='Last post modifications'
+ 'History', help='Last post modifications',
+ deprecated='This field will be removed for OpenERP v9.'
),
# creation / update stuff
'create_date': fields.datetime(
@@ -145,11 +95,71 @@ class BlogPost(osv.Model):
'res.users', 'Last Contributor',
select=True, readonly=True,
),
+ 'visits': fields.integer('No of Views'),
+ 'ranking': fields.function(_compute_ranking, string='Ranking', type='float'),
}
+
_defaults = {
- 'website_published': False
+ 'name': _('Blog Post Title'),
+ 'subtitle': _('Subtitle'),
+ '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()]
+ if ancestor_tags:
+ ancestor_tags.pop()
+ ancestor_tags.append('counter_%s' % counter)
+ 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('
+
+
+
+
+
+
@@ -155,5 +161,6 @@
name="Page History"
res_model="blog.post.history"
src_model="blog.post"/>
+
diff --git a/addons/website_event_track/__openerp__.py b/addons/website_event_track/__openerp__.py
index 338477eeb8e..418e049cec9 100644
--- a/addons/website_event_track/__openerp__.py
+++ b/addons/website_event_track/__openerp__.py
@@ -28,7 +28,8 @@ Adds support for:
],
'qweb': ['static/src/xml/*.xml'],
'demo': [
- 'data/event_demo.xml'
+ 'data/event_demo.xml',
+ 'data/website_event_track_demo.xml'
],
'installable': True,
}
diff --git a/addons/website_event_track/controllers/event.py b/addons/website_event_track/controllers/event.py
index 466e3d37a40..60d4bbd390d 100644
--- a/addons/website_event_track/controllers/event.py
+++ b/addons/website_event_track/controllers/event.py
@@ -23,11 +23,14 @@ import openerp
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.controllers.main import Website as controllers
+import datetime
import re
import werkzeug.utils
controllers = controllers()
+import pytz
+from pytz import timezone
class website_event(http.Controller):
@http.route(['/event//track/'], type='http', auth="public", website=True, multilang=True)
@@ -37,14 +40,65 @@ class website_event(http.Controller):
values = { 'track': track, 'event': track.event_id, 'main_object': track }
return request.website.render("website_event_track.track_view", values)
+ def _prepare_calendar(self, event, event_track_ids):
+ local_tz = pytz.timezone(event.timezone_of_event or 'UTC')
+ locations = {} # { location: [track, start_date, end_date, rowspan]}
+ dates = [] # [ (date, {}) ]
+ for track in event_track_ids:
+ locations.setdefault(track.location_id or False, [])
+
+ forcetr = True
+ for track in event_track_ids:
+ start_date = (datetime.datetime.strptime(track.date, '%Y-%m-%d %H:%M:%S')).replace(tzinfo=pytz.utc).astimezone(local_tz)
+ end_date = start_date + datetime.timedelta(hours = (track.duration or 30))
+ location = track.location_id or False
+ locations.setdefault(location, [])
+
+ # New TR, align all events
+ if forcetr or (start_date>dates[-1][0]) or not location:
+ dates.append((start_date, {}, bool(location)))
+ for loc in locations.keys():
+ if locations[loc] and (locations[loc][-1][2] > start_date):
+ locations[loc][-1][3] += 1
+ elif not locations[loc] or locations[loc][-1][2] < start_date:
+ locations[loc].append([False, locations[loc] and locations[loc][-1][2] or dates[0][0], start_date, 1])
+ dates[-1][1][loc] = locations[loc][-1]
+ forcetr = not bool(location)
+
+ # Add event
+ if locations[location] and locations[location][-1][1] > start_date:
+ locations[location][-1][3] -= 1
+ locations[location].append([track, start_date, end_date, 1])
+ dates[-1][1][location] = locations[location][-1]
+ return {
+ 'locations': locations,
+ 'dates': dates
+ }
+
+
# TODO: not implemented
@http.route(['/event//agenda'], type='http', auth="public", website=True, multilang=True)
def event_agenda(self, event, tag=None, **post):
- values = {
+ comp = lambda x: (x.date, bool(x.location_id))
+ event.track_ids.sort(lambda x,y: cmp(comp(x), comp(y)))
+
+ days = {}
+ days_nbr = {}
+ for track in event.track_ids:
+ if not track.date: continue
+ days.setdefault(track.date[:10], [])
+ days[track.date[:10]].append(track)
+
+ for d in days:
+ days_nbr[d] = len(days[d])
+ days[d] = self._prepare_calendar(event, days[d])
+
+ return request.website.render("website_event_track.agenda", {
'event': event,
- 'main_object': event,
- }
- return request.website.render("website_event_track.agenda", values)
+ 'days': days,
+ 'days_nbr': days_nbr,
+ 'tag': tag
+ })
@http.route([
'/event//track',
diff --git a/addons/website_event_track/data/event_demo.xml b/addons/website_event_track/data/event_demo.xml
index 5bdd302649b..784d962e471 100644
--- a/addons/website_event_track/data/event_demo.xml
+++ b/addons/website_event_track/data/event_demo.xml
@@ -24,20 +24,6 @@
Round Table
-
-
- Room 1
-
-
- Room 2
-
-
- Room 3
-
-
- Room 4
-
-
@@ -83,68 +69,6 @@
-
-
- A Better Future With OpenERP eCommerce
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Apart from being an enterprise management software, OpenERP is
- used nowadays for a great variety of enterprise frontends.
-
- The talk illustrates the impact of OpenERP in areas such as the
- company website, online events management, eCommerce, online
- recruitments, social media marketing, etc.
-
-
-
-
-
-
-
-
-
- How To Drive Sales With OpenERP CRM
-
-
-
- 1
-
-
-
-
-
-
-
-
-
-
-
- Apart from being an enterprise management software, OpenERP is
- used nowadays for a great variety of enterprise frontends.
-
- The talk illustrates the impact of OpenERP in areas such as the
- company website, online events management, eCommerce, online
- recruitments, social media marketing, etc.
-
-
-
-
-
-
-
-
http://facebook.com/openerp
@@ -160,35 +84,5 @@
-
-
- Social Marketing As a Source of Leads
-
-
-
- 0
-
-
-
-
-
-
-
-
-
-
- Apart from being an enterprise management software, OpenERP is
- used nowadays for a great variety of enterprise frontends.
-
- The talk illustrates the impact of OpenERP in areas such as the
- company website, online events management, eCommerce, online
- recruitments, social media marketing, etc.
-
-
-
-
-
-
-
diff --git a/addons/website_event_track/data/website_event_track_demo.xml b/addons/website_event_track/data/website_event_track_demo.xml
new file mode 100644
index 00000000000..b54d114e127
--- /dev/null
+++ b/addons/website_event_track/data/website_event_track_demo.xml
@@ -0,0 +1,325 @@
+
+
+
+
+ Le Foyer du lac
+
+
+ Theatre
+
+
+ Lauzelle
+
+
+ Foyer Royal
+
+
+ Biereau
+
+
+ Bruyère
+
+
+ How to develop a website module.
+
+
+
+
+
+
+ 3
+
+
+
+
+ How to integrate hardware materials with the OpenERP point of sale.
+
+
+
+
+
+
+
+
+
+ How to develop real time apps, the live chat module explained.
+
+
+
+
+
+
+
+
+
+ How to develop automated tests in the OpenERP web client.
+
+
+
+
+
+
+
+
+
+ The new way to promote your modules in the Apps platform and OpenERP website.
+
+
+
+
+
+
+
+
+
+ Detailed roadmap of accounting new modules and improvements for version 8.
+
+
+
+
+
+
+
+
+
+ A technical explanation of OpenERP as a CMS and a eCommerce platform for version 8.
+
+
+
+
+
+
+
+
+
+ Discover OpenERP CRM: How to optimize your sales, from leads to sales orders.
+
+
+
+
+
+ 2
+
+
+
+
+ How to use OpenERP for your HR process: recruitment, leaves management, appraisals, expenses, etc.
+
+
+
+
+
+
+ 2
+
+
+
+
+ Raising qualitive insights with the survey app
+
+
+
+
+
+ 5
+
+
+
+ Discover OpenERP Point-of-Sale: Your shop ready to use in 30 minutes.
+
+
+
+
+
+
+
+
+
+ Manage your events with OpenERP, the new training modules.
+
+
+
+
+
+
+
+
+
+ Advanced reporting with Google Spreadsheets integration.
+
+
+
+
+
+
+
+
+
+ New Paypal modules (portal, handling, installments).
+
+
+
+
+
+
+
+
+
+ OpenERP Mobile for Notes, Meetings and Messages.
+
+
+
+
+
+
+
+
+
+ OpenERP as your Enterprise Social Network.
+
+
+
+
+
+
+
+
+
+ The Art of Making an OpenERP Demo.
+
+
+
+
+
+
+
+
+
+ How to build your marketing strategy for the purpose of generating leads with OpenERP.
+
+
+
+
+
+ 5
+
+
+
+
+ Advanced lead management with OpenERP: tips and tricks from the fields
+
+
+
+
+
+ 5
+
+
+
+
+ New Certification Program (valid from Oct. 2013).
+
+
+
+
+
+
+
+
+
+ Recruiting high skilled talents with OpenERP HR apps
+
+
+
+
+
+ 7
+
+
+
+ Manage your KPIs (recomended to openERP partners).
+
+
+
+
+
+
+
+
+
+ Key Success factors selling OpenERP.
+
+
+
+
+
+
+
+
+
+ Merge proposals review, code sprint (entire day).
+
+
+
+
+
+
+
+
+
+ Merge proposals review, code sprint (entire afternoon)
+
+
+
+
+
+
+
+
+
+ OpenERP in 2014
+
+
+
+
+
+
+ 3
+
+
+ OpenERP Status & Strategy 2014
+
+
+
+
+
+
+
+
+ The new marketing strategy.
+
+
+
+
+
+
+ 6
+
+
+ Morning break
+
+
+
+
+
+
+
+ Lunch
+
+
+
+
+
+
+
+
diff --git a/addons/website_event_track/models/event.py b/addons/website_event_track/models/event.py
index 359b7df0067..c9d590d7068 100644
--- a/addons/website_event_track/models/event.py
+++ b/addons/website_event_track/models/event.py
@@ -23,6 +23,8 @@ from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.addons.website.models.website import slug
+import pytz
+
class event_track_tag(osv.osv):
_name = "event.track.tag"
_order = 'name'
@@ -79,7 +81,7 @@ class event_track(osv.osv):
'stage_id': fields.many2one('event.track.stage', 'Stage'),
'description': fields.html('Track Description', translate=True),
'date': fields.datetime('Track Date'),
- 'duration': fields.integer('Duration'),
+ 'duration': fields.float('Duration', digits=(16,2)),
'location_id': fields.many2one('event.track.location', 'Location'),
'event_id': fields.many2one('event.event', 'Event', required=True),
'color': fields.integer('Color Index'),
@@ -99,10 +101,11 @@ class event_track(osv.osv):
_defaults = {
'user_id': lambda self, cr, uid, ctx: uid,
'website_published': lambda self, cr, uid, ctx: False,
- 'duration': lambda *args: 60,
+ 'duration': lambda *args: 1.5,
'stage_id': _default_stage_id,
'priority': '2'
}
+
def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
stage_obj = self.pool.get('event.track.stage')
result = stage_obj.name_search(cr, uid, '', context=context)
@@ -117,6 +120,10 @@ class event_track(osv.osv):
#
class event_event(osv.osv):
_inherit = "event.event"
+ def _tz_get(self,cr,uid, context=None):
+ # put POSIX 'Etc/*' entries at the end to avoid confusing users - see bug 1086728
+ return [(tz,tz) for tz in sorted(pytz.all_timezones, key=lambda tz: tz if not tz.startswith('Etc/') else '_')]
+
def _get_tracks_tag_ids(self, cr, uid, ids, field_names, arg=None, context=None):
res = dict.fromkeys(ids, [])
for event in self.browse(cr, uid, ids, context=context):
@@ -134,11 +141,13 @@ class event_event(osv.osv):
'show_blog': fields.boolean('News'),
'tracks_tag_ids': fields.function(_get_tracks_tag_ids, type='one2many', relation='event.track.tag', string='Tags of Tracks'),
'allowed_track_tag_ids': fields.many2many('event.track.tag', string='Accepted Tags', help="List of available tags for track proposals."),
+ 'timezone_of_event': fields.selection(_tz_get, 'Event Timezone', size=64),
}
_defaults = {
'show_track_proposal': False,
'show_tracks': False,
'show_blog': False,
+ 'timezone_of_event':lambda self,cr,uid,c: self.pool.get('res.users').browse(cr, uid, uid, c).tz,
}
def _get_new_menu_pages(self, cr, uid, event, context=None):
context = context or {}
diff --git a/addons/website_event_track/static/src/css/website_event_track.css b/addons/website_event_track/static/src/css/website_event_track.css
index 7862175ec27..f6c01f8f19e 100644
--- a/addons/website_event_track/static/src/css/website_event_track.css
+++ b/addons/website_event_track/static/src/css/website_event_track.css
@@ -52,3 +52,43 @@
background-image: -ms-linear-gradient(top, #C2792A, #DB9141);
background-image: -o-linear-gradient(top, #C2792A, #DB9141);
}
+.event_color_0 {
+ background-color: white;
+ color: #5a5a5a;
+}
+.event_color_1 {
+ background-color: #cccccc;
+ color: #424242;
+}
+.event_color_2 {
+ background-color: #ffc7c7;
+ color: #7a3737;
+}
+.event_color_3 {
+ background-color: #fff1c7;
+ color: #756832;
+}
+.event_color_4 {
+ background-color: #e3ffc7;
+ color: #5d6937;
+}
+.event_color_5 {
+ background-color: #c7ffd5;
+ color: #1a7759;
+}
+.event_color_6 {
+ background-color: #c7ffff;
+ color: #1a5d83;
+}
+.event_color_7 {
+ background-color: #c7d5ff;
+ color: #3b3e75;
+}
+.event_color_8 {
+ background-color: #e3c7ff;
+ color: #4c3668;
+}
+.event_color_9 {
+ background-color: #ffc7f1;
+ color: #6d2c70;
+}
diff --git a/addons/website_event_track/static/src/js/website_event_track.js b/addons/website_event_track/static/src/js/website_event_track.js
new file mode 100644
index 00000000000..8093b9e7bca
--- /dev/null
+++ b/addons/website_event_track/static/src/js/website_event_track.js
@@ -0,0 +1,24 @@
+$(document).ready(function() {
+
+ jQuery.expr[":"].Contains = jQuery.expr.createPseudo(function(arg) {
+ return function( elem ) {
+ return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
+ };
+ });
+
+ $("#event_track_search").bind('keyup', function(e){
+ var change_text = $(this).val();
+ $('.event_track').removeClass('invisible');
+
+ $("#search_summary").removeClass('invisible');
+ if (change_text) {
+ $("#search_number").text($(".event_track:Contains("+change_text+")").length);
+ $(".event_track:not(:Contains("+change_text+"))").addClass('invisible');
+ } else {
+ $("#search_number").text(30);
+ }
+
+ event.preventDefault();
+ });
+
+});
diff --git a/addons/website_event_track/views/event_backend.xml b/addons/website_event_track/views/event_backend.xml
index ad262b6122e..c028b8b47d4 100644
--- a/addons/website_event_track/views/event_backend.xml
+++ b/addons/website_event_track/views/event_backend.xml
@@ -162,6 +162,9 @@
+
+
+
@@ -226,7 +229,7 @@
Regular Talks. These are standard talks with slides,
- alocated in slots of 30 minutes.
+ alocated in slots of 60 minutes.
- Lightning Talks. These are 10 minutes talks on many
+ Lightning Talks. These are 30 minutes talks on many
different topics. Most topics are accepted in lightning talks.
diff --git a/addons/website_gengo/controllers/main.py b/addons/website_gengo/controllers/main.py
index b1776f9974a..f80c7cbb34b 100644
--- a/addons/website_gengo/controllers/main.py
+++ b/addons/website_gengo/controllers/main.py
@@ -4,9 +4,6 @@ import openerp
from openerp.addons.web import http
from openerp.addons.web.http import request
import time
-import json
-from openerp.tools.translate import _
-
GENGO_DEFAULT_LIMIT = 20
@@ -40,21 +37,3 @@ class website_gengo(http.Controller):
def post_gengo_jobs(self):
request.registry['base.gengo.translations']._sync_request(request.cr, request.uid, limit=GENGO_DEFAULT_LIMIT, context=request.context)
return True
-
- @http.route('/website/gengo_callback/', type='http', auth='none')
- def gengo_callback(self,term,**post):
- if post and post.get('job'):
- translation_pool = request.registry['ir.translation']
- base_gengo_pool = request.registry['base.gengo.translations']
- job, vals = json.loads(post['job']), {}
- if job.get('status') == 'approved':
- vals.update({'state': 'translated', 'value': job.get('body_tgt')})
- flag, gengo = base_gengo_pool.gengo_authentication(request.cr, openerp.SUPERUSER_ID, context=request.context)
- job_comment = gengo.getTranslationJobComments(id=job.get('job_id'))
- if job_comment['opstat']=='ok':
- gengo_comments=""
- for comment in job_comment['response']['thread']:
- gengo_comments += _('%s\n-- Commented on %s by %s.\n\n') % (comment['body'], time.ctime(comment['ctime']), comment['author'])
- vals.update({'gengo_comment': gengo_comments})
- if vals:
- translation_pool.write(request.cr, openerp.SUPERUSER_ID, term.id, vals)
diff --git a/addons/website_gengo/static/src/js/website_gengo.js b/addons/website_gengo/static/src/js/website_gengo.js
index 75c82f83a46..a1755ed1290 100644
--- a/addons/website_gengo/static/src/js/website_gengo.js
+++ b/addons/website_gengo/static/src/js/website_gengo.js
@@ -56,7 +56,7 @@
new_content:self.getInitialContent(this),
translation_id: data.oeTranslationId || null,
gengo_translation: gengo_service_level,
- gengo_comment:"Original page:" + document.URL
+ gengo_comment:"\nOriginal Page: " + document.URL
});
});
openerp.jsonRpc('/website/set_translations', 'call', {
diff --git a/addons/website_partner/website_partner_demo.xml b/addons/website_partner/website_partner_demo.xml
index bedd472cc2a..8909001b790 100644
--- a/addons/website_partner/website_partner_demo.xml
+++ b/addons/website_partner/website_partner_demo.xml
@@ -2,6 +2,13 @@
+
+ True
+
+
+ True
+
+
True
diff --git a/addons/website_sale/static/src/js/website.tour.shop.js b/addons/website_sale/static/src/js/website.tour.shop.js
index adb4a9e556c..6291f2fc54e 100644
--- a/addons/website_sale/static/src/js/website.tour.shop.js
+++ b/addons/website_sale/static/src/js/website.tour.shop.js
@@ -66,39 +66,23 @@
},
{
waitNot: '.product_price .oe_currency_value:containsExact(1.00)',
- element: '#wrap img.img:first',
+ element: '#wrap img.product_detail_img',
placement: 'top',
title: _t("Update image"),
content: _t("Click here to set an image describing your product."),
},
{
- element: 'button.hover-edition-button:visible',
+ element: 'img[alt=ipad]',
placement: 'top',
- title: _t("Update image"),
- content: _t("Click here to set an image describing your product."),
- },
- {
- wait: 500,
- element: '.well a.pull-right',
- placement: 'bottom',
title: _t("Select an Image"),
- content: _t("Let's select an existing image."),
- popover: { fixed: true },
+ content: _t("Let's select an ipad image."),
},
{
- element: 'img[alt=imac]',
- placement: 'bottom',
- title: _t("Select an Image"),
- content: _t("Let's select an imac image."),
- popover: { fixed: true },
- },
- {
- waitNot: 'img[alt=imac]',
+ waitFor: '.media_selected img[alt=ipad]',
element: '.modal-content button.save',
- placement: 'bottom',
- title: _t("Select this Image"),
- content: _t("Click to add the image to the product decsription."),
- popover: { fixed: true },
+ placement: 'top',
+ title: _t("Save this Image"),
+ content: _t("Click on save to add the image to the product decsription."),
},
{
waitNot: '.modal-content:visible',
- on -
- -Read Next
+- Apart from being an enterprise management software, OpenERP is - used nowadays for a great variety of enterprise frontends. -
- The talk illustrates the impact of OpenERP in areas such as the - company website, online events management, eCommerce, online - recruitments, social media marketing, etc. -
-- Apart from being an enterprise management software, OpenERP is - used nowadays for a great variety of enterprise frontends. -
- The talk illustrates the impact of OpenERP in areas such as the - company website, online events management, eCommerce, online - recruitments, social media marketing, etc. -
-- Apart from being an enterprise management software, OpenERP is - used nowadays for a great variety of enterprise frontends. -
- The talk illustrates the impact of OpenERP in areas such as the - company website, online events management, eCommerce, online - recruitments, social media marketing, etc. -
-You can click on cells to highlight your interests.
-- Monday, 3rd June - 23 talks -
-10:00
- Room 5 -
10:30
11:00
12:00
15:00
10:30
11:00
+
+ talks
+
++
Duration
- minutes
+ hours
Location
-
Regular Talks. These are standard talks with slides,
- alocated in slots of 30 minutes.
+ alocated in slots of 60 minutes.
-
- Lightning Talks. These are 10 minutes talks on many
+ Lightning Talks. These are 30 minutes talks on many
different topics. Most topics are accepted in lightning talks.
diff --git a/addons/website_gengo/controllers/main.py b/addons/website_gengo/controllers/main.py index b1776f9974a..f80c7cbb34b 100644 --- a/addons/website_gengo/controllers/main.py +++ b/addons/website_gengo/controllers/main.py @@ -4,9 +4,6 @@ import openerp from openerp.addons.web import http from openerp.addons.web.http import request import time -import json -from openerp.tools.translate import _ - GENGO_DEFAULT_LIMIT = 20 @@ -40,21 +37,3 @@ class website_gengo(http.Controller): def post_gengo_jobs(self): request.registry['base.gengo.translations']._sync_request(request.cr, request.uid, limit=GENGO_DEFAULT_LIMIT, context=request.context) return True - - @http.route('/website/gengo_callback/