[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:
@@ -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 -->
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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'}"/>
|
||||
|
||||
@@ -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"><p>Test your vendor skills!</p></field>
|
||||
<field name="thank_you_message"><p></p></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">
|
||||
|
||||
@@ -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')])
|
||||
|
||||
@@ -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)],
|
||||
|
||||
@@ -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')" />
|
||||
|
||||
@@ -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')" />
|
||||
|
||||
@@ -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')])
|
||||
|
||||
@@ -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-->
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user