[MERGE] gamification, website_slides{_survey}: add certification badges section to ranks badge page

This merge adds a section to distinguish the certification badges from the
other badges users may obtain in eLearning. Certification badges are available
on the ranks page, linked to a running survey. Clicking on them directly
redirects into the linked course.

Other commits in this merge include

  * renaming a category field on challenge to challenge_category to ease
    its finding in code;
  * renaming some statistics fields on badge model to ease its understanding;
  * various usability improvements and fixes;

Task ID : 1961053
PR #32594

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Odoo's Mergebot
2019-11-22 19:18:38 +01:00
committed by GitHub
25 changed files with 215 additions and 92 deletions
+2 -2
View File
@@ -297,7 +297,7 @@ Thank you,
<field name="report_message_frequency">never</field>
<field name="user_domain" eval="str([('groups_id.id', '=', ref('base.group_user'))])" />
<field name="state">inprogress</field>
<field name="category">other</field>
<field name="challenge_category">other</field>
</record>
<record model="gamification.challenge" id="challenge_base_configure">
@@ -307,7 +307,7 @@ Thank you,
<field name="report_message_frequency">never</field>
<field name="user_domain" eval="str([('groups_id.id', '=', ref('base.group_erp_manager'))])" />
<field name="state">inprogress</field>
<field name="category">other</field>
<field name="challenge_category">other</field>
</record>
<!-- lines -->
+8 -8
View File
@@ -107,8 +107,8 @@ class GamificationBadge(models.Model):
'gamification.badge.user', 'badge_id',
string='Owners', help='The list of instances of this badge granted to users')
stat_count = fields.Integer("Total", compute='_get_owners_info', help="The number of time this badge has been received.")
stat_count_distinct = fields.Integer("Number of users", compute='_get_owners_info', help="The number of time this badge has been received by unique users.")
granted_count = fields.Integer("Total", compute='_get_owners_info', help="The number of time this badge has been received.")
granted_users_count = fields.Integer("Number of users", compute='_get_owners_info', help="The number of time this badge has been received by unique users.")
unique_owner_ids = fields.Many2many(
'res.users', string="Unique Owners", compute='_get_owners_info',
help="The list of unique users having received this badge.")
@@ -139,8 +139,8 @@ class GamificationBadge(models.Model):
the total number of users this badge was granted to
"""
self.env.cr.execute("""
SELECT badge_id, count(user_id) as stat_count,
count(distinct(user_id)) as stat_count_distinct,
SELECT badge_id, count(user_id) as granted_count,
count(distinct(user_id)) as granted_users_count,
array_agg(distinct(user_id)) as unique_owner_ids
FROM gamification_badge_user
WHERE badge_id in %s
@@ -148,14 +148,14 @@ class GamificationBadge(models.Model):
""", [tuple(self.ids)])
defaults = {
'stat_count': 0,
'stat_count_distinct': 0,
'granted_count': 0,
'granted_users_count': 0,
'unique_owner_ids': [],
}
mapping = {
badge_id: {
'stat_count': count,
'stat_count_distinct': distinct_count,
'granted_count': count,
'granted_users_count': distinct_count,
'unique_owner_ids': owner_ids,
}
for (badge_id, count, distinct_count, owner_ids) in self.env.cr._obj
+1 -1
View File
@@ -123,7 +123,7 @@ class Challenge(models.Model):
last_report_date = fields.Date("Last Report Date", default=fields.Date.today)
next_report_date = fields.Date("Next Report Date", compute='_get_next_report_date', store=True)
category = fields.Selection([
challenge_category = fields.Selection([
('hr', 'Human Resources / Engagement'),
('other', 'Settings / Gamification Tools'),
], string="Appears in", required=True, default='hr',
+6 -6
View File
@@ -35,7 +35,7 @@
<field name="arch" type="xml">
<tree string="Badge List">
<field name="name"/>
<field name="stat_count"/>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="stat_my"/>
<field name="rule_auth"/>
@@ -91,11 +91,11 @@
<field name="challenge_ids" mode="kanban" widget="many2many" nolabel="1" context="{'default_reward_id': active_id}" />
<field name="level"/>
</group>
<group string="Statistics">
<group id="badge_statistics" string="Statistics">
<group>
<field name="stat_count"/>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="stat_count_distinct"/>
<field name="granted_users_count"/>
</group>
<group>
<field name="stat_my"/>
@@ -117,7 +117,7 @@
<field name="name"/>
<field name="description"/>
<field name="stat_my"/>
<field name="stat_count"/>
<field name="granted_count"/>
<field name="stat_this_month"/>
<field name="unique_owner_ids"/>
<field name="stat_my_monthly_sending"/>
@@ -141,7 +141,7 @@
</span>
<div t-if="record.remaining_sending.value == 0" class="oe_grey">Can not grant</div>
<div>
<strong><t t-esc="record.stat_count.raw_value"/></strong> granted,
<strong><t t-esc="record.granted_count.raw_value"/></strong> granted,
<strong><t t-esc="record.stat_this_month.raw_value"/></strong> this month
</div>
<div t-if="record.description.value" class="o_kanban_badge_description">
+2 -2
View File
@@ -123,7 +123,7 @@
</div>
</group>
<group string="Category" groups="base.group_no_one">
<field name="category" widget="radio" />
<field name="challenge_category" widget="radio" />
</group>
</page>
</notebook>
@@ -218,7 +218,7 @@
<filter name="inprogress" string="Running Challenges"
domain="[('state', '=', 'inprogress')]"/>
<filter name="hr_challenges" string="HR Challenges"
domain="[('category', '=', 'hr')]"/>
domain="[('challenge_category', '=', 'hr')]"/>
<field name="name"/>
<group expand="0" string="Group By">
<filter string="State" name="state" domain="[]" context="{'group_by':'state'}"/>
+2 -2
View File
@@ -18,12 +18,12 @@ class HrEmployeeBase(models.AbstractModel):
'gamification.badge.user', 'employee_id',
help="Badges directly linked to the employee")
@api.depends('user_id.goal_ids.challenge_id.category')
@api.depends('user_id.goal_ids.challenge_id.challenge_category')
def _compute_employee_goals(self):
for employee in self:
employee.goal_ids = self.env['gamification.goal'].search([
('user_id', '=', employee.user_id.id),
('challenge_id.category', '=', 'hr'),
('challenge_id.challenge_category', '=', 'hr'),
])
@api.depends('direct_badge_ids', 'user_id.badge_ids.employee_id')
@@ -7,7 +7,7 @@
<field name="inherit_id" ref="gamification.badge_form_view"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button class="oe_stat_button" type="object" name="get_granted_employees" attrs="{'invisible': [('stat_count','=',0)]}" icon="fa-user">
<button class="oe_stat_button" type="object" name="get_granted_employees" attrs="{'invisible': [('granted_count','=',0)]}" icon="fa-user">
<field name="granted_employees_count" string="Granted" widget="statinfo"/>
</button>
</div>
@@ -19,7 +19,7 @@
<field name="name">Goals History</field>
<field name="view_mode">tree,kanban</field>
<field name="context">{'search_default_group_by_user': True, 'search_default_group_by_definition': True}</field>
<field name="domain">[('challenge_id.category', '=', 'hr')]</field>
<field name="domain">[('challenge_id.challenge_category', '=', 'hr')]</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new goal
@@ -35,7 +35,7 @@
<field name="name">Challenges</field>
<field name="res_model">gamification.challenge</field>
<field name="view_mode">kanban,tree,form</field>
<field name="domain">[('category', '=', 'hr')]</field>
<field name="domain">[('challenge_category', '=', 'hr')]</field>
<field name="context">{'search_default_inprogress':True, 'default_inprogress':True}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record model="gamification.badge" id="vendor_certification_badge">
<field name="name">MyCompany Vendor</field>
<field name="description">Congratulation, you are now official vendor of MyCompany</field>
<field name="rule_auth">nobody</field>
<field name="image_1920" type="base64" file="gamification/static/img/badge_good_job-image.png"/>
</record>
<!-- Odoo Vendor Certification -->
<record model="survey.survey" id="vendor_certification">
<field name="title">MyCompany Vendor Certification</field>
@@ -18,6 +25,8 @@
<field name="attempts_limit">2</field>
<field name="description">&lt;p&gt;Test your vendor skills!&lt;/p&gt;</field>
<field name="thank_you_message">&lt;p&gt;&lt;/p&gt;</field>
<field name="certification_give_badge">True</field>
<field name="certification_badge_id" ref="vendor_certification_badge"/>
</record>
<!-- Page 1 -->
<record model="survey.question" id="vendor_certification_page_1">
+1 -1
View File
@@ -7,4 +7,4 @@ from odoo import models, fields
class Challenge(models.Model):
_inherit = 'gamification.challenge'
category = fields.Selection(selection_add=[('certification', 'Certifications')])
challenge_category = fields.Selection(selection_add=[('certification', 'Certifications')])
+3 -1
View File
@@ -705,6 +705,8 @@ class Survey(models.Model):
# ------------------------------------------------------------
# GAMIFICATION / BADGES
# ------------------------------------------------------------
def _prepare_challenge_category(self):
return 'certification'
def _create_certification_badge_trigger(self):
self.ensure_one()
@@ -725,7 +727,7 @@ class Survey(models.Model):
'reward_id': self.certification_badge_id.id,
'state': 'inprogress',
'period': 'once',
'category': 'certification',
'challenge_category': self._prepare_challenge_category(),
'reward_realtime': True,
'report_message_frequency': 'never',
'user_domain': [('karma', '>', 0)],
+7 -7
View File
@@ -31,7 +31,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_teacher">
<field name="definition_id" eval="ref('definition_teacher')"/>
@@ -66,7 +66,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_nice_answer">
<field name="definition_id" eval="ref('definition_nice_answer')"/>
@@ -101,7 +101,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_good_answer">
<field name="definition_id" eval="ref('definition_good_answer')"/>
@@ -136,7 +136,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_great_answer">
<field name="definition_id" eval="ref('definition_great_answer')"/>
@@ -173,7 +173,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_enlightened">
<field name="definition_id" eval="ref('definition_enlightened')"/>
@@ -208,7 +208,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_guru">
<field name="definition_id" eval="ref('definition_guru')" />
@@ -244,7 +244,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_self_learner">
<field name="definition_id" eval="ref('definition_self_learner')"/>
@@ -38,7 +38,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_critic">
<field name="definition_id" eval="ref('definition_critic')"/>
@@ -74,7 +74,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_disciplined">
<field name="definition_id" eval="ref('definition_disciplined')"/>
@@ -110,7 +110,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_editor">
<field name="definition_id" eval="ref('definition_editor')"/>
@@ -145,7 +145,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_supporter">
<field name="definition_id" eval="ref('definition_supporter')" />
@@ -181,7 +181,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_peer_pressure">
<field name="definition_id" eval="ref('definition_peer_pressure')" />
@@ -34,7 +34,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_configure_profile">
<field name="definition_id" eval="ref('definition_configure_profile')"/>
@@ -70,7 +70,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_commentator">
<field name="definition_id" eval="ref('definition_commentator')"/>
@@ -105,7 +105,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_pundit">
<field name="definition_id" eval="ref('definition_pundit')" />
@@ -129,7 +129,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_chief_commentator">
<field name="definition_id" eval="ref('definition_commentator')"/>
@@ -164,7 +164,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_taxonomist">
<field name="definition_id" eval="ref('definition_taxonomist')" />
+11 -11
View File
@@ -31,7 +31,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_popular_question">
<field name="definition_id" eval="ref('definition_popular_question')"/>
@@ -67,7 +67,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_notable_question">
<field name="definition_id" eval="ref('definition_notable_question')"/>
@@ -102,7 +102,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_famous_question">
<field name="definition_id" eval="ref('definition_famous_question')"/>
@@ -139,7 +139,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_favorite_question_1">
<field name="definition_id" eval="ref('definition_favorite_question_1')"/>
@@ -174,7 +174,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_favorite_question_5">
<field name="definition_id" eval="ref('definition_favorite_question_5')"/>
@@ -209,7 +209,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_stellar_question_25">
<field name="definition_id" eval="ref('definition_stellar_question_25')"/>
@@ -246,7 +246,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_student">
<field name="definition_id" eval="ref('definition_student')"/>
@@ -281,7 +281,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_nice_question">
<field name="definition_id" eval="ref('definition_nice_question')"/>
@@ -316,7 +316,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_good_question">
<field name="definition_id" eval="ref('definition_good_question')"/>
@@ -351,7 +351,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_great_question">
<field name="definition_id" eval="ref('definition_great_question')" />
@@ -387,7 +387,7 @@
<field name="reward_realtime">True</field>
<field name="user_domain">[('karma', '>', 0)]</field>
<field name="state">inprogress</field>
<field name="category">forum</field>
<field name="challenge_category">forum</field>
</record>
<record model="gamification.challenge.line" id="line_scholar">
<field name="definition_id" eval="ref('definition_scholar')" />
+1 -1
View File
@@ -7,4 +7,4 @@ from odoo import models, fields
class Challenge(models.Model):
_inherit = 'gamification.challenge'
category = fields.Selection(selection_add=[('forum', 'Website / Forum')])
challenge_category = fields.Selection(selection_add=[('forum', 'Website / Forum')])
+8 -4
View File
@@ -168,11 +168,10 @@ class WebsiteProfile(http.Controller):
"""
domain = [('website_published', '=', True)]
if 'badge_category' in kwargs:
domain = expression.AND([[('challenge_ids.category', '=', kwargs.get('badge_category'))], domain])
domain = expression.AND([[('challenge_ids.challenge_category', '=', kwargs.get('badge_category'))], domain])
return domain
@http.route('/profile/ranks_badges', type='http', auth="public", website=True, sitemap=True)
def view_ranks_badges(self, **kwargs):
def _prepare_ranks_badges_values(self, **kwargs):
ranks = []
if 'badge_category' not in kwargs:
Rank = request.env['gamification.karma.rank']
@@ -180,7 +179,7 @@ class WebsiteProfile(http.Controller):
Badge = request.env['gamification.badge']
badges = Badge.sudo().search(self._prepare_badges_domain(**kwargs))
badges = sorted(badges, key=lambda b: b.stat_count_distinct, reverse=True)
badges = badges.sorted("granted_users_count", reverse=True)
values = self._prepare_user_values(searches={'badges': True})
values.update({
@@ -188,6 +187,11 @@ class WebsiteProfile(http.Controller):
'badges': badges,
'user': request.env.user,
})
return values
@http.route('/profile/ranks_badges', type='http', auth="public", website=True, sitemap=True)
def view_ranks_badges(self, **kwargs):
values = self._prepare_ranks_badges_values(**kwargs)
return request.render("website_profile.rank_badge_main", values)
# All Users Page
@@ -228,6 +228,10 @@ $owprofile-color-bg: mix($body-bg, #efeff4);
}
}
.wprofile_badge_img {
height: 2.5em;
}
// Other stuffs
.country_flag {
@@ -423,33 +423,40 @@
</template>
<template id="badge_content" name="Badges Page content">
<div class="row">
<div class="col-12">
<h1 class="mt-4 mt-lg-2">Badges</h1>
<p class="lead">
Besides gaining reputation with your questions and answers,
you receive badges for being especially helpful.<br class="d-none d-lg-inline-block"/>Badges
appear on your profile page, and your posts.
</p>
<div id="website_profile_badges">
<div class="row">
<div class="col-12">
<h1 class="mt-4 mt-lg-2">Badges</h1>
<p class="lead">
Besides gaining reputation with your questions and answers,
you receive badges for being especially helpful.<br class="d-none d-lg-inline-block"/>Badges
appear on your profile page, and your posts.
</p>
</div>
</div>
<div class="row col-12 align-items-center p-0" t-foreach="badges" t-as="badge">
<div class="col-3 d-flex align-items-center">
<t t-call="website_profile.badge_header"/>
</div>
<div class="col-6">
<span t-field="badge.description"/>
</div>
<div class="col-3 text-right">
<b t-esc="badge.granted_users_count"/>
<i class="text-muted"> awarded users</i>
</div>
</div>
</div>
<table class="table table-sm mb64">
<tr t-foreach="badges" t-as="badge">
<td class="align-middle">
<img t-if="not badge.image_1920 and badge.level" t-attf-src="/website_profile/static/src/img/badge_#{badge.level}.svg"
class="my-1" style="height:2.5em" t-att-alt="badge.name"/>
<img t-else="" t-att-src="website.image_url(badge, 'image_1024')" class="my-1" style="height:2.5em" t-att-alt="badge.name"/>
<h6 t-field="badge.name" class="d-inline my-0"/>
</td>
<td class="align-middle d-none d-md-table-cell">
<b t-esc="badge.stat_count_distinct"/>
<i class="text-muted"> awarded users</i>
</td>
<td class="align-middle">
<span t-field="badge.description"/>
</td>
</tr>
</table>
</template>
<template id="badge_header">
<img t-if="not badge.image_1920 and badge.level" t-attf-src="/website_profile/static/src/img/badge_#{badge.level}.svg"
class="my-1 mr-1 wprofile_badge_img" t-att-alt="badge.name"/>
<img t-else="" t-att-src="website.image_url(badge, 'image_1024')" class="my-1 mr-1 wprofile_badge_img" t-att-alt="badge.name"/>
<a t-if="badge_url" t-att-href="badge_url">
<h6 t-field="badge.name" class="d-inline my-0"/>
</a>
<h6 t-else="" t-field="badge.name" class="d-inline my-0"/>
</template>
<!--Private profile-->
+1 -1
View File
@@ -253,7 +253,7 @@ class WebsiteSlides(WebsiteProfile):
challenges_done = None
else:
challenges = request.env['gamification.challenge'].sudo().search([
('category', '=', 'slides'),
('challenge_category', '=', 'slides'),
('reward_id.is_published', '=', True)
], order='id asc', limit=5)
challenges_done = request.env['gamification.badge.user'].sudo().search([
@@ -27,7 +27,7 @@
</record>
<record id="badge_data_register_challenge" model="gamification.challenge">
<field name="name">Register to the platform</field>
<field name="category">slides</field>
<field name="challenge_category">slides</field>
<field name="period">once</field>
<field name="visibility_mode">personal</field>
<field name="report_message_frequency">never</field>
@@ -69,7 +69,7 @@
</record>
<record id="badge_data_profile_challenge" model="gamification.challenge">
<field name="name">Complete your profile</field>
<field name="category">slides</field>
<field name="challenge_category">slides</field>
<field name="period">once</field>
<field name="visibility_mode">personal</field>
<field name="report_message_frequency">never</field>
@@ -109,7 +109,7 @@
</record>
<record id="badge_data_course_challenge" model="gamification.challenge">
<field name="name">Complete a course</field>
<field name="category">slides</field>
<field name="challenge_category">slides</field>
<field name="period">once</field>
<field name="visibility_mode">personal</field>
<field name="report_message_frequency">never</field>
@@ -150,7 +150,7 @@
</record>
<record id="badge_data_certification_challenge" model="gamification.challenge">
<field name="name">Get a certification</field>
<field name="category">slides</field>
<field name="challenge_category">slides</field>
<field name="period">once</field>
<field name="visibility_mode">personal</field>
<field name="report_message_frequency">never</field>
@@ -190,7 +190,7 @@
</record>
<record id="badge_data_karma_challenge" model="gamification.challenge">
<field name="name">Read 2000 XP</field>
<field name="category">slides</field>
<field name="challenge_category">slides</field>
<field name="period">once</field>
<field name="visibility_mode">personal</field>
<field name="report_message_frequency">never</field>
@@ -7,4 +7,4 @@ from odoo import models, fields
class Challenge(models.Model):
_inherit = 'gamification.challenge'
category = fields.Selection(selection_add=[('slides', 'Website / Slides')])
challenge_category = fields.Selection(selection_add=[('slides', 'Website / Slides')])
@@ -8,6 +8,7 @@ import werkzeug.exceptions
from odoo import _
from odoo import http
from odoo.http import request
from odoo.osv import expression
from odoo.addons.website_slides.controllers.main import WebsiteSlides
from collections import defaultdict
@@ -74,3 +75,39 @@ class WebsiteSlides(WebsiteSlides):
] for user in users
}
return users_certificates
# Badges & Ranks Page
# ---------------------------------------------------
def _prepare_ranks_badges_values(self, **kwargs):
""" Extract certification badges, to render them in ranks/badges page in another section.
Order them by number of granted users desc and show only badges linked to opened certifications."""
values = super(WebsiteSlides, self)._prepare_ranks_badges_values(**kwargs)
# 1. Getting all certification badges, sorted by granted user desc
domain = expression.AND([[('survey_id', '!=', False)], self._prepare_badges_domain(**kwargs)])
certification_badges = request.env['gamification.badge'].sudo().search(domain)
# keep only the badge with challenge category = slides (the rest will be displayed under 'normal badges' section
certification_badges = certification_badges.filtered(
lambda b: 'slides' in b.challenge_ids.mapped('challenge_category'))
if not certification_badges:
return values
# 2. sort by granted users (done here, and not in search directly, because non stored field)
certification_badges = certification_badges.sorted("granted_users_count", reverse=True)
# 3. Remove certification badge from badges and keep only certification badge linked to opened survey
badges = values['badges'] - certification_badges
certification_badges = certification_badges.filtered(lambda b: b.survey_id.state == 'open')
# 4. Getting all course url for each badge
certification_slides = request.env['slide.slide'].sudo().search([('survey_id', 'in', certification_badges.mapped('survey_id').ids)])
certification_badge_urls = {slide.survey_id.certification_badge_id.id: slide.channel_id.website_url for slide in certification_slides}
# 5. Applying changes
values.update({
'badges': badges,
'certification_badges': certification_badges,
'certification_badge_urls': certification_badge_urls
})
return values
@@ -57,8 +57,34 @@ class Slide(models.Model):
rec = super(Slide, self).create(values)
if rec.survey_id:
rec.slide_type = 'certification'
if 'survey_id' in values:
rec._ensure_challenge_category()
return rec
def write(self, values):
old_surveys = self.mapped('survey_id')
result = super(Slide, self).write(values)
if 'survey_id' in values:
self._ensure_challenge_category(old_surveys=old_surveys - self.mapped('survey_id'))
return result
def unlink(self):
old_surveys = self.mapped('survey_id')
result = super(Slide, self).unlink()
self._ensure_challenge_category(old_surveys=old_surveys, unlink=True)
return result
def _ensure_challenge_category(self, old_surveys=None, unlink=False):
""" If a slide is linked to a survey that gives a badge, the challenge category of this badge must be
set to 'slides' in order to appear under the certification badge list on ranks_badges page.
If the survey is unlinked from the slide, the challenge category must be reset to 'certification'"""
if old_surveys:
old_certification_challenges = old_surveys.mapped('certification_badge_id').challenge_ids
old_certification_challenges.write({'challenge_category': 'certification'})
if not unlink:
certification_challenges = self.mapped('survey_id').mapped('certification_badge_id').challenge_ids
certification_challenges.write({'challenge_category': 'slides'})
def _generate_certification_url(self):
""" get a map of certification url for certification slide from `self`. The url will come from the survey user input:
1/ existing and not done user_input for member of the course
@@ -14,3 +14,7 @@ class Survey(models.Model):
return True
return super(Survey, self)._check_answer_creation(user, partner, email, test_entry=test_entry, check_attempts=check_attempts, invite_token=invite_token)
def _prepare_challenge_category(self):
slide_survey = self.env['slide.slide'].search([('survey_id', '=', self.id)])
return 'slides' if slide_survey else 'certification'
@@ -16,7 +16,7 @@
<div class="row">
<div class="col-12 col-lg-6" t-foreach="certificates" t-as="certificate">
<div class="card mb-2">
<div class="card-body o_wprofile_slides_course_card_body p-0 d-flex">
<div class="card-body o_wprofile_slides_course_card_body p-0 d-flex" t-attf-onclick="location.href='/slides/#{slug(certificate.slide_id.channel_id)}';">
<div class="pl-5 pr-4 rounded-left" t-attf-style="background-image: url(#{website.image_url(certificate.slide_id, 'image_128')}); background-position: center"/>
<div class="p-2 w-100">
<h5 class="mt-0 mb-1" t-esc="certificate.survey_id.title"/>
@@ -62,4 +62,34 @@
</td>
</xpath>
</template>
<template id="badge_content" inherit_id="website_profile.badge_content">
<xpath expr="//div[@id='website_profile_badges']" position="after">
<t t-if="certification_badges">
<div class="row">
<div class="col-12">
<h1 class="mt-4 mt-lg-2">Certification Badges</h1>
<p class="lead">
You can gain badges by passing certifications. Here is a list of all available certification badges.
<br />Follow the links to reach new heights and skill up!
</p>
<div class="row col-12 align-items-center p-0" t-foreach="certification_badges" t-as="badge">
<div class="col-3">
<t t-call="website_profile.badge_header">
<t t-if="badge.id in certification_badge_urls" t-set="badge_url" t-value="certification_badge_urls[badge.id]"/>
</t>
</div>
<div class="col-6">
<span t-field="badge.description"/>
</div>
<div class="col-3 text-right">
<b t-esc="badge.granted_users_count"/>
<i class="text-muted"> awarded users</i>
</div>
</div>
</div>
</div>
</t>
</xpath>
</template>
</data></odoo>