Abdullah Al-Habbal
Abdullah Al-Habbal

Reputation: 33

Add a new option to an existing selection field

The following options are what I have available currently:

I want to add another option called 'Solved', with blue colored circle.

I did inherit the "project.task" model and added selection_add method and overridden the kanban_state selection field with the 'Solved' text:

# Python File
from odoo import models, fields, api, _

class ProjectTask(models.Model):
    _inherit = 'project.task'

    kanban_state = fields.Selection(selection_add=[('solved', 'Solved')],
                                    ondelete={'solved': 'cascade'})

However it shows as 'Blocked' value with red circle:

I'm sure that I'm missing something here.

Upvotes: 3

Views: 837

Answers (1)

Kenly
Kenly

Reputation: 26748

The selection state is designed to use red color for all new states.

To use another color, you will need to override the selection state widget or create a custom selection widget

Example:

1. Create a new selection state widget to set a custom color in solved state

/** @odoo-module **/

import basicFields from "web.basic_fields";
import fieldRegistry from 'web.field_registry';
import { qweb } from 'web.core';


var CustomStateSelectionWidget = basicFields.StateSelectionWidget.extend({
    _prepareDropdownValues: function () {
        var self = this;
        var _data = [];
        var current_stage_id = self.recordData.stage_id && self.recordData.stage_id[0];
        var stage_data = {
            id: current_stage_id,
            legend_normal: this.recordData.legend_normal || undefined,
            legend_blocked : this.recordData.legend_blocked || undefined,
            legend_done: this.recordData.legend_done || undefined,
            legend_solved: this.recordData.legend_solved || undefined,
        };
        _.map(this.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 = 'o_status_green';
                value.state_name = stage_data.legend_done ? stage_data.legend_done : selection_item[1];
            } else if (selection_item[0] === 'solved') {
                value.state_class = 'o_status_blue';
                value.state_name = stage_data.legend_solved ? stage_data.legend_solved : selection_item[1];
            } else {
                value.state_class = 'o_status_red';
                value.state_name = stage_data.legend_blocked ? stage_data.legend_blocked : selection_item[1];
            }
            _data.push(value);
        });
        return _data;
    },

    _render: function () {
        var states = this._prepareDropdownValues();
        // Adapt "FormSelection"
        // Like priority, default on the first possible value if no value is given.
        var currentState = _.findWhere(states, {name: this.value}) || states[0];
        this.$('.o_status')
            .removeClass('o_status_red o_status_green o_status_blue')
            .addClass(currentState.state_class)
            .prop('special_click', true)
            .parent().attr('title', currentState.state_name)
            .attr('aria-label', this.string + ": " + currentState.state_name);

        // Render "FormSelection.Items" and move it into "FormSelection"
        var $items = $(qweb.render('FormSelection.items', {
            states: _.without(states, currentState)
        }));
        var $dropdown = this.$('.dropdown-menu');
        $dropdown.children().remove(); // remove old items
        $items.appendTo($dropdown);

        // Disable edition if the field is readonly
        var isReadonly = this.record.evalModifiers(this.attrs.modifiers).readonly;
        this.$('a[data-toggle=dropdown]').toggleClass('disabled', isReadonly || false);
    },

});

fieldRegistry.add('custom_state_selection', CustomStateSelectionWidget);

return CustomStateSelectionWidget;

2. Update models to use the legend field for solved state

from odoo import models, fields, api, _

from odoo.addons import project
project.models.project.PROJECT_TASK_READABLE_FIELDS.add('legend_solved')


class ProjectTaskType(models.Model):
    _inherit = 'project.task.type'

    legend_solved = fields.Char(
        'Blue Kanban Label', default=lambda s: _('Solved'), translate=True, required=True,
        help='Override the default value displayed for the solved state for kanban selection when the task or issue is in that stage.')


class ProjectTask(models.Model):
    _inherit = 'project.task'

    kanban_state = fields.Selection(selection_add=[('solved', 'Solved')],
                                    ondelete={'solved': 'cascade'})

    legend_solved = fields.Char(related='stage_id.legend_solved', string='Kanban Valid Explanation', readonly=True,
                                related_sudo=False)

    @api.depends('stage_id', 'kanban_state')
    def _compute_kanban_state_label(self):
        for task in self:
            if task.kanban_state == 'normal':
                task.kanban_state_label = task.legend_normal
            elif task.kanban_state == 'blocked':
                task.kanban_state_label = task.legend_blocked
            elif task.kanban_state == 'solved':
                task.kanban_state_label = task.legend_solved
            else:
                task.kanban_state_label = task.legend_done

3. Alter the project kanban view to set the selection state widget

<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
    <record id="view_task_kanban_custom_state_selection" model="ir.ui.view">
        <field name="name">project.task.kanban.custom.state.selection</field>
        <field name="model">project.task</field>
        <field name="inherit_id" ref="project.view_task_kanban"/>
        <field name="arch" type="xml">
            <field name="kanban_state" position="attributes">
                <attribute name="widget">custom_state_selection</attribute>
            </field>
        </field>
    </record>
</odoo>

4. Create an scss file to declare the o_status_blue class used in the custom widget

.o_status {
    &.o_status_blue {
        @extend .bg-primary;
    }
}

To load the js and scss files add the file paths under assets/web.assets_backend and also add the view under data

'data': [
    'views/project_view.xml',
],
'assets': {
    'web.assets_backend': [
        'MODULE_NAME/static/src/js/StateSelectionWidget.js',
        'MODULE_NAME/static/src/css/StateSelectionWidget.scss',
    ],
},

Upvotes: 2

Related Questions