diff --git a/addons/gamification/data/gamification_karma_rank_data.xml b/addons/gamification/data/gamification_karma_rank_data.xml index b91ee3dd4dc..2a5ad0231fe 100644 --- a/addons/gamification/data/gamification_karma_rank_data.xml +++ b/addons/gamification/data/gamification_karma_rank_data.xml @@ -13,9 +13,8 @@ Newbie

You just began the adventure! Welcome!

-

Keep going !

1
- + \ No newline at end of file diff --git a/addons/gamification/data/gamification_karma_rank_demo.xml b/addons/gamification/data/gamification_karma_rank_demo.xml index c34f93b486e..45b57ae34f3 100644 --- a/addons/gamification/data/gamification_karma_rank_demo.xml +++ b/addons/gamification/data/gamification_karma_rank_demo.xml @@ -1,5 +1,5 @@ - + 20 @@ -12,7 +12,11 @@ Student

You begin to understand things ! Keep going!

-

Keep going !

+ +
+
Reach the next rank and gain a very nice mug !
+ +
100
@@ -20,7 +24,11 @@ Bachelor

Hey ! You're not so dumb after all !

-

Keep going !

+ +
+
Reach the next rank and gain a very magic wand !
+ +
500
@@ -28,7 +36,11 @@ Master

You're good ! Really Good !

-

Keep going !

+ +
+
Reach the next rank and gain a very nice hat !
+ +
2000
@@ -36,7 +48,11 @@ Doctor

Ok, RESPECT !

-

Keep going !

+ +
+
Reach the next rank and gain a week-end with a unicorn !
+ +
10000
diff --git a/addons/gamification/models/gamification_karma_rank.py b/addons/gamification/models/gamification_karma_rank.py index e5a7897f44c..78b8e40ac50 100644 --- a/addons/gamification/models/gamification_karma_rank.py +++ b/addons/gamification/models/gamification_karma_rank.py @@ -19,9 +19,9 @@ class KarmaRank(models.Model): name = fields.Text(string='Rank Name', translate=True, required=True) description = fields.Html(string='Description', translate=html_translate, sanitize_attributes=False,) - description_reach_next = fields.Html( - string='Motivation phrase', translate=html_translate, sanitize_attributes=False, - help="Motivation phrase to reach next rank") + description_motivational = fields.Html( + string='Motivational', translate=html_translate, sanitize_attributes=False, + help="Motivational phrase to reach this rank") karma_min = fields.Integer(string='Required Karma', help='Minimum karma needed to reach this rank') user_ids = fields.One2many('res.users', 'rank_id', string='Users', help="Users having this rank") image = fields.Binary('Rank Icon') diff --git a/addons/gamification/static/img/rank_misc_hat.jpg b/addons/gamification/static/img/rank_misc_hat.jpg new file mode 100644 index 00000000000..68abf33bc14 Binary files /dev/null and b/addons/gamification/static/img/rank_misc_hat.jpg differ diff --git a/addons/gamification/static/img/rank_misc_mug.jpg b/addons/gamification/static/img/rank_misc_mug.jpg new file mode 100644 index 00000000000..09cc5567b0e Binary files /dev/null and b/addons/gamification/static/img/rank_misc_mug.jpg differ diff --git a/addons/gamification/static/img/rank_misc_unicorn.jpg b/addons/gamification/static/img/rank_misc_unicorn.jpg new file mode 100644 index 00000000000..5612d5f7855 Binary files /dev/null and b/addons/gamification/static/img/rank_misc_unicorn.jpg differ diff --git a/addons/gamification/static/img/rank_misc_wand.jpg b/addons/gamification/static/img/rank_misc_wand.jpg new file mode 100644 index 00000000000..4e2ec0457f3 Binary files /dev/null and b/addons/gamification/static/img/rank_misc_wand.jpg differ diff --git a/addons/gamification/views/gamification_karma_rank_views.xml b/addons/gamification/views/gamification_karma_rank_views.xml index f09d516ca88..f728cff538e 100644 --- a/addons/gamification/views/gamification_karma_rank_views.xml +++ b/addons/gamification/views/gamification_karma_rank_views.xml @@ -1,3 +1,4 @@ + @@ -35,8 +36,6 @@ - -
@@ -58,6 +57,7 @@ + diff --git a/addons/website_profile/controllers/main.py b/addons/website_profile/controllers/main.py index 92c69ae4c34..c0d6a278a0b 100644 --- a/addons/website_profile/controllers/main.py +++ b/addons/website_profile/controllers/main.py @@ -10,7 +10,6 @@ import werkzeug.wrappers from odoo import http, modules, tools from odoo.http import request from odoo.osv import expression -from odoo.tools import limited_image_resize class WebsiteProfile(http.Controller): @@ -30,6 +29,20 @@ class WebsiteProfile(http.Controller): return user.website_published and user.karma > 0 return False + def _get_default_avatar(self, field, headers, width, height): + img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') + with open(img_path, 'rb') as f: + image = f.read() + content = base64.b64encode(image) + dictheaders = dict(headers) if headers else {} + dictheaders['Content-Type'] = 'image/png' + headers = list(dictheaders.items()) + if not (width or height): + suffix = field.split('_')[-1] if '_' in field else 'large' + if suffix in ('small', 'medium', 'large', 'big'): + content = getattr(tools, 'image_resize_image_%s' % suffix)(content) + return content + def _check_user_profile_access(self, user_id): user_sudo = request.env['res.users'].sudo().browse(user_id) if user_sudo.karma == 0 or not user_sudo.website_published or \ @@ -60,16 +73,18 @@ class WebsiteProfile(http.Controller): @http.route([ '/profile/avatar/', ], type='http', auth="public", website=True, sitemap=False) - def get_user_profile_avatar(self, user_id=0, width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False, **post): + def get_user_profile_avatar(self, user_id, field='image_large', width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False, **post): + if field not in ('image_small', 'image_medium', 'image_large'): + return werkzeug.exceptions.Forbidden() + can_sudo = self._check_avatar_access(user_id, **post) - fname = post.get('field', 'image_medium') if can_sudo: status, headers, content = request.env['ir.http'].sudo().binary_content( - model='res.users', id=user_id, field=fname, + model='res.users', id=user_id, field=field, default_mimetype='image/png') else: status, headers, content = request.env['ir.http'].binary_content( - model='res.users', id=user_id, field=fname, + model='res.users', id=user_id, field=field, default_mimetype='image/png') if status == 301: return request.env['ir.http']._response_by_status(status, headers, content) @@ -77,19 +92,9 @@ class WebsiteProfile(http.Controller): return werkzeug.wrappers.Response(status=304) if not content: - img_path = modules.get_module_resource('web', 'static/src/img', 'placeholder.png') - with open(img_path, 'rb') as f: - image = f.read() - content = base64.b64encode(image) - dictheaders = dict(headers) if headers else {} - dictheaders['Content-Type'] = 'image/png' - headers = list(dictheaders.items()) - if not (width or height): - suffix = fname.split('_')[-1] - if suffix in ('small', 'medium', 'big'): - content = getattr(tools, 'image_resize_image_%s' % suffix)(content) + content = self._get_default_avatar(field, headers, width, height) - content = limited_image_resize( + content = tools.limited_image_resize( content, width=width, height=height, crop=crop, upper_limit=upper_limit, avoid_if_small=avoid_if_small) image_base64 = base64.b64decode(content) @@ -159,6 +164,7 @@ class WebsiteProfile(http.Controller): ranks = ranks.sorted(key=lambda b: b.karma_min) values = { 'ranks': ranks, + 'user': request.env.user, } return request.render("website_profile.rank_main", values) diff --git a/addons/website_profile/static/src/scss/website_profile.scss b/addons/website_profile/static/src/scss/website_profile.scss index c636bd40d92..b45b58a587c 100644 --- a/addons/website_profile/static/src/scss/website_profile.scss +++ b/addons/website_profile/static/src/scss/website_profile.scss @@ -127,7 +127,6 @@ $bronze: #eea91e; height: 128px; } } - border-bottom: 1px solid lightgray; .o_wprofile_next_rank_progress { background-color: lightgray; .o_wprofile_next_rank_progress_bar { diff --git a/addons/website_profile/views/website_profile.xml b/addons/website_profile/views/website_profile.xml index 06562d0e697..2a4752c2830 100644 --- a/addons/website_profile/views/website_profile.xml +++ b/addons/website_profile/views/website_profile.xml @@ -181,6 +181,7 @@ +
@@ -299,7 +300,7 @@ Ranks & Badges

- Do not stop learning with Odoo. Collects points on the forum or the eLearning platform. Those points will make you reach new ranks. + Do not stop learning with . Collects points on the forum or the eLearning platform. Those points will make you reach new ranks.

