Browse Source
[ADD] base_kanban_stage: Stage model and abstract logic
[ADD] base_kanban_stage: Stage model and abstract logic
* Add Kanban-compatible stage model base.kanban.stage * Add views, menu items, actions, and access controls needed to manage base.kanban.stage records * Add abstract model base.kanban.abstract that other models can inherit from to gain Kanban stage functionality * Add base Kanban view base_kanban_abstract_view_kanban, which can be customized as needed for use with models that inherit from base.kanban.abstract * Add model base.kanban.abstract.tester, which is needed for base.kanban.abstract unit tests12.0
Ted Salmon
8 years ago
committed by
ahenriquez
13 changed files with 606 additions and 0 deletions
-
108base_kanban_stage/README.rst
-
5base_kanban_stage/__init__.py
-
23base_kanban_stage/__openerp__.py
-
6base_kanban_stage/models/__init__.py
-
112base_kanban_stage/models/base_kanban_abstract.py
-
84base_kanban_stage/models/base_kanban_stage.py
-
3base_kanban_stage/security/ir.model.access.csv
-
BINbase_kanban_stage/static/description/icon.png
-
6base_kanban_stage/tests/__init__.py
-
73base_kanban_stage/tests/test_base_kanban_abstract.py
-
50base_kanban_stage/tests/test_base_kanban_stage.py
-
64base_kanban_stage/views/base_kanban_abstract.xml
-
72base_kanban_stage/views/base_kanban_stage.xml
@ -0,0 +1,108 @@ |
|||
.. image:: https://img.shields.io/badge/licence-lgpl--3-blue.svg |
|||
:target: http://www.gnu.org/licenses/LGPL-3.0-standalone.html |
|||
:alt: License: LGPL-3 |
|||
|
|||
====================== |
|||
Kanban - Stage Support |
|||
====================== |
|||
|
|||
This module provides a stage model compatible with Kanban views and the |
|||
standard views needed to manage these stages. It also provides the |
|||
``base.kanban.abstract`` model, which can be inherited to add support for |
|||
Kanban views with stages to any other model. Lastly, it includes a base Kanban |
|||
view that can be extended as needed. |
|||
|
|||
Installation |
|||
============ |
|||
|
|||
To install this module, simply follow the standard install process. |
|||
|
|||
Configuration |
|||
============= |
|||
|
|||
No configuration is needed or possible. |
|||
|
|||
Usage |
|||
===== |
|||
|
|||
* Inherit from ``base.kanban.abstract`` to add Kanban stage functionality to |
|||
the child model: |
|||
|
|||
.. code-block:: python |
|||
|
|||
class MyModel(models.Model): |
|||
_name = 'my.model' |
|||
_inherit = 'base.kanban.abstract' |
|||
|
|||
* Extend the provided base Kanban view (``base_kanban_abstract_view_kanban``) |
|||
as needed by the child model. The base view has four ``name`` attributes |
|||
intended to provide convenient XPath access to different parts of the Kanban |
|||
card. They are ``card_dropdown_menu``, ``card_header``, ``card_body``, and |
|||
``card_footer``: |
|||
|
|||
.. code-block:: xml |
|||
|
|||
<record id="my_model_view_kanban" model="ir.ui.view"> |
|||
<field name="name">My Model - Kanban View</field> |
|||
<field name="model">my.model</field> |
|||
<field name="inherit_id" ref="base_kanban_stage.base_kanban_abstract_view_kanban"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//div[@name='card_header']"> |
|||
<!-- Add header content here --> |
|||
</xpath> |
|||
<xpath expr="//div[@name='card_body']"> |
|||
<!-- Add body content here --> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
|
|||
* To manage stages, go to Settings > Technical > Kanban > Stages. |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/162/9.0 |
|||
|
|||
Known Issues / Roadmap |
|||
====================== |
|||
|
|||
* The grouping logic used by ``base.kanban.abstract`` currently does not |
|||
support additional domains and alternate sort orders |
|||
|
|||
Bug Tracker |
|||
=========== |
|||
|
|||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_. |
|||
In case of trouble, please check there if your issue has already been reported. |
|||
If you spotted it first, help us smash it by providing detailed and welcomed |
|||
feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Images |
|||
------ |
|||
|
|||
* Odoo Community Association: |
|||
`Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Dave Lasley <dave@laslabs.com> |
|||
* Oleg Bulkin <obulkin@laslabs.com> |
|||
* Daniel Reis |
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
OCA, or the Odoo Community Association, is a nonprofit organization whose |
|||
mission is to support the collaborative development of Odoo features and |
|||
promote its widespread use. |
|||
|
|||
To contribute to this module, please visit http://odoo-community.org. |
@ -0,0 +1,5 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import models |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
{ |
|||
'name': 'Kanban - Stage Support', |
|||
'summary': 'Provides stage model and abstract logic for inheritance', |
|||
'version': '9.0.1.0.0', |
|||
'author': "LasLabs, Odoo Community Association (OCA)", |
|||
'category': 'base', |
|||
'depends': [ |
|||
'web_kanban', |
|||
], |
|||
'website': 'https://laslabs.com', |
|||
'license': 'LGPL-3', |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'views/base_kanban_abstract.xml', |
|||
'views/base_kanban_stage.xml', |
|||
], |
|||
'installable': True, |
|||
'application': False, |
|||
} |
@ -0,0 +1,6 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import base_kanban_abstract |
|||
from . import base_kanban_stage |
@ -0,0 +1,112 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from openerp import api, fields, models |
|||
|
|||
|
|||
class BaseKanbanAbstract(models.AbstractModel): |
|||
'''Inherit from this class to add support for Kanban stages to your model. |
|||
All public properties are preceded with kanban_ in order to isolate from |
|||
child models, with the exception of stage_id, which is a required field in |
|||
the Kanban widget and must be defined as such.''' |
|||
|
|||
_name = 'base.kanban.abstract' |
|||
_order = 'kanban_priority desc, kanban_sequence' |
|||
_group_by_full = { |
|||
'stage_id': lambda s, *a, **k: s._read_group_stage_ids(*a, **k), |
|||
} |
|||
|
|||
kanban_sequence = fields.Integer( |
|||
default=10, |
|||
index=True, |
|||
help='Order of record in relation to other records in the same Kanban' |
|||
' stage and with the same priority', |
|||
) |
|||
kanban_priority = fields.Selection( |
|||
selection=[('0', 'Normal'), ('5', 'Medium'), ('10', 'High')], |
|||
index=True, |
|||
default='0', |
|||
help='The priority of the record (shown as stars in Kanban views)', |
|||
) |
|||
stage_id = fields.Many2one( |
|||
string='Kanban Stage', |
|||
comodel_name='base.kanban.stage', |
|||
track_visibility='onchange', |
|||
index=True, |
|||
copy=False, |
|||
help='The Kanban stage that this record is currently in', |
|||
default=lambda s: s._default_stage_id(), |
|||
domain=lambda s: [('res_model.model', '=', s._name)], |
|||
) |
|||
kanban_user_id = fields.Many2one( |
|||
string='Assigned To', |
|||
comodel_name='res.users', |
|||
index=True, |
|||
track_visibility='onchange', |
|||
help='User that the record is currently assigned to', |
|||
) |
|||
kanban_color = fields.Integer( |
|||
string='Color Index', |
|||
help='Color index to be used for the record\'s Kanban card', |
|||
) |
|||
kanban_legend_priority = fields.Text( |
|||
string='Priority Explanation', |
|||
related='stage_id.legend_priority', |
|||
help='Explanation text to help users understand how the priority/star' |
|||
' mechanism applies to this record (depends on current stage)', |
|||
) |
|||
kanban_legend_blocked = fields.Text( |
|||
string='Special Handling Explanation', |
|||
related='stage_id.legend_blocked', |
|||
help='Explanation text to help users understand how the special' |
|||
' handling status applies to this record (depends on current' |
|||
' stage)', |
|||
) |
|||
kanban_legend_done = fields.Text( |
|||
string='Ready Explanation', |
|||
related='stage_id.legend_done', |
|||
help='Explanation text to help users understand how the ready' |
|||
' status applies to this record (depends on current stage)', |
|||
) |
|||
kanban_legend_normal = fields.Text( |
|||
string='Normal Handling Explanation', |
|||
related='stage_id.legend_normal', |
|||
help='Explanation text to help users understand how the normal' |
|||
' handling status applies to this record (depends on current' |
|||
' stage)', |
|||
) |
|||
kanban_status = fields.Selection( |
|||
selection=[ |
|||
('normal', 'Normal Handling'), |
|||
('done', 'Ready'), |
|||
('blocked', 'Special Handling'), |
|||
], |
|||
string='Kanban Status', |
|||
default='normal', |
|||
track_visibility='onchange', |
|||
required=True, |
|||
copy=False, |
|||
help='A record can have one of several Kanban statuses, which are used' |
|||
' to indicate whether there are any special situations affecting' |
|||
' it. The exact meaning of each status is allowed to vary based' |
|||
' on the stage the record is in but they are roughly as follow:\n' |
|||
'* Normal Handling: Default status, no special situations\n' |
|||
'* Ready: Ready to transition to the next stage\n' |
|||
'* Special Handling: Blocked in some way (e.g. must be handled by' |
|||
' a specific user)\n' |
|||
) |
|||
|
|||
@api.model |
|||
def _default_stage_id(self): |
|||
return self.env['base.kanban.stage'] |
|||
|
|||
@api.multi |
|||
def _read_group_stage_ids( |
|||
self, domain=None, read_group_order=None, access_rights_uid=None |
|||
): |
|||
stage_model = self.env['base.kanban.stage'].sudo(access_rights_uid) |
|||
stages = stage_model.search([('res_model.model', '=', self._name)]) |
|||
names = [(r.id, r.display_name) for r in stages] |
|||
fold = {r.id: r.fold for r in stages} |
|||
return names, fold |
@ -0,0 +1,84 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from openerp import api, fields, models |
|||
|
|||
|
|||
class BaseKanbanStage(models.Model): |
|||
_name = 'base.kanban.stage' |
|||
_description = 'Kanban Stage' |
|||
_order = 'res_model, sequence' |
|||
|
|||
name = fields.Char( |
|||
string='Stage Name', |
|||
translate=True, |
|||
required=True, |
|||
help='Displayed as the header for this stage in Kanban views', |
|||
) |
|||
description = fields.Text( |
|||
translate=True, |
|||
help='Short description of the stage\'s meaning/purpose', |
|||
) |
|||
sequence = fields.Integer( |
|||
default=1, |
|||
required=True, |
|||
index=True, |
|||
help='Order of stage in relation to other stages available for the' |
|||
' same model', |
|||
) |
|||
legend_priority = fields.Text( |
|||
string='Priority Explanation', |
|||
translate=True, |
|||
default='Mark a card as medium or high priority (one or two stars) to' |
|||
' indicate that it should be escalated ahead of others with' |
|||
' lower priority/star counts.', |
|||
help='Explanation text to help users understand how the priority/star' |
|||
' mechanism applies to this stage', |
|||
) |
|||
legend_blocked = fields.Text( |
|||
string='Special Handling Explanation', |
|||
translate=True, |
|||
default='Give a card the special handling status to indicate that it' |
|||
' requires handling by a special user or subset of users.', |
|||
help='Explanation text to help users understand how the special' |
|||
' handling status applies to this stage', |
|||
) |
|||
legend_done = fields.Text( |
|||
string='Ready Explanation', |
|||
translate=True, |
|||
default='Mark a card as ready when it has been fully processed.', |
|||
help='Explanation text to help users understand how the ready status' |
|||
' applies to this stage', |
|||
) |
|||
legend_normal = fields.Text( |
|||
string='Normal Handling Explanation', |
|||
translate=True, |
|||
default='This is the default status and indicates that a card can be' |
|||
' processed by any user working this queue.', |
|||
help='Explanation text to help users understand how the normal' |
|||
' handling status applies to this stage', |
|||
) |
|||
fold = fields.Boolean( |
|||
string='Collapse?', |
|||
help='Determines whether this stage will be collapsed down in Kanban' |
|||
' views', |
|||
) |
|||
res_model = fields.Many2one( |
|||
string='Associated Model', |
|||
comodel_name='ir.model', |
|||
required=True, |
|||
index=True, |
|||
help='The model that this Kanban stage will be used for', |
|||
domain=[('transient', '=', False)], |
|||
default=lambda s: s._default_res_model(), |
|||
) |
|||
|
|||
@api.model |
|||
def _default_res_model(self): |
|||
'''Useful when creating stages from a Kanban view for another model''' |
|||
action_id = self.env.context.get('params', {}).get('action') |
|||
action = self.env['ir.actions.act_window'].browse(action_id) |
|||
default_model = action.res_model |
|||
if default_model != self._name: |
|||
return self.env['ir.model'].search([('model', '=', default_model)]) |
@ -0,0 +1,3 @@ |
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink |
|||
access_user,Kanban Stage - User Access,model_base_kanban_stage,base.group_user,1,0,0,0 |
|||
access_manager,Kanban Stage - Manager Access,model_base_kanban_stage,base.group_erp_manager,1,1,1,1 |
After Width: 128 | Height: 128 | Size: 9.2 KiB |
@ -0,0 +1,6 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from . import test_base_kanban_abstract |
|||
from . import test_base_kanban_stage |
@ -0,0 +1,73 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from openerp import models |
|||
from openerp.tests.common import TransactionCase |
|||
|
|||
|
|||
class BaseKanbanAbstractTester(models.Model): |
|||
_name = 'base.kanban.abstract.tester' |
|||
_inherit = 'base.kanban.abstract' |
|||
|
|||
|
|||
class TestBaseKanbanAbstract(TransactionCase): |
|||
def setUp(self): |
|||
super(TestBaseKanbanAbstract, self).setUp() |
|||
|
|||
BaseKanbanAbstractTester._build_model(self.registry, self.cr) |
|||
self.test_model = self.env[BaseKanbanAbstractTester._name] |
|||
|
|||
test_model_type = self.env['ir.model'].create({ |
|||
'model': BaseKanbanAbstractTester._name, |
|||
'name': 'Kanban Abstract - Test Model', |
|||
'state': 'base', |
|||
}) |
|||
|
|||
test_stage_1 = self.env['base.kanban.stage'].create({ |
|||
'name': 'Test Stage 1', |
|||
'res_model': test_model_type.id, |
|||
}) |
|||
test_stage_2 = self.env['base.kanban.stage'].create({ |
|||
'name': 'Test Stage 2', |
|||
'res_model': test_model_type.id, |
|||
'fold': True, |
|||
}) |
|||
|
|||
self.id_1 = test_stage_1.id |
|||
self.id_2 = test_stage_2.id |
|||
|
|||
def test_read_group_stage_ids_base_case(self): |
|||
'''It should return a structure with the proper content''' |
|||
self.assertEqual( |
|||
self.test_model._read_group_stage_ids(), |
|||
( |
|||
[(self.id_1, 'Test Stage 1'), (self.id_2, 'Test Stage 2')], |
|||
{self.id_1: False, self.id_2: True}, |
|||
) |
|||
) |
|||
|
|||
def test_read_group_stage_ids_correct_associated_model(self): |
|||
'''It should only return info for stages with right associated model''' |
|||
stage_model = self.env['ir.model'].search([ |
|||
('model', '=', 'base.kanban.stage'), |
|||
]) |
|||
self.env['base.kanban.stage'].create({ |
|||
'name': 'Test Stage 3', |
|||
'res_model': stage_model.id, |
|||
}) |
|||
|
|||
self.assertEqual( |
|||
self.test_model._read_group_stage_ids(), |
|||
( |
|||
[(self.id_1, 'Test Stage 1'), (self.id_2, 'Test Stage 2')], |
|||
{self.id_1: False, self.id_2: True}, |
|||
) |
|||
) |
|||
|
|||
def test_default_stage_id(self): |
|||
''' It should return an empty RecordSet ''' |
|||
self.assertEqual( |
|||
self.env['base.kanban.abstract']._default_stage_id(), |
|||
self.env['base.kanban.stage'] |
|||
) |
@ -0,0 +1,50 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Copyright 2016 LasLabs Inc. |
|||
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
|
|||
from openerp.tests.common import TransactionCase |
|||
|
|||
|
|||
class TestBaseKanbanStage(TransactionCase): |
|||
def test_default_res_model_no_params(self): |
|||
'''It should return empty ir.model Recordset if no params in context''' |
|||
test_stage = self.env['base.kanban.stage'].with_context({}) |
|||
res_model = test_stage._default_res_model() |
|||
|
|||
self.assertFalse(res_model) |
|||
self.assertEqual(res_model._name, 'ir.model') |
|||
|
|||
def test_default_res_model_no_action(self): |
|||
'''It should return empty ir.model Recordset if no action in params''' |
|||
test_stage = self.env['base.kanban.stage'].with_context(params={}) |
|||
res_model = test_stage._default_res_model() |
|||
|
|||
self.assertFalse(res_model) |
|||
self.assertEqual(res_model._name, 'ir.model') |
|||
|
|||
def test_default_res_model_info_in_context(self): |
|||
'''It should return correct ir.model record if info in context''' |
|||
test_action = self.env['ir.actions.act_window'].create({ |
|||
'name': 'Test Action', |
|||
'res_model': 'res.users', |
|||
}) |
|||
test_stage = self.env['base.kanban.stage'].with_context( |
|||
params={'action': test_action.id}, |
|||
) |
|||
|
|||
self.assertEqual( |
|||
test_stage._default_res_model(), |
|||
self.env['ir.model'].search([('model', '=', 'res.users')]) |
|||
) |
|||
|
|||
def test_default_res_model_ignore_self(self): |
|||
'''It should not return ir.model record corresponding to stage model''' |
|||
test_action = self.env['ir.actions.act_window'].create({ |
|||
'name': 'Test Action', |
|||
'res_model': 'base.kanban.stage', |
|||
}) |
|||
test_stage = self.env['base.kanban.stage'].with_context( |
|||
params={'action': test_action.id}, |
|||
) |
|||
|
|||
self.assertFalse(test_stage._default_res_model()) |
@ -0,0 +1,64 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- |
|||
Copyright 2016 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
<record id="base_kanban_abstract_view_kanban" model="ir.ui.view"> |
|||
<field name="name">Kanban Abstract - Base Kanban View</field> |
|||
<field name="model">base.kanban.abstract</field> |
|||
<field name="arch" type="xml"> |
|||
<kanban default_group_by="stage_id" class="o_kanban_small_column"> |
|||
<field name="display_name"/> |
|||
<field name="kanban_color"/> |
|||
<field name="kanban_priority"/> |
|||
<field name="stage_id" options="{'group_by_tooltip': {'description': 'Stage Description:', 'legend_priority': 'Use of Stars:'}}"/> |
|||
<field name="kanban_sequence"/> |
|||
<field name="kanban_legend_blocked"/> |
|||
<field name="kanban_legend_normal"/> |
|||
<field name="kanban_legend_done"/> |
|||
<field name="kanban_user_id"/> |
|||
<templates> |
|||
<t t-name="kanban-box"> |
|||
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.kanban_color.raw_value)} o_kanban_record oe_kanban_global_click"> |
|||
<div class="o_dropdown_kanban dropdown" name="card_dropdown_menu"> |
|||
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#"> |
|||
<span class="fa fa-bars fa-lg"/> |
|||
</a> |
|||
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel"> |
|||
<li t-if="widget.editable"> |
|||
<a type="edit">Edit</a> |
|||
</li> |
|||
<li t-if="widget.deletable"> |
|||
<a type="delete">Delete</a> |
|||
</li> |
|||
<li> |
|||
<ul class="oe_kanban_colorpicker" data-field="kanban_color"/> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
<div class="o_kanban_title" name="card_header"> |
|||
<field name="kanban_status" widget="kanban_state_selection"/> |
|||
<field name="display_name"/> |
|||
</div> |
|||
<div class="oe_kanban_details" name="card_body"> |
|||
<!-- Child modules should add model-specific data here --> |
|||
</div> |
|||
<div class="o_kanban_footer" name="card_footer"> |
|||
<div class="oe_kanban_bottom_left"> |
|||
<field name="kanban_priority" widget="priority"/> |
|||
</div> |
|||
<div class="oe_kanban_bottom_right" t-if="record.kanban_user_id"> |
|||
<img t-att-src="kanban_image('res.users', 'image_small', record.kanban_user_id.raw_value)" |
|||
class="oe_kanban_avatar_smallbox pull-right"/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
</templates> |
|||
</kanban> |
|||
</field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,72 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- |
|||
Copyright 2016 LasLabs Inc. |
|||
License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). |
|||
--> |
|||
|
|||
<odoo> |
|||
<record id="base_kanban_stage_view_form" model="ir.ui.view"> |
|||
<field name="name">Kanban Stage - Form View</field> |
|||
<field name="model">base.kanban.stage</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Kanban Stage"> |
|||
<header/> |
|||
<sheet> |
|||
<group string="Core Info" name="core_info"> |
|||
<field name="name"/> |
|||
<field name="res_model"/> |
|||
<field name="sequence"/> |
|||
<field name="fold"/> |
|||
<field name="description"/> |
|||
</group> |
|||
<group string="Priority and Statuses" name="explanations"> |
|||
<field name="legend_priority"/> |
|||
<field name="legend_blocked"/> |
|||
<field name="legend_done"/> |
|||
<field name="legend_normal"/> |
|||
</group> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="base_kanban_stage_view_tree" model="ir.ui.view"> |
|||
<field name="name">Kanban Stages - Tree View</field> |
|||
<field name="model">base.kanban.stage</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Kanban Stages"> |
|||
<field name="name"/> |
|||
<field name="res_model"/> |
|||
<field name="sequence"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="base_kanban_stage_view_search" model="ir.ui.view"> |
|||
<field name="name">Kanban Stages - Search View</field> |
|||
<field name="model">base.kanban.stage</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="Kanban Stages"> |
|||
<field name="name"/> |
|||
<field name="res_model"/> |
|||
<field name="sequence"/> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.actions.act_window" id="base_kanban_stage_action"> |
|||
<field name="name">Kanban Stages</field> |
|||
<field name="res_model">base.kanban.stage</field> |
|||
<field name="type">ir.actions.act_window</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem id="base_kanban_stage_root_menu" name="Kanban" |
|||
parent="base.menu_custom" sequence="50"/> |
|||
|
|||
<menuitem id="base_kanban_stage_menu" name="Stages" |
|||
parent="base_kanban_stage_root_menu" |
|||
action="base_kanban_stage_action" /> |
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue