diff options
| author | Martin Trigaux <mat@openerp.com> | 2013-12-24 16:51:38 +0100 |
|---|---|---|
| committer | Martin Trigaux <mat@openerp.com> | 2013-12-24 16:51:38 +0100 |
| commit | aba5888a34b9743a4ae0efc6df858df59b6e9b95 (patch) | |
| tree | 360abd2f0de843fbd3da94d0741d5b0d5a810cb3 /addons/gamification/static | |
| parent | 68795d8a10c90cbd8321ac86f8da642f6472551d (diff) | |
| parent | a42bf998e24eab8fcf498a831c2f49638cd4e4d2 (diff) | |
[MERGE] [ADD] gamification
New modules gamification, hr_gamification, gamification_sale_crm, portal_gamification.
Merry Christmas OpenERP
bzr revid: mat@openerp.com-20131224155138-3bbp8m3gyrfsb3ni
Diffstat (limited to 'addons/gamification/static')
| -rw-r--r-- | addons/gamification/static/description/icon.png | bin | 0 -> 22343 bytes | |||
| -rw-r--r-- | addons/gamification/static/src/css/Makefile | 3 | ||||
| -rw-r--r-- | addons/gamification/static/src/css/gamification.css | 190 | ||||
| -rw-r--r-- | addons/gamification/static/src/css/gamification.sass | 181 | ||||
| -rw-r--r-- | addons/gamification/static/src/js/gamification.js | 148 | ||||
| -rw-r--r-- | addons/gamification/static/src/xml/gamification.xml | 114 |
6 files changed, 636 insertions, 0 deletions
diff --git a/addons/gamification/static/description/icon.png b/addons/gamification/static/description/icon.png Binary files differnew file mode 100644 index 00000000000..52a75f726ba --- /dev/null +++ b/addons/gamification/static/description/icon.png diff --git a/addons/gamification/static/src/css/Makefile b/addons/gamification/static/src/css/Makefile new file mode 100644 index 00000000000..3a6a70cf59b --- /dev/null +++ b/addons/gamification/static/src/css/Makefile @@ -0,0 +1,3 @@ +gamification.css: gamification.sass + sass --trace -t expanded gamification.sass gamification.css + diff --git a/addons/gamification/static/src/css/gamification.css b/addons/gamification/static/src/css/gamification.css new file mode 100644 index 00000000000..4ac3a0340fa --- /dev/null +++ b/addons/gamification/static/src/css/gamification.css @@ -0,0 +1,190 @@ +@charset "UTF-8"; +.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_goal { + width: 230px; + min-height: 200px; +} +.openerp .oe_kanban_view .oe_kanban_card.oe_kanban_badge { + width: 250px; + min-height: 150px; +} +.openerp .oe_kanban_badge_avatars { + margin-top: 8px; +} +.openerp .oe_kanban_badge_avatars img { + width: 30px; + height: 30px; + padding-left: 0; + margin-top: 3px; + border-radius: 2px; + -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +} +.openerp .oe_kanban_goal .oe_goal_state_block { + width: 200px; + height: 130px; + margin: auto; + margin-bottom: -20px; +} +.openerp .oe_kanban_goal .oe_goal_state_block .oe_goal_state { + font-size: 2.5em; + font-weight: bold; + padding-top: 30px; +} +.openerp .oe_kanban_goal .oe_goal_state_block .oe_goal_state.oe_e { + font-size: 7em; +} +.openerp .oe_kanban_goal .oe_goal_state_block, .openerp .oe_kanban_goal p { + text-align: center; +} +.openerp .oe_kanban_content .oe_goal_gauge:first-child { + margin: auto; +} +.openerp .oe_kanban_content .oe_goal_gauge svg { + margin-top: -20px; +} +.openerp .oe_no_overflow { + overflow: hidden; +} +.openerp .oe_red { + color: red; +} +.openerp .oe_green { + color: green; +} +.openerp .oe_orange { + color: orange; +} +.openerp .oe_form td .oe_no_padding { + margin-left: -6px; +} +.openerp .oe_mail_wall .oe_mail_wall_aside { + margin-top: 15px; + position: relative; + display: inline-block; + vertical-align: top; + width: 280px; + border-radius: 2px; +} +.openerp .oe_mail_wall .oe_mail_wall_aside .oe_gamification_challenge_list { + background-color: #ededf6; +} +.openerp .oe_mail_wall .oe_mail_wall_aside .oe_gamification_suggestion { + background-color: #d3def1; +} +.openerp .oe_mail_wall .oe_mail_wall_aside .oe_gamification_suggestion ul { + padding-left: 15px; +} +.openerp .oe_mail_wall .oe_mail_wall_aside h4, .openerp .oe_mail_wall .oe_mail_wall_aside .oe_goals_list .oe_thead { + text-align: center; + padding-bottom: 15px; +} +.openerp .oe_mail_wall .oe_mail_wall_aside > div { + border-bottom: solid 5px white; + border-radius: 2px; +} +.openerp .oe_mail_wall .oe_goal { + border-bottom: solid 3px white; + padding: 5px 10px; +} +.openerp .oe_mail_wall .oe_goal .oe_update_challenge.oe_e, .openerp .oe_mail_wall .oe_goal .oe_goal_action.oe_e { + visibility: hidden; + font-size: 25px; + float: right; + position: relative; +} +.openerp .oe_mail_wall .oe_goal div:hover > .oe_update_challenge, .openerp .oe_mail_wall .oe_goal div:hover > .oe_goal_action, .openerp .oe_mail_wall .oe_goal th:hover > .oe_goal_action { + visibility: visible; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list { + padding-left: 0; + margin-top: 5px; + margin-bottom: 10px; + width: 100%; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_no_progress div { + display: inline-block; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_no_progress::before { + content: "•"; + padding-right: 4px; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_no_progress.oe_goal_reached::before { + content: "✓"; + padding-right: 0; + margin-left: -2px; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_no_progress.oe_goal_reached .oe_cell { + text-decoration: line-through; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_cell.oe_goal_current { + font-size: 150%; + font-weight: bold; + min-width: 50px; + padding: 0 5px; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_goal_outer_box { + display: inline-block; + position: relative; + z-index: 0; + vertical-align: middle; + width: 100%; + border: solid 1px rgba(0, 0, 0, 0.03); + border-radius: 2px; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_goal_outer_box.oe_no_progress { + border: none; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_goal_progress_background { + background-color: white; + position: absolute; + height: 100%; + width: 100%; + z-index: -2; + top: 0; + left: 0; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_goal_progress { + background-color: #d4e9de; + position: absolute; + height: 100%; + width: 0; + z-index: -1; + top: 0; + left: 0; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_thead { + font-weight: normal; + padding: 5px; + text-align: center; +} +.openerp .oe_mail_wall .oe_goal .oe_goals_list .oe_cell { + padding: 3px 0; +} +.openerp .oe_mail_wall .oe_table.oe_goals_list .col0 { + font-size: 200%; + font-weight: bold; + width: 25px; + text-align: center; +} +.openerp .oe_mail_wall .oe_table.oe_goals_list .col1 { + padding: 0 5px; +} +.openerp .oe_mail_wall .oe_table.oe_goals_list .col2 { + width: auto; +} +.openerp .oe_mail_wall .oe_user_avatar { + width: 24px; + padding-right: 5px; +} +.openerp .oe_mail_wall .oe_mail { + display: inline-block; +} +.openerp .oe_mail_wall .oe_table { + display: table; +} +.openerp .oe_mail_wall .oe_row { + display: table-row; +} +.openerp .oe_mail_wall .oe_cell { + display: table-cell; + vertical-align: middle; +} diff --git a/addons/gamification/static/src/css/gamification.sass b/addons/gamification/static/src/css/gamification.sass new file mode 100644 index 00000000000..3bb6b570e66 --- /dev/null +++ b/addons/gamification/static/src/css/gamification.sass @@ -0,0 +1,181 @@ +@charset "utf-8" + +.openerp + // Kanban views + .oe_kanban_view + .oe_kanban_card.oe_kanban_goal + width: 230px + min-height: 200px + .oe_kanban_card.oe_kanban_badge + width: 250px + min-height: 150px + .oe_kanban_badge_avatars + margin-top: 8px + img + width: 30px + height: 30px + padding-left: 0 + margin-top: 3px + border-radius: 2px + -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) + + .oe_kanban_goal + .oe_goal_state_block + width: 200px + height: 130px + margin: auto + margin-bottom: -20px + .oe_goal_state + font-size: 2.5em + font-weight: bold + padding-top: 30px + .oe_goal_state.oe_e + font-size: 7em + .oe_goal_state_block,p + text-align: center + + .oe_kanban_content + .oe_goal_gauge:first-child + margin: auto /* avoid margin-right: 16px */ + .oe_goal_gauge + svg + margin-top: -20px + .oe_no_overflow + overflow: hidden + + + .oe_red + color: red + .oe_green + color: green + .oe_orange + color: orange + + + // compensate padding from .openerp .oe_form td.oe_form_group_cell + .oe_form_group_cell + .oe_form td .oe_no_padding + margin-left: -6px + + + .oe_mail_wall + .oe_mail_wall_aside + margin-top: 15px + position: relative + display: inline-block + vertical-align: top + width: 280px + border-radius: 2px + + .oe_gamification_challenge_list + background-color: #EDEDF6 + .oe_gamification_suggestion + background-color: rgb(211, 222, 241) + ul + padding-left: 15px + + h4, .oe_goals_list .oe_thead + text-align: center + padding-bottom: 15px + + .oe_mail_wall_aside > div + border-bottom: solid 5px white + border-radius: 2px + + .oe_goal + border-bottom: solid 3px white + padding: 5px 10px + .oe_update_challenge.oe_e, .oe_goal_action.oe_e + visibility: hidden + font-size: 25px + float: right + position: relative + div:hover > .oe_update_challenge, div:hover > .oe_goal_action, th:hover > .oe_goal_action + visibility: visible + + .oe_goals_list + padding-left: 0 + margin-top: 5px + margin-bottom: 10px + width: 100% + + .oe_no_progress + div + display: inline-block + .oe_no_progress::before + content: "•" + padding-right: 4px + .oe_no_progress.oe_goal_reached::before + content: "✓" + padding-right: 0 + margin-left: -2px + .oe_no_progress.oe_goal_reached + .oe_cell + text-decoration: line-through + + .oe_cell.oe_goal_current + font-size: 150% + font-weight: bold + min-width: 50px + padding: 0 5px + + .oe_goal_outer_box + display: inline-block + position: relative + z-index: 0 + vertical-align: middle + width: 100% + border: solid 1px rgba(0,0,0,0.03) + border-radius: 2px + .oe_goal_outer_box.oe_no_progress + border: none + + .oe_goal_progress_background + background-color: white + position: absolute + height: 100% + width: 100% + z-index: -2 + top: 0 + left: 0 + + .oe_goal_progress + background-color: rgb(212, 233, 222) + position: absolute + height: 100% + width: 0 + z-index: -1 + top: 0 + left: 0 + + .oe_thead + font-weight: normal + padding: 5px + text-align: center + .oe_cell + padding: 3px 0 + + .oe_table.oe_goals_list + .col0 + font-size: 200% + font-weight: bold + width: 25px + text-align: center + .col1 + padding: 0 5px + .col2 + width: auto + + .oe_user_avatar + width: 24px + padding-right: 5px + + .oe_mail + display: inline-block + + .oe_table + display: table + .oe_row + display: table-row + .oe_cell + display: table-cell + vertical-align: middle diff --git a/addons/gamification/static/src/js/gamification.js b/addons/gamification/static/src/js/gamification.js new file mode 100644 index 00000000000..2a8db5f369d --- /dev/null +++ b/addons/gamification/static/src/js/gamification.js @@ -0,0 +1,148 @@ +openerp.gamification = function(instance) { + var QWeb = instance.web.qweb; + + instance.gamification.Sidebar = instance.web.Widget.extend({ + template: 'gamification.UserWallSidebar', + init: function (parent, action) { + var self = this; + this._super(parent, action); + this.deferred = $.Deferred(); + this.goals_info = {}; + this.challenge_suggestions = {}; + $(document).off('keydown.klistener'); + }, + events: { + // update a challenge and related goals + 'click a.oe_update_challenge': function(event) { + var self = this; + var challenge_id = parseInt(event.currentTarget.id, 10); + var goals_updated = new instance.web.Model('gamification.challenge').call('quick_update', [challenge_id]); + $.when(goals_updated).done(function() { + self.get_goal_todo_info(); + }); + }, + // action to modify a goal + 'click a.oe_goal_action': function(event) { + var self = this; + var goal_id = parseInt(event.currentTarget.id, 10); + var goal_action = new instance.web.Model('gamification.goal').call('get_action', [goal_id]).then(function(res) { + goal_action['action'] = res; + }); + $.when(goal_action).done(function() { + var action = self.do_action(goal_action.action); + $.when(action).done(function () { + new instance.web.Model('gamification.goal').call('update', [[goal_id]]).then(function(res) { + self.get_goal_todo_info(); + }); + }); + }); + }, + // get more info about a challenge request + 'click a.oe_challenge_reply': function(event) { + var self = this; + var challenge_id = parseInt(event.currentTarget.id, 10); + var challenge_action = new instance.web.Model('gamification.challenge').call('reply_challenge_wizard', [challenge_id]).then(function(res) { + challenge_action['action'] = res; + }); + $.when(challenge_action).done(function() { + self.do_action(challenge_action.action).done(function () { + self.get_goal_todo_info(); + }); + }); + }, + 'click .oe_goal h4': function(event) { + var self = this; + this.kkeys = []; + $(document).on('keydown.klistener', function(event) { + if ("37,38,39,40,65,66".indexOf(event.keyCode) < 0) { + $(document).off('keydown.klistener'); + } else { + self.kkeys.push(event.keyCode); + if (self.kkeys.toString().indexOf("38,38,40,40,37,39,37,39,66,65") >= 0) { + new instance.web.Model('gamification.badge').call('check_progress', []); + $(document).off('keydown.klistener'); + } + } + }); + } + }, + start: function() { + var self = this; + this._super.apply(this, arguments); + self.get_goal_todo_info(); + self.get_challenge_suggestions(); + }, + get_goal_todo_info: function() { + var self = this; + var challenges = new instance.web.Model('res.users').call('get_serialised_gamification_summary', []).then(function(result) { + if (result.length === 0) { + self.$el.find(".oe_gamification_challenge_list").hide(); + } else { + self.$el.find(".oe_gamification_challenge_list").empty(); + _.each(result, function(item){ + var $item = $(QWeb.render("gamification.ChallengeSummary", {challenge: item})); + self.render_money_fields($item); + self.render_user_avatars($item); + self.$el.find('.oe_gamification_challenge_list').append($item); + }); + } + }); + }, + get_challenge_suggestions: function() { + var self = this; + var challenge_suggestions = new instance.web.Model('res.users').call('get_challenge_suggestions', []).then(function(result) { + if (result.length === 0) { + self.$el.find(".oe_gamification_suggestion").hide(); + } else { + var $item = $(QWeb.render("gamification.ChallengeSuggestion", {challenges: result})); + self.$el.find('.oe_gamification_suggestion').append($item); + } + }); + }, + render_money_fields: function(item) { + var self = this; + self.dfm = new instance.web.form.DefaultFieldManager(self); + // Generate a FieldMonetary for each .oe_goal_field_monetary + item.find(".oe_goal_field_monetary").each(function() { + var currency_id = parseInt( $(this).attr('data-id'), 10); + money_field = new instance.web.form.FieldMonetary(self.dfm, { + attrs: { + modifiers: '{"readonly": true}' + } + }); + money_field.set('currency', currency_id); + money_field.get_currency_info(); + money_field.set('value', parseInt($(this).text(), 10)); + money_field.replace($(this)); + }); + }, + render_user_avatars: function(item) { + var self = this; + item.find(".oe_user_avatar").each(function() { + var user_id = parseInt( $(this).attr('data-id'), 10); + var url = instance.session.url('/web/binary/image', {model: 'res.users', field: 'image_small', id: user_id}); + $(this).attr("src", url); + }); + } + }); + + instance.mail.Widget.include({ + start: function() { + this._super(); + var sidebar = new instance.gamification.Sidebar(this); + sidebar.appendTo($('.oe_mail_wall_aside')); + }, + }); + + instance.web_kanban.KanbanRecord.include({ + // open related goals when clicking on challenge kanban view + on_card_clicked: function() { + if (this.view.dataset.model === 'gamification.challenge') { + this.$('.oe_kanban_project_list a').first().click(); + } else { + this._super.apply(this, arguments); + } + }, + }); + +}; diff --git a/addons/gamification/static/src/xml/gamification.xml b/addons/gamification/static/src/xml/gamification.xml new file mode 100644 index 00000000000..6316ca886f0 --- /dev/null +++ b/addons/gamification/static/src/xml/gamification.xml @@ -0,0 +1,114 @@ +<templates> + <t t-name="gamification.UserWallSidebar" class="oe_gamification_user_wall_sidebar"> + <div> + <div class="oe_gamification_suggestion"></div> + <div class="oe_gamification_challenge_list"></div> + </div> + </t> + <t t-name="gamification.ChallengeSummary"> + <div class="oe_goal"> + <div> + <a class="oe_update_challenge oe_e" rol="button" t-attf-id="{challenge.id}">e</a> + <h4><t t-esc="challenge.name" /></h4> + </div> + + <t t-if="challenge.visibility_mode == 'personal'"> + <div class="oe_table oe_goals_list"> + <div t-foreach="challenge.lines" t-as="line" t-attf-class="oe_row oe_goal_outer_box #{line.state == 'reached' ? 'oe_goal_reached' : ''} #{line.display_mode != 'progress' ? 'oe_no_progress' : ''}"> + <t t-if="line.display_mode == 'progress'"> + <div class="oe_goal_progress_background"></div> + <div class="oe_goal_progress" t-attf-style="#{line.display_mode == 'progress' ? 'width: '+line.completeness+'%;' : 'width:0;'}"></div> + <div class="oe_cell oe_goal_current"><t t-esc="line.current" /></div> + </t> + <div class="oe_cell"> + <t t-if="line.computation_mode != 'manually' and !line.action"> + <span t-att-title="line.description"><t t-esc="line.name" /></span> + </t> + <t t-if="line.action or line.computation_mode == 'manually'"> + <span t-att-title="line.description"><a class="oe_goal_action" t-att-id="line.id"><t t-esc="line.name" /></a></span> + </t> + <t t-if="line.display_mode == 'progress'"><br/> + <div class="oe_grey"> + <t t-if="line.definition_condition == 'higher'"> + Target: + </t> + <t t-if="line.definition_condition == 'lower'"> + Target: <= + </t> + <span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="line.target"/></span> + <t t-if="line.suffix"><t t-esc="line.suffix"/></t> + </div> + </t> + </div> + </div> + </div> + </t> + + <t t-if="challenge.visibility_mode == 'ranking'"> + <div t-foreach="challenge.lines" t-as="line" class="oe_goals_list oe_table"> + <div class="oe_row"> + <div class="oe_cell oe_thead" colspan="3" t-attf-title="#{line.description ? line.description : ''}"> + <strong><t t-esc="line.name"/></strong> + <br/> + <div class="oe_grey"> + <t t-if="line.definition_condition == 'higher'"> + Target: + </t> + <t t-if="line.definition_condition == 'lower'"> + Target: <= + </t> + <span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="line.target" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t> + </div> + </div> + </div> + <div t-foreach="line.goals" t-as="goal" t-attf-class="#{goal.id == line.own_goal_id ? 'oe_bold' : ''}"> + <div t-attf-class="oe_row oe_goal_outer_box #{goal.state == 'reached' ? 'oe_goal_reached' : ''} #{line.display_mode != 'progress' ? 'oe_no_progress' : ''}"> + <t t-if="line.display_mode == 'progress'"> + <div class="oe_goal_progress_background"></div> + <div class="oe_goal_progress" t-attf-style="#{line.display_mode == 'progress' ? 'width: '+goal.completeness+'%;' : 'width:0;'}"></div> + </t> + + <div class="oe_cell col0"><t t-esc="goal.rank" /></div> + <div class="oe_cell col1"><img class="oe_user_avatar" t-attf-alt="#{goal.name}" t-attf-data-id="#{goal.user_id}"/></div> + <div class="oe_cell col2"> + <t t-if="line.display_mode == 'progress'"> + <!-- progress, action on current value --> + <t t-esc="goal.name"/><br/> + <t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.action)"> + <span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="goal.current" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t> + </t> + <t t-if="goal.id == line.own_goal_id and (line.action or line.computation_mode == 'manually')"> + <a class="oe_goal_action" t-att-id="line.own_goal_id"> + <span t-attf-class="#{line.monetary ? 'oe_goal_field_monetary' : ''}" t-attf-data-id="#{line.monetary ? challenge.currency : ''}"><t t-esc="goal.current" /></span><t t-if="line.suffix"> <t t-esc="line.suffix"/></t> + </a> + </t> + </t> + <t t-if="line.display_mode != 'progress'"> + <!-- not progress, action on user name --> + <t t-if="goal.id != line.own_goal_id or (line.computation_mode != 'manually' and !line.action)"> + <t t-esc="goal.name"/> + </t> + <t t-if="goal.id == line.own_goal_id and (line.action or line.computation_mode == 'manually')"> + <a class="oe_goal_action" t-att-id="line.own_goal_id"><t t-esc="goal.name"/></a> + </t> + </t> + </div> + </div> + </div> + </div> + </t> + </div> + </t> + + <t t-name="gamification.ChallengeSuggestion"> + <div class="oe_goal"> + <h4>Invited Challenges</h4> + <ul t-foreach="challenges" t-as="challenge" class="oe_goals_list"> + <li> + <strong><a class="oe_challenge_reply" t-attf-title="#{challenge.description.value ? challenge.description.value : ''}" t-attf-id="{challenge.id}" title="more details..."><t t-esc="challenge.name"/></a></strong> + </li> + </ul> + </div> + </t> + +</templates> |
