Amit Patel (OpenERP) has proposed merging
lp:~openerp-dev/openobject-addons/trunk-project-kanban into
lp:openobject-addons.
Requested reviews:
OpenERP Core Team (openerp)
For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-project-kanban/+merge/97342
[IMP]:project:improved kanban view for project.
--
https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-project-kanban/+merge/97342
Your team OpenERP R&D Team is subscribed to branch
lp:~openerp-dev/openobject-addons/trunk-project-kanban.
=== modified file 'project/__openerp__.py'
--- project/__openerp__.py 2012-02-13 15:27:55 +0000
+++ project/__openerp__.py 2012-03-14 05:10:37 +0000
@@ -71,5 +71,8 @@
'auto_install': False,
'application': True,
'certificate': '0075116868317',
+ 'css': [
+ 'static/src/css/project.css'
+ ],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'project/images/photo.png'
Binary files project/images/photo.png 1970-01-01 00:00:00 +0000 and project/images/photo.png 2012-03-14 05:10:37 +0000 differ
=== modified file 'project/project.py'
--- project/project.py 2012-02-28 14:08:16 +0000
+++ project/project.py 2012-03-14 05:10:37 +0000
@@ -26,6 +26,7 @@
from tools.translate import _
from osv import fields, osv
from openerp.addons.resource.faces import task as Task
+from openerp import addons
# I think we can remove this in v6.1 since VMT's improvements in the framework ?
#class project_project(osv.osv):
@@ -149,6 +150,14 @@
res[id]['progress_rate'] = 0.0
return res
+ def _open_task(self, cr, uid, ids, field_name, arg, context=None):
+ open_task={}
+ task_pool=self.pool.get('project.task')
+ for id in ids:
+ task_ids = task_pool.search(cr, uid, [('project_id', '=', id)])
+ open_task[id] = len(task_ids)
+ return open_task
+
def unlink(self, cr, uid, ids, *args, **kwargs):
for proj in self.browse(cr, uid, ids):
if proj.tasks:
@@ -191,12 +200,14 @@
'warn_header': fields.text('Mail Header', help="Header added at the beginning of the email for the warning message sent to the customer when a task is closed.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
'warn_footer': fields.text('Mail Footer', help="Footer added at the beginning of the email for the warning message sent to the customer when a task is closed.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
+ 'open_task': fields.function(_open_task , type='integer',string="Open Tasks"),
}
+
def _get_type_common(self, cr, uid, context):
ids = self.pool.get('project.task.type').search(cr, uid, [('project_default','=',1)], context=context)
return ids
- _order = "sequence"
+ _order = "sequence,priority"
_defaults = {
'active': True,
'priority': 1,
@@ -251,7 +262,7 @@
message = _("The project '%s' has been opened.") % name
self.log(cr, uid, id, message)
return res
-
+
def map_tasks(self, cr, uid, old_project_id, new_project_id, context=None):
""" copy and map tasks from old to new project """
if context is None:
@@ -443,6 +454,45 @@
'user_id': int(p.booked_resource[0].name[5:]),
}, context=context)
return True
+
+ def open_tasks(self, cr, uid, ids, context=None):
+ #Open the View for the Tasks for the project
+ """
+ This opens Tasks views
+ @return :Dictionary value for task view
+ """
+ if context is None:
+ context = {}
+ value = {}
+ data_obj = self.pool.get('ir.model.data')
+ for project in self.browse(cr, uid, ids, context=context):
+ # Get Task views
+ tree_view = data_obj.get_object_reference(cr, uid, 'project', 'view_task_tree2')
+ form_view = data_obj.get_object_reference(cr, uid, 'project', 'view_task_form2')
+ calander_view = data_obj.get_object_reference(cr, uid, 'project', 'view_task_calendar')
+ search_view = data_obj.get_object_reference(cr, uid, 'project', 'view_task_search_form')
+ kanban_view = data_obj.get_object_reference(cr, uid, 'project', 'view_task_kanban')
+ context.update({
+ #'search_default_user_id': uid,
+ 'search_default_project_id':project.id,
+ #'search_default_open':1,
+ })
+ value = {
+ 'name': _('Task'),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'form,tree',
+ 'res_model': 'project.task',
+ 'view_id': False,
+ 'domain':[('project_id','in',ids)],
+ 'context': context,
+ 'views': [(kanban_view and kanban_view[1] or False, 'kanban'),(tree_view and tree_view[1] or False, 'tree'),(calander_view and calander_view[1] or False, 'calendar'),(form_view and form_view[1] or False, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'search_view_id': search_view and search_view[1] or False,
+ 'nodestroy': True
+ }
+ return value
+
project()
class users(osv.osv):
@@ -913,7 +963,7 @@
for attachment_id in attachment_ids:
new_attachment_ids.append(attachment.copy(cr, uid, attachment_id, default={'res_id': delegated_task_id}, context=context))
return new_attachment_ids
-
+
def do_delegate(self, cr, uid, ids, delegate_data={}, context=None):
"""
@@ -944,7 +994,7 @@
self.do_pending(cr, uid, task.id, context=context)
elif delegate_data['state'] == 'done':
self.do_close(cr, uid, task.id, context=context)
-
+
message = _("The task '%s' has been delegated to %s.") % (delegate_data['name'], delegate_data['user_id'][1])
self.log(cr, uid, task.id, message)
delegated_tasks[task.id] = delegated_task_id
@@ -1042,7 +1092,7 @@
new_stage = vals.get('type_id')
vals_reset_kstate = dict(vals, kanban_state='normal')
for t in self.browse(cr, uid, ids, context=context):
- write_vals = vals_reset_kstate if t.type_id != new_stage else vals
+ write_vals = vals_reset_kstate if t.type_id != new_stage else vals
super(task,self).write(cr, uid, [t.id], write_vals, context=context)
result = True
else:
@@ -1179,7 +1229,7 @@
for history in self.browse(cr, uid, ids, context=context):
cr.execute('''select
id
- from
+ from
project_task_history
where
task_id=%s and
=== modified file 'project/project_view.xml'
--- project/project_view.xml 2012-02-13 15:27:55 +0000
+++ project/project_view.xml 2012-03-14 05:10:37 +0000
@@ -11,7 +11,6 @@
<menuitem id="menu_project_management" name="Project" parent="base.menu_main_pm" sequence="1"/>
<menuitem id="menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/>
-
<!-- Project -->
<record id="edit_project" model="ir.ui.view">
<field name="name">project.project.form</field>
@@ -165,18 +164,71 @@
</field>
</record>
+ <record model="ir.ui.view" id="view_project_kanban">
+ <field name="name">project.project.kanban</field>
+ <field name="model">project.project</field>
+ <field name="type">kanban</field>
+ <field name="arch" type="xml">
+ <kanban>
+ <field name="effective_hours"/>
+ <field name="total_hours"/>
+ <field name="date"/>
+ <templates>
+ <t t-name="kanban-box">
+ <div class="oe_module_vignette oe_kanban_box oe_kanban_color_border">
+ <div class="oe_module_icon oe_project oe_project_border">
+ <div class="sequence">
+ <a type="edit"><img class="oe_topbar_avatar" data-default-src="/web/static/src/img/topbar-avatar.png" src="/web/static/src/img/topbar-avatar.png"/></a>
+ <!--<field name="priority"/>-->
+ </div>
+ <kbd class="user">Manager</kbd><br/>
+ <div class="manager"><field name="user_id"/></div>
+ <t t-if="record.date.raw_value">
+ <kbd class="user">Deadline</kbd><br/>
+ <div class="manager"><field name="date"/></div>
+ </t>
+ </div>
+ <div class="oe_module_desc">
+ <h4 class="oe_project_font1"><a type="edit"><div class="oe_project_font"><field name="name"/></div></a></h4>
+ <p class="tasks">
+ <button name="open_tasks" class="oe_project_buttons" type="object"><i>Tasks (<field name="open_task"/>)</i></button>
+ </p>
+
+ <div class="progress invoiced">
+ <br/>
+ <t t-esc="Math.round(record.effective_hours.raw_value)"/> hrs
+ <progress t-att-value="record.effective_hours.raw_value" t-att-max="record.total_hours.raw_value"></progress>
+ <t t-esc="Math.round(record.total_hours.raw_value)"/> hrs
+ </div>
+ </div>
+ <br/>
+
+ </div>
+ </t>
+ </templates>
+
+ </kanban>
+ </field>
+ </record>
+
<record id="open_view_project_all" model="ir.actions.act_window">
<field name="name">Projects</field>
<field name="res_model">project.project</field>
<field name="view_type">form</field>
<field name="domain">[]</field>
- <field name="view_mode">tree,form,gantt</field>
+ <field name="view_mode">kanban,tree,form,gantt</field>
<field name="view_id" ref="view_project"/>
<field name="search_view_id" ref="view_project_project_filter"/>
- <field name="context">{'search_default_Current':1}</field>
+ <!-- <field name="context">{'search_default_Current':1}</field> -->
<field name="help">A project contains a set of tasks or issues that will be performed by your resources assigned to it. A project can be hierarchically structured, as a child of a Parent Project. This allows you to design large project structures with different phases spread over the project duration cycle. Each user can set his default project in his own preferences to automatically filter the tasks or issues he usually works on. If you choose to invoice the time spent on a project task, you can find project tasks to be invoiced in the billing section.</field>
</record>
+ <record id="open_view_project_kanban" model="ir.actions.act_window.view">
+ <field name="sequence" eval="0"/>
+ <field name="view_mode">kanban</field>
+ <field name="act_window_id" ref="open_view_project_all"/>
+ </record>
+
<record id="open_view_template_project" model="ir.actions.act_window">
<field name="name">Templates of Projects</field>
<field name="res_model">project.project</field>
@@ -623,12 +675,9 @@
</record>
<menuitem id="menu_tasks_config" name="Tasks" parent="project.menu_definitions" sequence="1"/>
-
- <menuitem id="menu_project_config_project" name="Projects and Stages" parent="menu_definitions" sequence="1"/>
-
+ <menuitem id="menu_project_config_project" name="Stages" parent="menu_definitions" sequence="1"/>
<menuitem action="open_task_type_form" id="menu_task_types_view" parent="menu_project_config_project" sequence="2"/>
- <menuitem action="open_view_project_all" id="menu_open_view_project_all" parent="menu_project_config_project" sequence="1"/>
-
+ <menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/>
<act_window context="{'search_default_user_id': [active_id], 'default_user_id': active_id}" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/>
<act_window
=== added directory 'project/static/src/css'
=== added file 'project/static/src/css/project.css'
--- project/static/src/css/project.css 1970-01-01 00:00:00 +0000
+++ project/static/src/css/project.css 2012-03-14 05:10:37 +0000
@@ -0,0 +1,134 @@
+.oe_project_vignette {
+ padding: 6px;
+ min-height: 100px;
+}
+.oe_project_border{
+ border-right: groove;
+}
+
+.progress{
+ text-align: le;
+ width: auto;
+}
+.oe_project_font{
+ color: #000000;
+
+}
+.sequence {
+border-bottom: groove;
+font-size: 20px;
+
+}
+
+.invoiced{
+ font-size: 10px;
+
+}
+.oe_project {
+width: 70px;
+}
+.user {
+color:rgb(192,192,192);
+font-size: 10px;
+}
+.manager {
+font-size: 9px;
+}
+
+.oe_project_buttons {
+ display: inline-block;
+ padding: 0px 0px;
+ background-color: transparent;
+ border: hidden;
+ color: #0000FF;
+
+}
+
+.oe_project_buttons:hover {
+ cursor: pointer;
+ background-size: 100% 100%;
+}
+
+.oe_project_font1{
+
+ -webkit-margin-before: 0em;
+-webkit-margin-after: 0em;
+}
+
+.oe_project_icon, .oe_project_desc {
+ display: inline-block;
+ vertical-align: top;
+}
+
+.oe_project_icon {
+ width: 80px;
+ height: 80px;
+ padding: 0 4px;
+}
+
+.oe_project_progress{
+ border-top-left-radius:3px;
+ border-top-right-radius:3px;
+ font-size: 40px;
+ height:70px;
+ font-weight: bold;
+ text-align: center;
+ margin-bottom:-7px;
+ color: #FFFFFF;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
+ background-color: #8A89BA;
+}
+.oe_project_end_date{
+ border-bottom-left-radius:3px;
+ border-bottom-right-radius:3px;
+ font-size: 12px;
+ text-align: center;
+ font-weight: bold;
+ color: #8A89BA;
+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
+ background-color: #FFFFFF;
+}
+.oe_project_text{
+ border-bottom-left-radius:3px;
+ border-bottom-right-radius:3px;
+ font-size: 15px;
+ text-align: center;
+ font-weight: bold;
+ color: #FFFFFF;
+ background-color: #8A89BA;
+}
+.oe_project_image {
+ width: 20px;
+ height: 20px;
+ }
+
+.oe_project_desc {
+ width: 220px;
+ font-size: 13px;
+ padding: 2px 5px;
+ color: #4c4c4c;
+}
+
+.oe_project_desc h4 {
+ margin: 0;
+ font-size: 13px;
+}
+
+.oe_project_desc h4 a {
+ color: #4c4c4c;
+}
+
+.oe_project_desc h4 a:hover {
+ text-decoration: underline;
+}
+
+.oe_project_desc p {
+ margin: 3px 0 5px;
+}
+
+.oe_project_desc .oe_button {
+ font-size: 66%;
+ min-width: 40px;
+ height: 17px;
+}
+
=== modified file 'project_issue/project_issue.py'
--- project_issue/project_issue.py 2011-12-21 22:15:04 +0000
+++ project_issue/project_issue.py 2012-03-14 05:10:37 +0000
@@ -487,9 +487,28 @@
class project(osv.osv):
_inherit = "project.project"
+
+ def _compute_issue(self, cr, uid, ids, field_name, arg, context=None):
+ res={}
+ issue_pool=self.pool.get('project.issue')
+ for project in self.browse(cr, uid, ids, context=context):
+ issues = issue_pool.search(cr, uid, [('project_id','=',project.id)])
+ res[project.id] = len(issues)
+ return res
+
+ def _open_issue(self, cr, uid, ids, field_name, arg, context=None):
+ open_issue={}
+ issue_pool=self.pool.get('project.issue')
+ for id in ids:
+ issue_ids = issue_pool.search(cr, uid, [('project_id', '=', id)])
+ open_issue[id] = len(issue_ids)
+ return open_issue
+
_columns = {
'project_escalation_id' : fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
- 'reply_to' : fields.char('Reply-To Email Address', size=256)
+ 'reply_to' : fields.char('Reply-To Email Address', size=256),
+ 'issues': fields.function(_compute_issue , store=True,type='integer',string="Issue"),
+ 'open_issues': fields.function(_open_issue , type='integer',string="Open Issues"),
}
def _check_escalation(self, cr, uid, ids, context=None):
@@ -499,6 +518,43 @@
return False
return True
+ def open_issues(self, cr, uid, ids, context=None):
+ #Open the View for the Tasks for the project
+ """
+ This opens Issues views
+ @return :Dictionary value for issue view
+ """
+ if context is None:
+ context = {}
+ value = {}
+ data_obj = self.pool.get('ir.model.data')
+ for project in self.browse(cr, uid, ids, context=context):
+ # Get Task views
+ tree_view = data_obj.get_object_reference(cr, uid, 'project_issue', 'project_issue_tree_view')
+ form_view = data_obj.get_object_reference(cr, uid, 'project_issue', 'project_issue_form_view')
+ calander_view = data_obj.get_object_reference(cr, uid, 'project_issue', 'project_issue_calendar_view')
+ search_view = data_obj.get_object_reference(cr, uid, 'project_issue', 'view_project_issue_filter')
+ kanban_view = data_obj.get_object_reference(cr, uid, 'project_issue', 'project_issue_kanban_view')
+ context.update({
+ #'search_default_user_id': uid,
+ 'search_default_project_id':project.id
+ })
+ value = {
+ 'name': _('Issue'),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'form,tree',
+ 'res_model': 'project.issue',
+ 'view_id': False,
+ 'domain':[('project_id','in',ids)],
+ 'context': context,
+ 'views': [(kanban_view and kanban_view[1] or False, 'kanban'),(tree_view and tree_view[1] or False, 'tree'),(calander_view and calander_view[1] or False, 'calendar'),(form_view and form_view[1] or False, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'search_view_id': search_view and search_view[1] or False,
+ 'nodestroy': True
+ }
+ return value
+
_constraints = [
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
]
=== modified file 'project_issue/project_issue_view.xml'
--- project_issue/project_issue_view.xml 2011-12-19 16:54:40 +0000
+++ project_issue/project_issue_view.xml 2012-03-14 05:10:37 +0000
@@ -234,7 +234,21 @@
</calendar>
</field>
</record>
-
+ <!--project kanban view -->
+ <record id="view_project_kanban_inherited" model="ir.ui.view">
+ <field name="name">project.project.kanban.inherited</field>
+ <field name="model">project.project</field>
+ <field name="type">kanban</field>
+ <field name="inherit_id" ref="project.view_project_kanban"/>
+ <field name="arch" type="xml">
+ <xpath expr="//p[@class='tasks']" position="replace">
+ <p class="issues">
+ <button name="open_tasks" class="oe_project_buttons" type="object"><i>Tasks (<field name="open_task"/>)</i></button>
+ <button name="open_issues" class="oe_project_buttons" type="object"><i>Issues (<field name="open_issues"/>)</i></button>
+ </p>
+ </xpath>
+ </field>
+ </record>
<!-- Project Issue Karban View-->
@@ -344,7 +358,7 @@
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Feature Tracker Search">
- <filter icon="terp-go-today" string="Today"
+ <filter icon="terp-go-today" string="Today"
domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Today's features"/>
<separator orientation="vertical"/>
<group>
=== modified file 'project_timesheet/project_timesheet_view.xml'
--- project_timesheet/project_timesheet_view.xml 2012-01-31 13:36:57 +0000
+++ project_timesheet/project_timesheet_view.xml 2012-03-14 05:10:37 +0000
@@ -43,6 +43,19 @@
</xpath>
</field>
</record>
+ <!--project kanban view -->
+ <record id="view_project_timesheet_kanban_inherited" model="ir.ui.view">
+ <field name="name">project.project.timesheet.kanban.inherited</field>
+ <field name="model">project.project</field>
+ <field name="type">kanban</field>
+ <field name="inherit_id" ref="project.view_project_kanban"/>
+ <field name="arch" type="xml">
+ <xpath expr="//div[@class='progress invoiced']" position="before">
+ <b><kbd class="progress invoiced">Invoiced : <field name="amount_invoiced"/> <field name="currency_id"/></kbd></b>
+ </xpath>
+ </field>
+ </record>
+
<record id="view_account_analytic_line_search_account_inherit" model="ir.ui.view">
<field name="name">account.analytic.line.search.account_id</field>
<field name="model">account.analytic.line</field>
_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help : https://help.launchpad.net/ListHelp