summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorYannick Tivisse <yti@odoo.com>2015-09-14 14:07:19 +0200
committerYannick Tivisse <yti@odoo.com>2015-09-22 11:33:58 +0200
commite5181b05f73364c424ab3e7cef186501b2dcb63a (patch)
tree5a3204d699927804a9bcf96357b64b3d30b833a2 /addons
parent8c8fee29ea3ee9737f4da19e7eed2f9937232517 (diff)
[FIX] web_kanban, web: KanbanSelection widget refactoring
- Change the widget behavior from asynchronous to asynchronous, by adding 3 related fields on the project.task model, which are the custom labels defined for the stage - Instead of making a rpc call, we are taking directly the labels on the parent for the kanban view, or on the view datarecord for the form view - There are now 2 templates for the kanban view or the form view - The development has been backported in the community version - The options attribute has been removed on the project_view.xml file for the kanban_state field
Diffstat (limited to 'addons')
-rw-r--r--addons/project/project.py4
-rw-r--r--addons/project/project_view.xml15
-rw-r--r--addons/web/static/src/js/views/form_widgets.js79
-rw-r--r--addons/web/static/src/xml/base.xml29
-rw-r--r--addons/web_kanban/static/src/js/kanban_widgets.js62
-rw-r--r--addons/web_kanban/static/src/xml/web_kanban.xml17
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 &amp;&amp; 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 &amp;&amp; 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 &amp;&amp; rec.state_class || '')"/>
+ <t t-raw="rec.state_name"/>
+ </a>
+ </li>
+ </ul>
+ </div>
+</t>
+
</template>