[IMP] sale_(project): improve the UX for project app

Purpose of this commit to improve generic usage of project app.

So in this commit done the following changes:
 - switch the id and the priority fields from place for task list view
 - add a 'view sales order' button that should open the form view of the SO
   linked to the SOL set on the milestone for milestone list view
 - add a 'sales order' stat button that should open the form view of the SO
   linked to the SOL set on the milestone for milestone form view
 - add a 'done' option; represent it in purple in status field
 - if there is only 1 assignee, display its name on the card instead of
   1 assignee for project sharing kanban view
 - add an 'all tasks' menu on the right of the 'my tasks' one

task-2917086

closes odoo/odoo#97669

Related: odoo/upgrade#3893
Related: odoo/enterprise#30195
Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
This commit is contained in:
Rohitkumar (roku)
2022-11-25 17:55:56 +01:00
committed by Barad Mahendra
parent eebc3e0483
commit f7f3d9610b
11 changed files with 98 additions and 14 deletions
+6
View File
@@ -1332,5 +1332,11 @@ Send it ASAP, its urgent.</field>
<field name="progress" eval="35"/>
<field name="status">at_risk</field>
</record>
<record id="project_update_3" model="project.update" context="{'default_project_id': ref('project.project_project_3')}">
<field name="name">Status</field>
<field name="user_id" eval="ref('base.user_admin')"/>
<field name="progress" eval="100"/>
<field name="status">done</field>
</record>
</data>
</odoo>
+1
View File
@@ -409,6 +409,7 @@ class Project(models.Model):
('off_track', 'Off Track'),
('on_hold', 'On Hold'),
('to_define', 'Set Status'),
('done', 'Done'),
], default='to_define', compute='_compute_last_update_status', store=True, readonly=False, required=True)
last_update_color = fields.Integer(compute='_compute_last_update_color')
milestone_ids = fields.One2many('project.milestone', 'project_id', copy=True)
+3 -1
View File
@@ -14,6 +14,7 @@ STATUS_COLOR = {
'at_risk': 2, # orange
'off_track': 23, # red / danger
'on_hold': 4, # light blue
'done': 5, # purple
False: 0, # default grey -- for studio
# Only used in project.task
'to_define': 0,
@@ -46,7 +47,8 @@ class ProjectUpdate(models.Model):
('on_track', 'On Track'),
('at_risk', 'At Risk'),
('off_track', 'Off Track'),
('on_hold', 'On Hold')
('on_hold', 'On Hold'),
('done', 'Done'),
], required=True, tracking=True)
color = fields.Integer(compute='_compute_color')
progress = fields.Integer(tracking=True)
@@ -51,6 +51,10 @@
}
}
.o_kanban_counter_progress .bg-purple {
background-color: purple;
}
@include media-breakpoint-down(md) {
.o_view_nocontent {
top: 15%;
@@ -8,6 +8,7 @@ export const STATUS_COLORS = {
'at_risk': 2,
'off_track': 1,
'on_hold': 4,
'done': 5,
};
export const STATUS_COLOR_PREFIX = 'o_status_bubble mx-0 o_color_bubble_';
@@ -212,7 +212,7 @@
<xpath expr="//div[hasclass('o_portal_sidebar')]" position="inside">
<t t-set="o_portal_fullwidth_alert" groups="project.group_project_user">
<t t-call="portal.portal_back_in_edit_mode">
<t t-set="backend_url" t-value="'/web#model=project.task&amp;id=%s&amp;action=%s&amp;view_type=form' % (task.id, task.env.ref('project.action_view_all_task').id)"/>
<t t-set="backend_url" t-value="'/web#model=project.task&amp;id=%s&amp;action=%s&amp;view_type=form' % (task.id, task.env.ref('project.action_view_my_task').id)"/>
</t>
</t>
@@ -100,9 +100,8 @@
<div class="oe_kanban_bottom_right" t-if="!selection_mode">
<span t-if="record.portal_user_names.raw_value.length > 0" class="pe-2" t-att-title="record.portal_user_names.raw_value">
<t t-set="user_count" t-value="record.portal_user_names.raw_value.split(',').length"/>
<t t-out="user_count"/>
<t t-if="user_count > 1"> assignees</t>
<t t-else=""> assignee</t>
<t t-if="user_count > 1"><t t-out="user_count"/> assignees</t>
<t t-else="" t-out="record.portal_user_names.raw_value"/>
</span>
<field name="kanban_state" widget="state_selection"/>
</div>
+57 -7
View File
@@ -826,7 +826,7 @@
<field name="last_update_color"/>
<field name="last_update_status"/>
<field name="tag_ids"/>
<progressbar field="last_update_status" colors='{"on_track": "success", "at_risk": "warning", "off_track": "danger", "on_hold": "info"}'/>
<progressbar field="last_update_status" colors='{"on_track": "success", "at_risk": "warning", "off_track": "danger", "on_hold": "info", "done": "purple"}'/>
<field name="sequence" widget="handle"/>
<templates>
<t t-name="kanban-box">
@@ -1508,8 +1508,8 @@
<field name="is_closed" invisible="1" />
<field name="sequence" invisible="1" readonly="1"/>
<field name="allow_milestones" invisible="1"/>
<field name="priority" widget="priority" optional="show" nolabel="1"/>
<field name="id" optional="hide"/>
<field name="priority" widget="priority" optional="show" nolabel="1"/>
<field name="child_text" invisible="1"/>
<field name="allow_subtasks" invisible="1"/>
<field name="name" widget="name_with_subtask_count"/>
@@ -1650,7 +1650,19 @@
</field>
</record>
<record id="action_view_all_task" model="ir.actions.act_window">
<record id="view_task_kanban_inherit_all_task" model="ir.ui.view">
<field name="name">project.task.kanban.inherit.all.task</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="view_task_kanban"/>
<field name="mode">primary</field>
<field name="arch" type="xml">
<xpath expr="//kanban" position="attributes">
<attribute name="default_group_by">project_id</attribute>
</xpath>
</field>
</record>
<record id="action_view_my_task" model="ir.actions.act_window">
<field name="name">My Tasks</field>
<field name="res_model">project.task</field>
<field name="view_mode">kanban,tree,form,calendar,pivot,graph,activity</field>
@@ -1690,16 +1702,51 @@
<field name="act_window_id" ref="action_view_task"/>
</record>
<record id="open_view_all_task_list_kanban" model="ir.actions.act_window.view">
<record id="open_view_my_task_list_kanban" model="ir.actions.act_window.view">
<field name="sequence" eval="10"/>
<field name="view_mode">kanban</field>
<field name="view_id" ref="view_task_kanban_inherit_my_task"/>
<field name="act_window_id" ref="action_view_all_task"/>
<field name="act_window_id" ref="action_view_my_task"/>
</record>
<record id="open_view_all_task_list_tree" model="ir.actions.act_window.view">
<record id="open_view_my_task_list_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="20"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="open_view_my_tasks_list_view"/>
<field name="act_window_id" ref="action_view_my_task"/>
</record>
<record id="open_view_my_task_list_calendar" model="ir.actions.act_window.view">
<field name="sequence" eval="40"/>
<field name="view_mode">calendar</field>
<field name="act_window_id" ref="action_view_my_task"/>
<field name="view_id" ref="view_task_all_calendar"/>
</record>
<record id="action_view_all_task" model="ir.actions.act_window">
<field name="name">All Tasks</field>
<field name="res_model">project.task</field>
<field name="view_mode">tree,kanban,form,calendar,pivot,graph,activity</field>
<field name="context">{'search_default_open_tasks': 1, 'default_user_ids': [(4, uid)]}</field>
<field name="search_view_id" ref="view_task_search_form_extended"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No tasks found. Let's create one!
</p>
<p>
Organize your tasks by dispatching them across the pipeline.<br/>
Collaborate efficiently by chatting in real-time or via email.
</p>
</field>
</record>
<record id="open_view_all_task_list_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="10"/>
<field name="view_mode">tree</field>
<field name="act_window_id" ref="action_view_all_task"/>
</record>
<record id="open_view_all_task_list_kanban" model="ir.actions.act_window.view">
<field name="sequence" eval="20"/>
<field name="view_mode">kanban</field>
<field name="view_id" ref="view_task_kanban_inherit_all_task"/>
<field name="act_window_id" ref="action_view_all_task"/>
</record>
<record id="open_view_all_task_list_calendar" model="ir.actions.act_window.view">
@@ -1710,7 +1757,10 @@
</record>
<menuitem name="My Tasks" id="menu_project_management" parent="menu_main_pm"
action="action_view_all_task" sequence="2" groups="base.group_no_one,group_project_user"/>
action="action_view_my_task" sequence="2" groups="group_project_user"/>
<menuitem name="All Tasks" id="menu_project_management_all_tasks" parent="menu_main_pm"
action="action_view_all_task" sequence="2" groups="group_project_user"/>
<record id="project_task_action_from_partner" model="ir.actions.act_window">
<field name="name">Tasks</field>
@@ -67,7 +67,7 @@ class ProjectTaskTypeDelete(models.TransientModel):
elif self.env.context.get('stage_view'):
action = self.env["ir.actions.actions"]._for_xml_id("project.open_task_type_form")
else:
action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_all_task")
action = self.env["ir.actions.actions"]._for_xml_id("project.action_view_my_task")
context = action.get('context', '{}')
context = context.replace('uid', str(self.env.uid))
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
from odoo import api, fields, models, _
class ProjectMilestone(models.Model):
_name = 'project.milestone'
@@ -19,3 +19,13 @@ class ProjectMilestone(models.Model):
@api.model
def _get_fields_to_export(self):
return super()._get_fields_to_export() + ['allow_billable', 'quantity_percentage', 'sale_line_name']
def action_view_sale_order(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': _('Sales Order'),
'res_model': 'sale.order',
'res_id': self.sale_line_id.order_id.id,
'view_mode': 'form',
}
@@ -123,6 +123,13 @@
<field name="quantity_percentage" groups="sales_team.group_sale_salesman" widget="percentage" readonly="0"/>
</group>
</xpath>
<xpath expr="//button[@name='%(project.action_view_task_from_milestone)d']" position="before">
<button name="action_view_sale_order" type="object" class="oe_stat_button" icon="fa-dollar" attrs="{'invisible': [('sale_line_id', '=', False)]}">
<div class="o_stat_info">
<span class="o_stat_text">Sales Order</span>
</div>
</button>
</xpath>
</field>
</record>
@@ -140,6 +147,10 @@
<field name="quantity_percentage" optional="hide" widget="percentage" readonly="1" groups="!sales_team.group_sale_salesman"/>
<field name="quantity_percentage" optional="hide" widget="percentage" groups="sales_team.group_sale_salesman"/>
</xpath>
<xpath expr="//button[@name='action_view_tasks']" position="after">
<button name="action_view_sale_order" type="object" string="View Sales Order"
class="btn btn-link float-end" attrs="{'invisible': [('sale_line_id', '=', False)]}"/>
</xpath>
</field>
</record>