How do I earn badges? When you finish a course, reach milestones, you're awarded badges. diff --git a/addons/website_sale_slides/data/website_sale_slides_demo.xml b/addons/website_sale_slides/data/website_sale_slides_demo.xml index c7ff453e837..dc223fb388e 100644 --- a/addons/website_sale_slides/data/website_sale_slides_demo.xml +++ b/addons/website_sale_slides/data/website_sale_slides_demo.xml @@ -46,7 +46,7 @@ 10 -

Tools you will need to complete this course.
+ Tools you will need to complete this course. How to find quality wood @@ -59,7 +59,7 @@ 5 -
Learn of to identify quality wood in order to create solid furnitures.
+ Learn of to identify quality wood in order to create solid furnitures.
How to create your own piece of furniture @@ -72,7 +72,7 @@ 0 -
From a piece of wood to a fully functional furniture, step by step.
+ From a piece of wood to a fully functional furniture, step by step.
diff --git a/addons/website_slides/controllers/main.py b/addons/website_slides/controllers/main.py index 6a75730daa0..ba36df3fd00 100644 --- a/addons/website_slides/controllers/main.py +++ b/addons/website_slides/controllers/main.py @@ -6,7 +6,7 @@ import itertools import logging import werkzeug -from odoo import http, _ +from odoo import http, modules, tools, _ from odoo.exceptions import AccessError, UserError from odoo.http import request from odoo.osv import expression @@ -14,7 +14,6 @@ from odoo.osv import expression from odoo.addons.http_routing.models.ir_http import slug from odoo.addons.website_profile.controllers.main import WebsiteProfile from odoo.addons.website.models.ir_http import sitemap_qs2dom -from odoo.tools import html2plaintext _logger = logging.getLogger(__name__) @@ -267,7 +266,7 @@ class WebsiteSlides(WebsiteProfile): 'message_post_hash': channel._sign_token(request.env.user.partner_id.id), 'message_post_pid': request.env.user.partner_id.id, 'last_message_id': last_message_data.get('id'), - 'last_message': html2plaintext(last_message_data.get('body', '')), + 'last_message': tools.html2plaintext(last_message_data.get('body', '')), 'last_rating_value': last_message_data.get('rating_value'), }) @@ -362,6 +361,36 @@ class WebsiteSlides(WebsiteProfile): return request.redirect('/web/login?redirect=/slides/slide/%s' % (slide.id)) return request.render("website.403") + @http.route('/slides/slide//get_image', type='http', auth="public", website=True, sitemap=False) + def slide_get_image(self, slide_id, field='image_medium', width=0, height=0, crop=False, avoid_if_small=False, upper_limit=False): + # Protect infographics by limiting access to 256px (large) images + if field not in ('image_small', 'image_medium', 'image_large'): + return werkzeug.exceptions.Forbidden() + + slide = request.env['slide.slide'].sudo().browse(slide_id).exists() + if not slide: + raise werkzeug.exceptions.NotFound() + + status, headers, content = request.env['ir.http'].sudo().binary_content( + model='slide.slide', id=slide.id, field=field, + default_mimetype='image/png') + if status == 301: + return request.env['ir.http']._response_by_status(status, headers, content) + if status == 304: + return werkzeug.wrappers.Response(status=304) + + if not content: + content = self._get_default_avatar(field, headers, width, height) + + content = tools.limited_image_resize( + content, width=width, height=height, crop=crop, upper_limit=upper_limit, avoid_if_small=avoid_if_small) + + image_base64 = base64.b64decode(content) + headers.append(('Content-Length', len(image_base64))) + response = request.make_response(image_base64, headers) + response.status_code = status + return response + # JSONRPC @http.route('/slides/slide/like', type='json', auth="user", website=True) def slide_like(self, slide_id, upvote): diff --git a/addons/website_slides/data/slide_slide_demo.xml b/addons/website_slides/data/slide_slide_demo.xml index cf47aca1637..8971ec2fa8f 100644 --- a/addons/website_slides/data/slide_slide_demo.xml +++ b/addons/website_slides/data/slide_slide_demo.xml @@ -12,7 +12,7 @@ 40 -
A summary of know-how: how and what.
+ A summary of know-how: how and what. @@ -25,7 +25,7 @@ 5 -
Just some basics Tree Infographic.
+ Just some basics Tree Infographic.
Interesting Tree Facts @@ -37,7 +37,7 @@ 10 -
Just some basics Interesting Tree Facts.
+ Just some basics Interesting Tree Facts.
Energy Efficiency Facts @@ -49,7 +49,7 @@ 15 -
Just some basics Energy Efficiency Facts.
+ Just some basics Energy Efficiency Facts.
How to plant a potted tree @@ -63,7 +63,7 @@ 0 -
Jim and Todd plant a potted tree for a customer of Knecht's Nurseries and Landscaping. Narrated by Leif Knecht, owner.
+ Jim and Todd plant a potted tree for a customer of Knecht's Nurseries and Landscaping. Narrated by Leif Knecht, owner.
A little chat with Harry Potted @@ -110,7 +110,7 @@ 5 -
We had a little chat with Harry Potted, sure he had interesting things to say !
+ We had a little chat with Harry Potted, sure he had interesting things to say !
3 Main Methodologies @@ -123,7 +123,7 @@ 20 -
A summary of know-how: how and what.
+ A summary of know-how: how and what.
diff --git a/addons/website_slides/models/slide_channel.py b/addons/website_slides/models/slide_channel.py index 9d51ea52d1c..c782b2813d4 100644 --- a/addons/website_slides/models/slide_channel.py +++ b/addons/website_slides/models/slide_channel.py @@ -136,7 +136,7 @@ class Channel(models.Model): @api.depends('channel_partner_ids.channel_id') def _compute_members_count(self): - read_group_res = self.env['slide.channel.partner'].sudo().read_group([('channel_id', 'in', self.ids)], [], 'channel_id') + read_group_res = self.env['slide.channel.partner'].sudo().read_group([('channel_id', 'in', self.ids)], ['channel_id'], 'channel_id') data = dict((res['channel_id'][0], res['channel_id_count']) for res in read_group_res) for channel in self: channel.members_count = data.get(channel.id, 0) @@ -154,7 +154,7 @@ class Channel(models.Model): channel.valid_channel_partner_ids = result.get(channel.id, False) channel.is_member = self.env.user.partner_id.id in channel.valid_channel_partner_ids if channel.valid_channel_partner_ids else False - @api.depends('slide_ids.slide_type', 'slide_ids.is_published', + @api.depends('slide_ids.slide_type', 'slide_ids.is_published', 'slide_ids.completion_time', 'slide_ids.likes', 'slide_ids.dislikes', 'slide_ids.total_views') def _compute_slides_statistics(self): result = dict((cid, dict(total_slides=0, total_views=0, total_votes=0, total_time=0)) for cid in self.ids) diff --git a/addons/website_slides/models/slide_slide.py b/addons/website_slides/models/slide_slide.py index 5dc5dcc4d5a..617ad2e1421 100644 --- a/addons/website_slides/models/slide_slide.py +++ b/addons/website_slides/models/slide_slide.py @@ -288,7 +288,7 @@ class Slide(models.Model): @api.multi def write(self, values): - if values.get('website_published') and any(not slide.channel_id.can_publish for slide in self): + if 'website_published' in values and any(not slide.channel_id.can_publish for slide in self): values.pop('website_published') if values.get('url') and values['url'] != self.url: diff --git a/addons/website_slides/static/src/scss/website_slides.scss b/addons/website_slides/static/src/scss/website_slides.scss index feb6acd6ffb..75dd02662e4 100644 --- a/addons/website_slides/static/src/scss/website_slides.scss +++ b/addons/website_slides/static/src/scss/website_slides.scss @@ -149,6 +149,10 @@ div .o_wslides_home_main { background: linear-gradient(150deg, #875A7B 20%, #62495B 80%) !important; opacity: 0.95; + a { + color: #FFFFFF; + } + nav { .breadcrumb-item::before { font-weight: bold; diff --git a/addons/website_slides/views/website_slides_templates.xml b/addons/website_slides/views/website_slides_templates.xml index af82d23701c..e06e75d0b66 100644 --- a/addons/website_slides/views/website_slides_templates.xml +++ b/addons/website_slides/views/website_slides_templates.xml @@ -52,15 +52,11 @@ -
- - +
+ + + +
@@ -73,7 +69,7 @@
- +
- +
@@ -318,10 +316,9 @@
- +
diff --git a/addons/website_slides/views/website_slides_templates_homepage.xml b/addons/website_slides/views/website_slides_templates_homepage.xml index caeab4f77df..4364b486987 100644 --- a/addons/website_slides/views/website_slides_templates_homepage.xml +++ b/addons/website_slides/views/website_slides_templates_homepage.xml @@ -142,6 +142,11 @@ + + + + +
- steps + steps
@@ -312,7 +317,6 @@
-
@@ -353,9 +357,7 @@
- - - +
@@ -369,17 +371,18 @@ @@ -407,10 +410,10 @@
-