[IMP] web: hide in kanban tag's color (#20815)

New feature:

   - New Transparent tag visual (grey border & text, white bg),
   - By default, newly created kanban tags are transparent,
   - Tag's colorpicker has now a 'Hide in Kanban' checkbox,
     to select the transparent color.

Toggling off 'Hide in Kanban' sets the color of the tag as follow:

   - Previous color, if 'Hide in Kanban' was toggled on on the
     same formview session.
   - Color 1 (dark orange), otherwise.
This commit is contained in:
Alexandre Kühn
2017-11-20 10:47:43 +01:00
committed by GitHub
parent 7d2666d020
commit 23e6dd36d7
10 changed files with 144 additions and 41 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ class AccountAccountTag(models.Model):
name = fields.Char(required=True)
applicability = fields.Selection([('accounts', 'Accounts'), ('taxes', 'Taxes')], required=True, default='accounts')
color = fields.Integer('Color Index', default=10)
color = fields.Integer('Color Index')
active = fields.Boolean(default=True, help="Set active to false to hide the Account Tag without removing it.")
#----------------------------------------------------------
+1 -1
View File
@@ -8,7 +8,7 @@ class AccountAnalyticTag(models.Model):
_name = 'account.analytic.tag'
_description = 'Analytic Tags'
name = fields.Char(string='Analytic Tag', index=True, required=True)
color = fields.Integer('Color Index', default=10)
color = fields.Integer('Color Index')
active = fields.Boolean(default=True, help="Set active to false to hide the Analytic Tag without removing it.")
+1 -1
View File
@@ -1220,7 +1220,7 @@ class Tag(models.Model):
_description = "Category of lead"
name = fields.Char('Name', required=True, translate=True)
color = fields.Integer('Color Index', default=10)
color = fields.Integer('Color Index')
_sql_constraints = [
('name_uniq', 'unique (name)', "Tag name already exists !"),
+1 -1
View File
@@ -297,7 +297,7 @@ class FleetVehicleTag(models.Model):
_name = 'fleet.vehicle.tag'
name = fields.Char(required=True, translate=True)
color = fields.Integer('Color Index', default=10)
color = fields.Integer('Color Index')
_sql_constraints = [('name_uniq', 'unique (name)', "Tag name already exists !")]
+1 -1
View File
@@ -873,7 +873,7 @@ class ProjectTags(models.Model):
_description = "Tasks Tags"
name = fields.Char(required=True)
color = fields.Integer(string='Color Index', default=10)
color = fields.Integer(string='Color Index')
_sql_constraints = [
('name_uniq', 'unique (name)', "Tag name already exists!"),
@@ -1703,6 +1703,7 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
events: _.extend({}, FieldMany2ManyTags.prototype.events, {
'click .badge': '_onOpenColorPicker',
'mousedown .o_colorpicker a': '_onUpdateColor',
'mousedown .o_colorpicker .o_hide_in_kanban': '_onUpdateColor',
'focusout .o_colorpicker': '_onCloseColorPicker',
}),
@@ -1713,43 +1714,63 @@ var FormFieldMany2ManyTags = FieldMany2ManyTags.extend({
/**
* @private
*/
_onCloseColorPicker: function (){
_onCloseColorPicker: function () {
this.$color_picker.remove();
},
/**
* @private
* @param {MouseEvent} event
* @param {MouseEvent} ev
*/
_onOpenColorPicker: function (event) {
var tag_id = $(event.currentTarget).data('id');
var tag = _.findWhere(this.value.data, { res_id: tag_id });
_onOpenColorPicker: function (ev) {
var tagID = $(ev.currentTarget).data('id');
var tagColor = $(ev.currentTarget).data('color');
var tag = _.findWhere(this.value.data, { res_id: tagID });
if (tag && this.colorField in tag.data) { // if there is a color field on the related model
this.$color_picker = $(qweb.render('FieldMany2ManyTag.colorpicker', {
'widget': this,
'tag_id': tag_id,
'tag_id': tagID,
}));
$(event.currentTarget).append(this.$color_picker);
$(ev.currentTarget).append(this.$color_picker);
this.$color_picker.dropdown('toggle');
this.$color_picker.attr("tabindex", 1).focus();
if (!tagColor) {
this.$('.o_checkbox input').prop('checked', true);
}
}
},
/**
* Update color based on target of ev
* either by clicking on a color item or
* by toggling the 'Hide in Kanban' checkbox.
*
* @private
* @param {MouseEvent} event
* @param {MouseEvent} ev
*/
_onUpdateColor: function (event) {
event.preventDefault();
var self = this;
var color = $(event.currentTarget).data('color');
var id = $(event.currentTarget).data('id');
var tag = self.$("span.badge[data-id='" + id + "']");
var current_color = tag.data('color');
if (color === current_color) { return; }
_onUpdateColor: function (ev) {
ev.preventDefault();
var $target = $(ev.currentTarget);
var color = $target.data('color');
var id = $target.data('id');
var tag = this.$("span.badge[data-id='" + id + "']");
var currentColor = tag.data('color');
var changes = {};
if ($target.is('.o_hide_in_kanban')) {
var $checkbox = $('.o_hide_in_kanban .o_checkbox input');
$checkbox.prop('checked', !$checkbox.prop('checked')); // toggle checkbox
this.prevColors = this.prevColors ? this.prevColors : {};
if ($checkbox.is(':checked')) {
this.prevColors[id] = currentColor
} else {
color = this.prevColors[id] ? this.prevColors[id] : 1;
}
} else if ($target.is('[class^="o_tag_color"]')) { // $target.is('o_tag_color_')
if (color === currentColor) { return; }
}
changes[this.colorField] = color;
this.trigger_up('field_changed', {
dataPointID: _.findWhere(this.value.data, {res_id: id}).id,
changes: changes,
+59 -11
View File
@@ -91,16 +91,6 @@
.o-flex-flow(row, wrap);
.o-align-items(baseline);
.o-tag-color(@size: 0) when (@size < @odoo-nb-ui-color) {
.o_tag_color_@{size} {
&, &::after {
background-color: ~"@{odoo-color-@{size}}";
}
}
.o-tag-color(@size + 1);
}
.o-tag-color();
> .o_field_widget {
.o-flex(1, 0, 100px);
position: initial;
@@ -119,8 +109,45 @@
max-width: 200px;
}
// o-kanban-colorpicker without customizing
// '&:first-child > a::before' (transparent red-crossed colorpick)
.o-tag-colorpicker() {
@o-tag-colorpicker-padding-right: @odoo-dropdown-hpadding - 2 * @o-kanban-inner-hmargin;
max-width: 100%;
padding: 3px @o-tag-colorpicker-padding-right 3px @odoo-dropdown-hpadding;
> li {
display: inline-block;
margin: @o-kanban-inner-hmargin @o-kanban-inner-hmargin 0 0;
border: 1px solid white;
box-shadow: 0 0 0 1px @gray-lighter-dark;
> a {
display: block;
&::after {
content: "";
display: block;
width: 20px;
height: 15px;
}
}
&:last-of-type {
box-shadow: 0 0 0 0px white; // remove grey border on hide in kanban
color: @odoo-main-text-color;
}
}
}
> .tagcolor_dropdown_menu {
min-width: 150px; // down from 160px of .dropdown-menu
margin-right: 0px; // cancel right margin of .dropdown-menu
}
> .o_colorpicker > ul {
.o-kanban-colorpicker();
.o-tag-colorpicker();
white-space: normal;
}
@@ -128,6 +155,27 @@
cursor: pointer;
}
}
.o-tag-color(@size: 0) when (@size < @odoo-nb-ui-color) {
.o_tag_color_@{size} when (@size = 0) {
& {
background-color: white;
color: ~"@{odoo-color-@{size}}";
box-shadow: inset 0 0 0 2px ~"@{odoo-color-@{size}}";
}
&::after {
background-color: ~"@{odoo-color-@{size}}";
}
}
.o_tag_color_@{size} when (@size > 0) {
&, &::after {
background-color: ~"@{odoo-color-@{size}}";
}
}
.o-tag-color(@size + 1);
}
.o-tag-color();
}
// Stars
+14 -5
View File
@@ -792,14 +792,23 @@
</t>
</t>
<t t-name="FieldMany2ManyTag.colorpicker">
<div class="o_colorpicker dropdown-menu" role="menu">
<div class="o_colorpicker dropdown-menu tagcolor_dropdown_menu" role="menu">
<ul>
<li t-foreach="12" t-as="color">
<li t-foreach="11" t-as="color">
<a href="#"
t-att-data-id="tag_id"
t-att-data-color="color"
t-attf-class="o_tag_color_#{color}"
t-att-title="color === 0 ? 'Not shown in kanban' : ''"/>
t-att-data-color="color+1"
t-attf-class="o_tag_color_#{color+1}"/>
</li>
<li> <!-- checkbox for tag color 0 -->
<div class="o_hide_in_kanban"
t-att-data-id="tag_id"
t-att-data-color="0">
<div class="o_checkbox">
<input type="checkbox"/>
<span/>
</div> Hide in Kanban
</div>
</li>
</ul>
</div>
@@ -8322,7 +8322,7 @@ QUnit.module('relational_fields', {
});
QUnit.test('fieldmany2many tags with color: rendering and edition', function (assert) {
assert.expect(20);
assert.expect(28);
this.data.partner.records[0].timmy = [12, 14];
this.data.partner_type.records.push({id: 13, display_name: "red", color: 8});
@@ -8391,6 +8391,31 @@ QUnit.module('relational_fields', {
// save the record (should do the write RPC with the correct commands)
form.$buttons.find('.o_form_button_save').click();
// checkbox 'Hide in Kanban'
$input = form.$('.o_field_many2manytags span[data-id=13]'); // selects 'red' tag
$input.click(); // opens the colorpicker dropdown
assert.ok(form.$('.o_field_many2manytags span[data-id=13] .o_colorpicker .o_checkbox'), "should have a checkbox in the colorpicker dropdown menu");
$input.click();
var $checkBox = form.$('.o_field_many2manytags span[data-id=13] .o_colorpicker .o_checkbox input');
assert.notOk($checkBox.is(':checked'), "should have unticked checkbox in colorpicker dropdown menu");
$checkBox.mousedown();
$input = form.$('.o_field_many2manytags span[data-id=13]'); // refresh
assert.equal($input.data('color'), "0", "should become transparent when toggling on checkbox");
$input.click();
$checkBox = form.$('.o_field_many2manytags span[data-id=13] .o_colorpicker .o_checkbox input'); // refresh
assert.ok($checkBox.is(':checked'), "should have a ticked checkbox in colorpicker dropdown menu after mousedown");
$checkBox.mousedown();
$input = form.$('.o_field_many2manytags span[data-id=13]'); // refresh
assert.equal($input.data('color'), "8", "should revert to old color when toggling off checkbox");
$input.click();
$checkBox = form.$('.o_field_many2manytags span[data-id=13] .o_colorpicker .o_checkbox input'); // refresh
assert.notOk($checkBox.is(':checked'), "should have an unticked checkbox in colorpicker dropdown menu after 2nd click");
// TODO: it would be nice to test the behaviors of the autocomplete dropdown
// (like refining the research, creating new tags...), but ui-autocomplete
// makes it difficult to test
@@ -13,7 +13,7 @@ class TrackTag(models.Model):
name = fields.Char('Tag')
track_ids = fields.Many2many('event.track', string='Tracks')
color = fields.Integer(string='Color Index', default=10)
color = fields.Integer(string='Color Index')
_sql_constraints = [
('name_uniq', 'unique (name)', "Tag name already exists !"),