diff options
| -rw-r--r-- | addons/project/project.py | 4 | ||||
| -rw-r--r-- | addons/project/project_view.xml | 15 | ||||
| -rw-r--r-- | addons/web/static/src/js/views/form_widgets.js | 79 | ||||
| -rw-r--r-- | addons/web/static/src/xml/base.xml | 29 | ||||
| -rw-r--r-- | addons/web_kanban/static/src/js/kanban_widgets.js | 62 | ||||
| -rw-r--r-- | addons/web_kanban/static/src/xml/web_kanban.xml | 17 |
6 files changed, 111 insertions, 95 deletions
diff --git a/addons/project/project.py b/addons/project/project.py index e61251e465a..c55a718a3a3 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -453,6 +453,9 @@ class task(osv.osv): 'attachment_ids': fields.one2many('ir.attachment', 'res_id', domain=lambda self: [('res_model', '=', self._name)], auto_join=True, string='Attachments'), # In the domain of displayed_image_id, we couln't use attachment_ids because a one2many is represented as a list of commands so we used res_model & res_id 'displayed_image_id': fields.many2one('ir.attachment', domain="[('res_model', '=', 'project.task'), ('res_id', '=', id), ('mimetype', 'ilike', 'image')]", string='Displayed Image'), + 'legend_blocked': fields.related("stage_id", "legend_blocked", type="char", string='Kanban Blocked Explanation'), + 'legend_done': fields.related("stage_id", "legend_done", type="char", string='Kanban Valid Explanation'), + 'legend_normal': fields.related("stage_id", "legend_normal", type="char", string='Kanban Ongoing Explanation'), } _defaults = { 'stage_id': _get_default_stage_id, @@ -637,7 +640,6 @@ class task(osv.osv): # user_id change: update date_assign if vals.get('user_id'): vals['date_assign'] = fields.datetime.now() - # context: no_log, because subtype already handle this create_context = dict(context, mail_create_nolog=True) task_id = super(task, self).create(cr, uid, vals, context=create_context) diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index a99da613812..46aa452adfd 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -254,11 +254,7 @@ options='{"terminology": "archive"}'/> </button> </div> - <field name="kanban_state" widget="kanban_state_selection" - options='{ - "states_legend_field": "stage_id", - "states_legend": {"normal": "legend_normal", "blocked": "legend_blocked", "done": "legend_done"} - }'/> + <field name="kanban_state" widget="kanban_state_selection"/> <div class="oe_title"> <h1 class="o_row"> <field name="priority" widget="priority"/> @@ -274,6 +270,9 @@ <field name="planned_hours" widget="float_time" groups="project.group_time_work_estimation_tasks" on_change="onchange_planned(planned_hours)"/> + <field name="legend_blocked" invisible="1"/> + <field name="legend_normal" invisible="1"/> + <field name="legend_done" invisible="1"/> </group> <group> <field name="date_deadline"/> @@ -329,6 +328,9 @@ <field name="attachment_ids"/> <field name="displayed_image_id"/> <field name="active"/> + <field name="legend_blocked"/> + <field name="legend_normal"/> + <field name="legend_done"/> <templates> <t t-name="kanban-box"> <div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click"> @@ -365,8 +367,7 @@ <div class="oe_kanban_bottom_right"> <img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar pull-right"/> <div class="pull-left" groups="base.group_user"> - <field name="kanban_state" widget="kanban_state_selection" - options='{"states_legend": {"normal": "legend_normal", "blocked": "legend_blocked", "done": "legend_done"}}'/> + <field name="kanban_state" widget="kanban_state_selection"/> </div> </div> </div> diff --git a/addons/web/static/src/js/views/form_widgets.js b/addons/web/static/src/js/views/form_widgets.js index 30a4700e766..074a36e76f7 100644 --- a/addons/web/static/src/js/views/form_widgets.js +++ b/addons/web/static/src/js/views/form_widgets.js @@ -165,6 +165,7 @@ var FieldChar = common.AbstractField.extend(common.ReinitializeFieldMixin, { }); var KanbanSelection = FieldChar.extend({ + template: "FormSelection", init: function (field_manager, node) { this._super(field_manager, node); }, @@ -180,54 +181,58 @@ var KanbanSelection = FieldChar.extend({ prepare_dropdown_selection: function() { var self = this; var _data = []; - var fetch_stage; - var selection = this.field.selection || []; - var stage_id = _.isArray(this.view.datarecord.stage_id) ? this.view.datarecord.stage_id[0] : this.view.datarecord.stage_id; - var legend_field = this.options && this.options.states_legend_field || false; - var fields_to_read = _.map( - this.options && this.options.states_legend || {}, - function (value, key, list) { return value; }); - if (legend_field && fields_to_read && stage_id) { - fetch_stage = new data.DataSet( - this, - self.view.fields[legend_field].field.relation).read_ids([stage_id], - fields_to_read); - } - else { fetch_stage = $.Deferred().resolve(false); } - return $.when(fetch_stage).then(function (stage_data) { - _.map(selection, function(res) { - var value = { - 'name': res[0], - 'tooltip': res[1], - 'state_name': res[1], - }; - if (stage_data && stage_data[0][self.options.states_legend[res[0]]]) { - value['state_name'] = stage_data[0][self.options.states_legend[res[0]]]; - value['tooltip'] = stage_data[0][self.options.states_legend[res[0]]]; - } - if (res[0] == 'normal') { value['state_class'] = 'oe_kanban_status'; } - else if (res[0] == 'done') { value['state_class'] = 'oe_kanban_status oe_kanban_status_green'; } - else { value['state_class'] = 'oe_kanban_status oe_kanban_status_red'; } - _data.push(value); - }); - return _data; + var current_stage_id = self.view.datarecord.stage_id[0]; + var stage_data = { + id: current_stage_id, + legend_normal: self.view.datarecord.legend_normal, + legend_blocked : self.view.datarecord.legend_blocked, + legend_done: self.view.datarecord.legend_done, + }; + _.map(self.field.selection || [], function(selection_item) { + var value = { + 'name': selection_item[0], + 'tooltip': selection_item[1], + }; + if (selection_item[0] === 'normal') { + value.state_name = stage_data.legend_normal ? stage_data.legend_normal : selection_item[1]; + } else if (selection_item[0] === 'done') { + value.state_class = 'oe_kanban_status_green'; + value.state_name = stage_data.legend_done ? stage_data.legend_done : selection_item[1]; + } else { + value.state_class = 'oe_kanban_status_red'; + value.state_name = stage_data.legend_blocked ? stage_data.legend_blocked : selection_item[1]; + } + _data.push(value); }); + return _data; }, render_value: function() { + this._super(); + this.states = this.prepare_dropdown_selection(); var self = this; - var dd_fetched = this.prepare_dropdown_selection(); - return $.when(dd_fetched).then(function (states) { - self.states = states; - self.$el.addClass('oe_right oe_inline'); - self.$el.html(QWeb.render("KanbanSelection", {'widget': self})); - self.$el.find('li').on('click', self.set_kanban_selection.bind(self)); + // Adapt "FormSelection" + var current_state = _.find(this.states, function(state) { + return state.name === self.get('value'); }); + this.$('.oe_kanban_status') + .removeClass('oe_kanban_status_red oe_kanban_status_green') + .addClass(current_state.state_class); + + // Render "FormSelection.Items" and move it into "FormSelection" + var $items = $(QWeb.render('FormSelection.items', { + states: _.without(this.states, current_state) + })); + var $dropdown = this.$el.find('.dropdown-menu'); + $dropdown.children().remove(); // remove old items + $items.appendTo($dropdown); + this.$el.find('a').on('click', this.set_kanban_selection.bind(this)); }, /* setting the value: in view mode, perform an asynchronous call and reload the form view; in edit mode, use set_value to save the new value that will be written when saving the record. */ set_kanban_selection: function (ev) { var self = this; + ev.preventDefault(); var li = $(ev.target).closest('li'); if (li.length) { var value = String(li.data('value')); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index be17df5ba48..435352efc16 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -679,28 +679,21 @@ </t> </span> </t> -<t t-name="KanbanSelection"> - <div class="btn-group kanban_state"> - <t t-foreach="widget.states" t-as="rec"> - <a t-if="widget.get('value') === rec.name"> - <a class="dropdown-toggle" data-toggle="dropdown"> - <span t-att-class="rec.state_class" t-if="widget.get('value') === rec.name" t-att-title="rec.tooltip"/> - <span class="sr-only">Toggle Dropdown</span> - </a> - </a> - </t> +<t t-name="FormSelection"> + <div class="btn-group o_kanban_selection"> + <a href="#" data-toggle="dropdown"><span class="oe_kanban_status"/></a> <ul class="dropdown-menu state" role="menu"> - <t t-foreach="widget.states" t-as="rec"> - <t t-if="widget.get('value') !== rec.name"> - <li t-att-data-value="rec.name" ><a href="#"> - <span t-att-class="rec.state_class" t-att-title="rec.tooltip"/> - <t t-raw="rec.state_name" /></a> - </li> - </t> - </t> </ul> </div> </t> +<t t-name="FormSelection.items"> + <li t-foreach="states" t-as="rec" t-att-data-value="rec.name"> + <a href="#"> + <span t-att-class="'oe_kanban_status ' + (rec.state_class && rec.state_class || '')"/> + <t t-raw="rec.state_name"/> + </a> + </li> +</t> <div t-name="Priority" class="o_priority"> <a t-if="!widget.readonly" t-foreach="widget.values.slice(1)" t-as="v" href="#" t-att-data-value="v[0]" t-att-title="v[1]" class="o_priority_star fa"/> <span t-if="widget.readonly" t-foreach="widget.values.slice(1)" t-as="v" t-att-data-value="v[0]" t-att-title="v[1]" class="o_priority_star fa"/> diff --git a/addons/web_kanban/static/src/js/kanban_widgets.js b/addons/web_kanban/static/src/js/kanban_widgets.js index 4db931e9a64..9fe64c3c3ea 100644 --- a/addons/web_kanban/static/src/js/kanban_widgets.js +++ b/addons/web_kanban/static/src/js/kanban_widgets.js @@ -9,7 +9,6 @@ var pyeval = require('web.pyeval'); var Registry = require('web.Registry'); var session = require('web.session'); var Widget = require('web.Widget'); - var QWeb = core.qweb; /** * Interface to be implemented by kanban fields. @@ -103,53 +102,52 @@ var KanbanSelection = AbstractField.extend({ this.name = $node.attr('name'); this.parent = parent; }, + // Instead of making several rpc calls for each kanban card, take the values from the related fields on the tasks prepare_dropdown_selection: function() { var self = this; - var data = []; - _.map(this.field.selection || [], function(res) { + var _data = []; + var stage_id = self.parent.values.stage_id.value[0]; + var stage_data = { + id: stage_id, + legend_normal: self.parent.values.legend_normal.value, + legend_blocked : self.parent.values.legend_blocked.value, + legend_done: self.parent.values.legend_done.value, + }; + _.map(self.field.selection || [], function(res) { var value = { 'name': res[0], 'tooltip': res[1], - 'state_name': res[1], }; - var leg_opt = self.options && self.options.states_legend || null; - if (leg_opt) { - var key = leg_opt[value.name]; - var legend = self.parent.group_info && self.parent.group_info[key]; - if (legend) { - value.state_name = legend; - value.tooltip = legend; - } + if (res[0] === 'normal') { + value.state_name = stage_data.legend_normal ? stage_data.legend_normal : res[1]; + } else if (res[0] === 'done') { + value.state_class = 'oe_kanban_status_green'; + value.state_name = stage_data.legend_done ? stage_data.legend_done : res[1]; + } else { + value.state_class = 'oe_kanban_status_red'; + value.state_name = stage_data.legend_blocked ? stage_data.legend_blocked : res[1]; } - if (res[0] == 'normal') { value.state_class = 'oe_kanban_status'; } - else if (res[0] == 'done') { value.state_class = 'oe_kanban_status oe_kanban_status_green'; } - else { value.state_class = 'oe_kanban_status oe_kanban_status_red'; } - data.push(value); + _data.push(value); }); - return data; + return _data; }, renderElement: function() { var self = this; - this.states = this.prepare_dropdown_selection(); - var state; - for(var i = 0 ; i < this.states.length ; i++) { - if(this.states[i].name === this.get('value')) { - state = this.states[i]; - } - } + self.states = this.prepare_dropdown_selection(); - this.$el = $(QWeb.render("KanbanSelection", {'widget': this})); - this.$('a').first().find('span').removeClass().addClass(state.state_class); - this.$('ul li').show().filter(function() { - return ($(this).data('value') === state.name); - }).hide(); + var current_state = _.find(this.states, function(state) { + return state.name === self.get('value'); + }); - this.$('a').click(function (ev) { + self.$el = $(QWeb.render("KanbanSelection", { + current_state_class: current_state.state_class, + states: _.without(this.states, current_state) + })); + self.$('a').click(function (ev) { ev.preventDefault(); }); - - this.$('li').click(this.set_kanban_selection.bind(this)); + self.$('a').click(self.set_kanban_selection.bind(self)); }, set_kanban_selection: function(e) { e.preventDefault(); diff --git a/addons/web_kanban/static/src/xml/web_kanban.xml b/addons/web_kanban/static/src/xml/web_kanban.xml index e07298e95b5..07663caa85b 100644 --- a/addons/web_kanban/static/src/xml/web_kanban.xml +++ b/addons/web_kanban/static/src/xml/web_kanban.xml @@ -84,4 +84,21 @@ <img t-att-src="'/web/image/' + widget.field.raw_value[0] + '?unique=1'"/> </div> </t> + +<t t-name="KanbanSelection"> + <div class="btn-group o_kanban_selection"> + <a href="#" data-toggle="dropdown"> + <span t-att-class="'oe_kanban_status ' + (current_state_class && current_state_class || '')"/> + </a> + <ul class="dropdown-menu state" role="menu"> + <li t-foreach="states" t-as="rec" t-att-data-value="rec.name"> + <a href="#"> + <span t-att-class="'oe_kanban_status ' + (rec.state_class && rec.state_class || '')"/> + <t t-raw="rec.state_name"/> + </a> + </li> + </ul> + </div> +</t> + </template> |
