Merge lp:~openerp-dev/openobject-addons/trunk-form-v2-project-chs into lp:~openerp-dev/openobject-addons/trunk-form-v2-fme

Proposed by Christophe Simonis (OpenERP)
Status: Needs review
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-form-v2-project-chs
Merge into: lp:~openerp-dev/openobject-addons/trunk-form-v2-fme
Diff against target: 1100 lines (+812/-11)
17 files modified
project/__openerp__.py (+3/-1)
project/project.py (+39/-1)
project/project_view.xml (+91/-6)
project/static/src/css/project.css (+231/-0)
project/static/src/js/dropdown.js (+92/-0)
project/static/src/js/project.js (+71/-0)
project_issue/__openerp__.py (+1/-0)
project_issue/project_issue.py (+49/-2)
project_issue/project_issue_menu.xml (+1/-0)
project_issue/project_issue_view.xml (+25/-0)
project_issue/static/src/js/project_issue.js (+14/-0)
project_long_term/project_long_term.py (+39/-1)
project_long_term/project_long_term_view.xml (+32/-0)
project_timesheet/__openerp__.py (+1/-0)
project_timesheet/project_timesheet.py (+60/-0)
project_timesheet/project_timesheet_view.xml (+42/-0)
project_timesheet/static/src/js/project_timesheet.js (+21/-0)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-form-v2-project-chs
Reviewer Review Type Date Requested Status
Antony Lesuisse (OpenERP) Needs Fixing
Review via email: mp+101402@code.launchpad.net

Description of the change

mergeable ?

To post a comment you must log in.
6722. By Christophe Simonis (OpenERP)

[~IMP] project_*: simplify open_* actions for project kanban view

Revision history for this message
Antony Lesuisse (OpenERP) (al-openerp) wrote :

Nope need cleanups [rco].

review: Needs Fixing
Revision history for this message
Antony Lesuisse (OpenERP) (al-openerp) wrote :

The merge should now target trunk.

Unmerged revisions

6722. By Christophe Simonis (OpenERP)

[~IMP] project_*: simplify open_* actions for project kanban view

6721. By Christophe Simonis (OpenERP)

[~FIX] project: correct kanban css

6720. By Christophe Simonis (OpenERP)

[MERGE] lp:~openerp-dev/openobject-addons/trunk-project-gallery-apa

6719. By Christophe Simonis (OpenERP)

[FIX] project: remove dependence to wiki module

6718. By Christophe Simonis (OpenERP)

[FIX] project: correct dependencies

6717. By Christophe Simonis (OpenERP)

[FIX] remove Antony's shit

6716. By Quentin (OpenERP) <email address hidden>

[IMP] sale: applied changes in sale order form view as per last trunk

6715. By Quentin (OpenERP) <email address hidden>

[FIX] base_setup: resolved tag mismatch

6714. By Antony Lesuisse (OpenERP)

crm.lead

6713. By Antony Lesuisse (OpenERP)

sale html to form

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'project/__openerp__.py'
2--- project/__openerp__.py 2012-04-10 12:09:38 +0000
3+++ project/__openerp__.py 2012-04-10 16:40:13 +0000
4@@ -29,7 +29,7 @@
5 "sequence": 8,
6 'complexity': "easy",
7 "images": ["images/gantt.png", "images/project_dashboard.jpeg","images/project_task_tree.jpeg","images/project_task.jpeg","images/project.jpeg","images/task_analysis.jpeg"],
8- "depends": ["base_setup", "product", "analytic", "board", "mail", "resource"],
9+ "depends": ["base_setup", "product", "analytic", "board", "mail", "resource","web_kanban"],
10 "description": """
11 Project management module tracks multi-level projects, tasks, work done on tasks, eso.
12 ======================================================================================
13@@ -70,6 +70,8 @@
14 'installable': True,
15 'auto_install': False,
16 'application': True,
17+ 'css': ['static/src/css/project.css'],
18+ 'js': ['static/src/js/dropdown.js','static/src/js/project.js'],
19 'certificate': '0075116868317',
20 }
21 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
22
23=== modified file 'project/project.py'
24--- project/project.py 2012-04-03 17:21:08 +0000
25+++ project/project.py 2012-04-10 16:40:13 +0000
26@@ -154,6 +154,14 @@
27 if proj.tasks:
28 raise osv.except_osv(_('Operation Not Permitted !'), _('You cannot delete a project containing tasks. I suggest you to desactivate it.'))
29 return super(project, self).unlink(cr, uid, ids, *args, **kwargs)
30+
31+ def _open_task(self, cr, uid, ids, field_name, arg, context=None):
32+ open_task={}
33+ task_pool=self.pool.get('project.task')
34+ for id in ids:
35+ task_ids = task_pool.search(cr, uid, [('project_id', '=', id)])
36+ open_task[id] = len(task_ids)
37+ return open_task
38
39 _columns = {
40 'complete_name': fields.function(_complete_name, string="Project Name", type='char', size=250),
41@@ -191,7 +199,35 @@
42 '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)]}),
43 '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)]}),
44 'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
45+ 'task': fields.boolean('Task',help = "If you check this field tasks appears in kanban view"),
46+ 'open_task': fields.function(_open_task , type='integer',string="Open Tasks"),
47+ 'color': fields.integer('Color Index'),
48 }
49+ def dummy(self, cr, uid, ids, context=None):
50+ return False
51+
52+ def open_tasks(self, cr, uid, ids, context=None):
53+ #Open the View for the Tasks for the project
54+ """
55+ This opens Tasks views
56+ @return :Dictionary value for task view
57+ """
58+ if context is None:
59+ context = {}
60+ if ids:
61+ context = dict(context, search_default_project_id=ids[0])
62+ return {
63+ 'name': _('Task'),
64+ 'context': context,
65+ 'view_type': 'form',
66+ 'view_mode': 'kanban,tree,calendar,form',
67+ 'res_model': 'project.task',
68+ 'view_id': False,
69+ 'domain':[('project_id','in',ids)],
70+ 'type': 'ir.actions.act_window',
71+ 'nodestroy': True
72+ }
73+
74 def _get_type_common(self, cr, uid, context):
75 ids = self.pool.get('project.task.type').search(cr, uid, [('project_default','=',1)], context=context)
76 return ids
77@@ -201,7 +237,8 @@
78 'active': True,
79 'priority': 1,
80 'sequence': 10,
81- 'type_ids': _get_type_common
82+ 'type_ids': _get_type_common,
83+ 'task' : True,
84 }
85
86 # TODO: Why not using a SQL contraints ?
87@@ -720,6 +757,7 @@
88 'sequence': 10,
89 'active': True,
90 'user_id': lambda obj, cr, uid, context: uid,
91+ 'project_id':lambda self, cr, uid, context: context.get('active_id',False),
92 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
93 }
94
95
96=== modified file 'project/project_view.xml'
97--- project/project_view.xml 2012-04-10 12:09:38 +0000
98+++ project/project_view.xml 2012-04-10 16:40:13 +0000
99@@ -19,7 +19,7 @@
100 <field name="type">form</field>
101 <field name="arch" type="xml">
102 <form string="Project">
103- <group colspan="6" col="6">
104+ <group colspan="4" col="6">
105 <field name="name" string="Project Name" select="1"/>
106 <field name="analytic_account_id" invisible="1" required="0"/>
107 <field name="parent_id" string="Parent" domain="[('id','!=',analytic_account_id)]" context="{'current_model': 'project.project'}"/>
108@@ -30,12 +30,17 @@
109 </group>
110 <notebook colspan="4">
111 <page string="Administration">
112+ <group col="2" colspan="2" name="kanban">
113+ <separator colspan="2" string="Project Management"/>
114+ <field name="task"/>
115+ </group>
116 <group col="2" colspan="2">
117- <separator colspan="2" string="Performance"/>
118+ <separator colspan="4" string="Performance"/>
119 <field name="planned_hours" widget="float_time"/>
120 <field name="effective_hours" widget="float_time" />
121 <field name="resource_calendar_id"/>
122 </group>
123+ <newline/>
124 <group col="2" colspan="2" name="misc">
125 <separator colspan="4" string="Miscelleanous"/>
126 <field name="company_id" select="1" groups="base.group_multi_company" widget="selection" required="1"/>
127@@ -154,6 +159,86 @@
128 </tree>
129 </field>
130 </record>
131+
132+ <record model="ir.ui.view" id="view_project_kanban">
133+ <field name="name">project.project.kanban</field>
134+ <field name="model">project.project</field>
135+ <field name="type">kanban</field>
136+ <field name="arch" type="xml">
137+ <kanban>
138+ <field name="effective_hours"/>
139+ <field name="total_hours"/>
140+ <field name="date"/>
141+ <field name="name"/>
142+ <field name="members"/>
143+ <field name="task"/>
144+ <field name="user_id"/>
145+ <field name="date"/>
146+ <field name="color"/>
147+ <field name="open_task"/>
148+ <templates>
149+ <t t-name="kanban-box">
150+ <div class="project_vignettes">
151+ <li t-attf-class="oe_project_kanban_vignette #{kanban_color(record.color.raw_value)}">
152+ <a href="#" class="oe_project_kanban_action dropdown-toggle"><span class="oe_i">B</span></a>
153+ <ul class="dropdown-menu">
154+ <li ><a type="edit" >Edit...</a></li>
155+ <li ><a type="delete">Delete</a></li>
156+ <!--li>
157+ <ul class="color-chooser">
158+ <li><a t-att-id="record.id.value" class="bgcolor_steelblue"><span class="steelblue square"></span></a></li>
159+ <li><a t-att-id="record.id.value" class="bgcolor_firebrick"><span class="firebrick square"></span></a></li>
160+ <li><a t-att-id="record.id.value" class="bgcolor_khaki"><span class="khaki square"></span></a></li>
161+ <li><a t-att-id="record.id.value" class="bgcolor_thistle"><span class="thistle square"></span></a></li>
162+ <li><a t-att-id="record.id.value" class="bgcolor_orange"><span class="orange square"></span></a></li>
163+ </ul>
164+ </li-->
165+ </ul>
166+ <h4><t t-esc="record.name.value.substr(0,32)"/><t t-if="record.name.value.length > 32">...</t></h4>
167+ <h4 id="list" height="10px">
168+ <a id="1">
169+ <t t-if="record.task.raw_value">
170+ <button name="open_tasks" id = "open_tasks" class="oe_project_buttons" type="object"><t t-if="record.open_task.value &lt;= 1"> Task</t><t t-if="record.open_task.value &gt; 1"> Tasks</t>(<t t-esc="record.open_task.value"/>)</button>
171+ </t>
172+ </a>
173+ </h4>
174+ <br />
175+ <button class="click_button" type="object">
176+ <table class="project_fields">
177+ <tr id="deadline" t-if="record.date.raw_value">
178+ <th align="left">Deadline</th>
179+ <td align="left">
180+ <t t-esc="record.date.raw_value.toString('MMMM')"/>
181+ <t t-esc="record.date.raw_value.getDate()"/>,
182+ <t t-esc="record.date.raw_value.getFullYear()"/>
183+ </td>
184+ </tr>
185+ <tr>
186+ <th align="left" width="70px">Progress</th>
187+ <td align="left">
188+ <t t-esc="Math.round(record.effective_hours.raw_value/24)"/>/<t t-esc="Math.round(record.total_hours.raw_value/24)"/> days
189+ </td>
190+ </tr>
191+ </table>
192+ <t t-if="record.members.raw_value.length > 7">
193+ <t t-foreach="record.members.raw_value" t-as="member">
194+ <img t-att-src="kanban_image('res.users', 'avatar', member)" t-att-id="member" class="project_avatar"/>
195+ </t>
196+ </t>
197+ <t t-if="record.members.raw_value.length &lt;= 7">
198+ <br/><br/>
199+ <t t-foreach="record.members.raw_value" t-as="member">
200+ <img t-att-src="kanban_image('res.users', 'avatar', member)" t-att-id="member" class="project_avatar"/>
201+ </t>
202+ </t>
203+ </button>
204+ </li>
205+ </div>
206+ </t>
207+ </templates>
208+ </kanban>
209+ </field>
210+ </record>
211
212 <record id="view_project_project_gantt" model="ir.ui.view">
213 <field name="name">project.project.gantt</field>
214@@ -170,8 +255,8 @@
215 <field name="res_model">project.project</field>
216 <field name="view_type">form</field>
217 <field name="domain">[]</field>
218- <field name="view_mode">tree,form,gantt</field>
219- <field name="view_id" ref="view_project"/>
220+ <field name="view_mode">kanban,tree,form,gantt</field>
221+ <field name="view_id" ref="view_project_kanban"/>
222 <field name="search_view_id" ref="view_project_project_filter"/>
223 <field name="context">{}</field>
224 <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>
225@@ -621,10 +706,10 @@
226
227 <menuitem id="menu_tasks_config" name="GTD" parent="project.menu_definitions" sequence="1"/>
228
229- <menuitem id="menu_project_config_project" name="Projects and Stages" parent="menu_definitions" sequence="1"/>
230+ <menuitem id="menu_project_config_project" name="Stages" parent="menu_definitions" sequence="1"/>
231
232 <menuitem action="open_task_type_form" id="menu_task_types_view" parent="menu_project_config_project" sequence="2" groups="base.group_no_one"/>
233- <menuitem action="open_view_project_all" id="menu_open_view_project_all" parent="menu_project_config_project" sequence="1" groups="base.group_no_one"/>
234+ <menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/>
235
236 <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"/>
237
238
239=== added directory 'project/static/src/css'
240=== added file 'project/static/src/css/project.css'
241--- project/static/src/css/project.css 1970-01-01 00:00:00 +0000
242+++ project/static/src/css/project.css 2012-04-10 16:40:13 +0000
243@@ -0,0 +1,231 @@
244+.project_fields {
245+ margin-top: 1px;
246+ margin-bottom: 1px;
247+ font-size: 11px;
248+ }
249+.project_fields td {
250+ border: none;
251+ padding: 2px 0 2px 8px; }
252+.project_fields th {
253+ padding: 0;
254+ border-right: 1px solid #dddddd;
255+ vertical-align: top;
256+ margin-right: 8px; }
257+
258+ .project_vignettes li {
259+ float: left; }
260+ .project_vignettes .project_avatar {
261+ width: 28px;
262+ height: 28px; }
263+ .project_vignettes .project_fields {
264+ width: 100%; }
265+ .project_vignettes .project_fields th {
266+ font-weight: normal; }
267+ .project_vignettes .project_fields td {
268+ color: #888888; }
269+ .project_vignettes h4 a {
270+ color: #4c4c4c; }
271+
272+
273+ .project_vignettes > li h4 {
274+ margin-bottom: 2px; }
275+
276+.oe_project_buttons {
277+ padding: 0px 0px !important;
278+ background: none !important;
279+ background-color: transparent !important;
280+ border: hidden !important;
281+ color: #8A89BA !important;
282+
283+}
284+
285+.oe_project_buttons:hover {
286+ cursor: pointer;
287+ color: #0000FF;
288+}
289+
290+.project_avatar {
291+ -moz-border-radius: 4px;
292+ -webkit-border-radius: 4px;
293+ border-radius: 4px;
294+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
295+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
296+ -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); }
297+
298+
299+.click_button {
300+ background: none !important;
301+ background-color: transparent !important;
302+ border: hidden !important;
303+ min-height: 155px;
304+ min-width: 265px;
305+ border: hidden;
306+ margin-left: 6px !important;
307+ margin-top: 3px !important;
308+ text-align: left;
309+ vertical-align: super;
310+ font-size: 11px;
311+}
312+
313+.dropdown-menu {
314+ display: none;
315+ position: absolute; }
316+
317+.dropdown {
318+ position: relative; }
319+
320+.dropdown-toggle:after {
321+ width: 0;
322+ height: 0;
323+ display: inline-block;
324+ content: "&darr";
325+ text-indent: -99999px;
326+ vertical-align: top;
327+ margin-top: 8px;
328+ margin-left: 4px;
329+ border-left: 4px solid transparent;
330+ border-right: 4px solid transparent;
331+ border-top: 4px solid white;
332+ filter: alpha(opacity=50);
333+ -khtml-opacity: 0.5;
334+ -moz-opacity: 0.5;
335+ opacity: 0.5; }
336+
337+
338+ .oe_project_kanban_vignette .dropdown-menu .color-chooser {
339+ padding: 0 3px; }
340+ .oe_project_kanban_vignette .dropdown-menu .color-chooser li {
341+ float: left; }
342+ .oe_project_kanban_vignette .dropdown-menu .color-chooser li a {
343+ padding: 2px; }
344+a.oe_project_kanban_action {
345+ position: absolute;
346+ right: 0;
347+ display: none;
348+ }
349+ a.oe_project_kanban_action:hover {
350+ text-decoration: none; }
351+ a.oe_project_kanban_action .oe_i {
352+ color: #4c4c4c; }
353+.square {
354+ display: inline-block;
355+ width: 18px;
356+ height: 18px; }
357+
358+.oe_kanban_color_1 {
359+ background: steelblue;
360+}
361+.oe_kanban_color_2 {
362+ background: firebrick;
363+}
364+.oe_kanban_color_3 {
365+ background: khaki;
366+}
367+.oe_kanban_color_4 {
368+ background: thistle;
369+}
370+.oe_kanban_color_5 {
371+ background: orange;
372+}
373+
374+
375+.steelblue {
376+ background: steelblue; }
377+
378+.firebrick {
379+ background: firebrick; }
380+
381+.khaki {
382+ background: khaki; }
383+
384+.thistle {
385+ background: thistle; }
386+
387+.orange {
388+ background: orange; }
389+.open {
390+ display: block;
391+ }
392+ .open .dropdown-menu {
393+ display: block; }
394+
395+
396+a.oe_project_kanban_action {
397+ position: absolute;
398+ right: 0;
399+ }
400+ a.oe_project_kanban_action:hover {
401+ text-decoration: none;
402+ }
403+ a.oe_project_kanban_action .eo_i {
404+ color: #4c4c4c; }
405+
406+
407+.oe_project_kanban_vignette {
408+ position: relative;
409+ min-height: 50px;
410+ background: white;
411+ border: 1px solid #d8d8d8;
412+ border-bottom-color: #b9b9b9;
413+ padding: 6px;
414+ margin: 6px 0;
415+ display: inline-block;
416+ -moz-border-radius: 4px;
417+ -webkit-border-radius: 4px;
418+ border-radius: 4px;
419+
420+}
421+ .oe_project_kanban_vignette:last-child {
422+ margin-bottom: 0; }
423+ .oe_project_kanban_vignette:hover {
424+ -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
425+ -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
426+ -box-shadow: 0 0 3px rgba(0, 0, 0, 0.6); }
427+ .oe_project_kanban_vignette h4 {
428+ margin: 0 0 2px; }
429+
430+
431+.oe_project_kanban_vignette .dropdown-menu {
432+ top: 30px;
433+ right: -140px;
434+ padding: 4px;
435+ border: 1px solid #afafb6;
436+ width: 160px;
437+ overflow-x: hidden;
438+ z-index: 900;
439+ background: white;
440+ -moz-border-radius: 3px;
441+ -webkit-border-radius: 3px;
442+ border-radius: 3px;
443+ -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
444+ -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
445+ -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3); }
446+ .oe_project_kanban_vignette .dropdown-menu p {
447+ margin-left: 12px; }
448+ .oe_project_kanban_vignette .dropdown-menu li {
449+ float: none;
450+ display: block;
451+ background-color: none; }
452+ .oe_project_kanban_vignette .dropdown-menu li a {
453+ display: block;
454+ padding: 3px 6px;
455+ clear: both;
456+ font-weight: normal;
457+ line-height: 14px;
458+ color: #4c4c4c;
459+ text-decoration: none; }
460+ .oe_project_kanban_vignette .dropdown-menu li a:hover {
461+ background: #f0f0fa;
462+ background: -moz-linear-gradient(#f0f0fa, #eeeef6);
463+ background: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6));
464+ background: -webkit-linear-gradient(#f0f0fa, #eeeef6);
465+ -moz-box-shadow: none;
466+ -webkit-box-shadow: none;
467+ -box-shadow: none; }
468+
469+.oe_project_kanban_vignette .dropdown-menu .color-chooser {
470+ padding: 0 3px; }
471+ .oe_project_kanban_vignette .dropdown-menu .color-chooser li {
472+ float: left; }
473+ .oe_project_kanban_vignette .dropdown-menu .color-chooser li a {
474+ padding: 2px; }
475
476=== added file 'project/static/src/img/tasks_icon.png'
477Binary files project/static/src/img/tasks_icon.png 1970-01-01 00:00:00 +0000 and project/static/src/img/tasks_icon.png 2012-04-10 16:40:13 +0000 differ
478=== added directory 'project/static/src/js'
479=== added file 'project/static/src/js/dropdown.js'
480--- project/static/src/js/dropdown.js 1970-01-01 00:00:00 +0000
481+++ project/static/src/js/dropdown.js 2012-04-10 16:40:13 +0000
482@@ -0,0 +1,92 @@
483+/* ============================================================
484+ * bootstrap-dropdown.js v2.0.2
485+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
486+ * ============================================================
487+ * Copyright 2012 Twitter, Inc.
488+ *
489+ * Licensed under the Apache License, Version 2.0 (the "License");
490+ * you may not use this file except in compliance with the License.
491+ * You may obtain a copy of the License at
492+ *
493+ * http://www.apache.org/licenses/LICENSE-2.0
494+ *
495+ * Unless required by applicable law or agreed to in writing, software
496+ * distributed under the License is distributed on an "AS IS" BASIS,
497+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
498+ * See the License for the specific language governing permissions and
499+ * limitations under the License.
500+ * ============================================================ */
501+
502+
503+!function( $ ){
504+
505+ "use strict"
506+
507+ /* DROPDOWN CLASS DEFINITION
508+ * ========================= */
509+
510+ var toggle = '[data-toggle="dropdown"]'
511+ , Dropdown = function ( element ) {
512+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
513+ $('html').on('click.dropdown.data-api', function () {
514+ $el.parent().removeClass('open')
515+ })
516+ }
517+
518+ Dropdown.prototype = {
519+
520+ constructor: Dropdown
521+
522+ , toggle: function ( e ) {
523+ var $this = $(this)
524+ , selector = $this.attr('data-target')
525+ , $parent
526+ , isActive
527+
528+ if (!selector) {
529+ selector = $this.attr('href')
530+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
531+ }
532+
533+ $parent = $(selector)
534+ $parent.length || ($parent = $this.parent())
535+
536+ isActive = $parent.hasClass('open')
537+
538+ clearMenus()
539+ !isActive && $parent.toggleClass('open')
540+
541+ return false
542+ }
543+
544+ }
545+
546+ function clearMenus() {
547+ $(toggle).parent().removeClass('open')
548+ }
549+
550+
551+ /* DROPDOWN PLUGIN DEFINITION
552+ * ========================== */
553+
554+ $.fn.dropdown = function ( option ) {
555+ return this.each(function () {
556+ var $this = $(this)
557+ , data = $this.data('dropdown')
558+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
559+ if (typeof option == 'string') data[option].call($this)
560+ })
561+ }
562+
563+ $.fn.dropdown.Constructor = Dropdown
564+
565+
566+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
567+ * =================================== */
568+
569+ $(function () {
570+ $('html').on('click.dropdown.data-api', clearMenus)
571+ $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
572+ })
573+
574+}( window.jQuery );
575\ No newline at end of file
576
577=== added file 'project/static/src/js/project.js'
578--- project/static/src/js/project.js 1970-01-01 00:00:00 +0000
579+++ project/static/src/js/project.js 2012-04-10 16:40:13 +0000
580@@ -0,0 +1,71 @@
581+openerp.project = function(openerp) {
582+ openerp.web_kanban.ProjectKanban = openerp.web_kanban.KanbanRecord.include({
583+
584+ bind_events: function() {
585+ self = this;
586+ if(this.view.dataset.model == 'project.project') {
587+ //open dropdwon when click on the icon.
588+ $('.dropdown-toggle').dropdown();
589+
590+ //show and hide the dropdown icon when mouseover and mouseour.
591+ $('.oe_project_kanban_vignette').mouseover(function() {
592+ return $(this).find('.oe_project_kanban_action').show();
593+ }).mouseout(function() {
594+ return $(this).find('.oe_project_kanban_action').hide();
595+ });
596+
597+ //set avatar title for members.
598+ _.each($(this.$element).find('.project_avatar'),function(avatar){
599+ var dataset = new openerp.web.DataSetSearch(this, 'res.users', self.session.context, [['id','=',avatar.id]]);
600+ dataset.read_slice(['name']).then(function(result){
601+ avatar.setAttribute("title",result[0].name)
602+ });
603+ });
604+
605+ //if task is true , then open the task when click on the anywhere in the box.
606+ if(this.record.task.raw_value)$(this.$element).find('.click_button').attr('data-name','open_tasks');
607+ if(!this.record.task.raw_value)$(this.$element).find('.click_button').attr('data-name','dummy');
608+
609+ // set sequence like Tasks,Issues,Timesheets and Phases
610+ my_list = $("#list a")
611+ my_list.sort(function (a, b) {
612+ var aValue = parseInt(a.id);
613+ var bValue = parseInt(b.id);
614+ // ASC
615+ //return aValue == bValue ? 0 : aValue < bValue ? -1 : 1;
616+ // DESC
617+ return aValue == bValue ? 0 : aValue < bValue ? -1 : 1;
618+ });
619+ $('#list').replaceWith(my_list);
620+
621+ // set background color
622+ this.$element.find('.bgcolor_steelblue').click(function(){
623+ $(this).closest('li.oe_project_kanban_vignette').removeClass().addClass('oe_project_kanban_vignette ' + self.kanban_color(1));
624+ self.view.dataset.write(parseInt(this.id), {color:1});
625+ });
626+
627+ this.$element.find('.bgcolor_firebrick').click(function(){
628+ $(this).closest('li.oe_project_kanban_vignette').removeClass().addClass('oe_project_kanban_vignette ' + self.kanban_color(2));
629+ self.view.dataset.write(parseInt(this.id), {color:2});
630+ });
631+
632+ this.$element.find('.bgcolor_khaki').click(function(){
633+ $(this).closest('li.oe_project_kanban_vignette').removeClass().addClass('oe_project_kanban_vignette ' + self.kanban_color(3));
634+ self.view.dataset.write(parseInt(this.id), {color:3});
635+ });
636+
637+ this.$element.find('.bgcolor_thistle').click(function(){
638+ $(this).closest('li.oe_project_kanban_vignette').removeClass().addClass('oe_project_kanban_vignette ' + self.kanban_color(4));
639+ self.view.dataset.write(parseInt(this.id), {color:4});
640+ });
641+
642+ this.$element.find('.bgcolor_orange').click(function(){
643+ $(this).closest('li.oe_project_kanban_vignette').removeClass().addClass('oe_project_kanban_vignette ' + self.kanban_color(5));
644+ self.view.dataset.write(parseInt(this.id), {color:5});
645+ });
646+
647+ };
648+ self._super();
649+ }
650+ });
651+}
652
653=== modified file 'project_issue/__openerp__.py'
654--- project_issue/__openerp__.py 2012-03-14 12:32:06 +0000
655+++ project_issue/__openerp__.py 2012-04-10 16:40:13 +0000
656@@ -64,6 +64,7 @@
657 'installable': True,
658 'auto_install': False,
659 'application': True,
660+ 'js': ['static/src/js/project_issue.js'],
661 'certificate' : '001236490750848623845',
662 }
663
664
665=== modified file 'project_issue/project_issue.py'
666--- project_issue/project_issue.py 2012-04-03 17:21:08 +0000
667+++ project_issue/project_issue.py 2012-04-10 16:40:13 +0000
668@@ -222,6 +222,16 @@
669 }),
670 }
671
672+ def _get_project(self, cr, uid, context=None):
673+ user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
674+ if user.context_project_id:
675+ return user.context_project_id.id
676+ else:
677+ project_id = context.get('active_id',False)
678+ return project_id
679+
680+ def on_change_project(self, cr, uid, ids, project_id, context=None):
681+ return {}
682
683 _defaults = {
684 'active': 1,
685@@ -506,10 +516,47 @@
686
687 class project(osv.osv):
688 _inherit = "project.project"
689+
690+ def _compute_issue(self, cr, uid, ids, field_name, arg, context=None):
691+ res={}
692+ issue_pool=self.pool.get('project.issue')
693+ for project in self.browse(cr, uid, ids, context=context):
694+ issues = issue_pool.search(cr, uid, [('project_id','=',project.id)])
695+ res[project.id] = len(issues)
696+ return res
697+
698 _columns = {
699 '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)]}),
700- 'reply_to' : fields.char('Reply-To Email Address', size=256)
701- }
702+ 'reply_to' : fields.char('Reply-To Email Address', size=256),
703+ 'issues' : fields.boolean('Issues',help = "If you check this field issues are appears in kanban view"),
704+ 'total_issues': fields.function(_compute_issue , type='integer',string="Issue"),
705+ }
706+
707+ _defaults = {
708+ 'issues' : True,
709+ }
710+
711+ def open_issues(self, cr, uid, ids, context=None):
712+ #Open the View for the Tasks for the project
713+ """
714+ This opens Issues views
715+ @return :Dictionary value for issue view
716+ """
717+ if context is None:
718+ context = {}
719+ if ids:
720+ context = dict(context, search_default_project_id=ids[0])
721+ return {
722+ 'name': _('Issue'),
723+ 'view_type': 'form',
724+ 'view_mode': 'kanban,tree,calendar,form',
725+ 'res_model': 'project.issue',
726+ 'view_id': False,
727+ 'domain':[('project_id','in',ids)],
728+ 'context': context,
729+ 'type': 'ir.actions.act_window',
730+ 'nodestroy': True
731+ }
732
733 def _check_escalation(self, cr, uid, ids, context=None):
734 project_obj = self.browse(cr, uid, ids[0], context=context)
735
736=== modified file 'project_issue/project_issue_menu.xml'
737--- project_issue/project_issue_menu.xml 2012-04-05 16:55:29 +0000
738+++ project_issue/project_issue_menu.xml 2012-04-10 16:40:13 +0000
739@@ -54,6 +54,7 @@
740 view_mode="tree,form,calendar,graph"
741 view_type="form"/>
742
743+
744 <menuitem name="Issues" id="menu_project_issue_track" parent="project.menu_project_management"
745 action="project_issue_categ_act0" sequence="15"/>
746 </data>
747
748=== modified file 'project_issue/project_issue_view.xml'
749--- project_issue/project_issue_view.xml 2012-04-03 10:24:08 +0000
750+++ project_issue/project_issue_view.xml 2012-04-10 16:40:13 +0000
751@@ -343,12 +343,37 @@
752 <field name="type">form</field>
753 <field name="inherit_id" ref="project.edit_project"/>
754 <field name="arch" type="xml">
755+ <xpath expr="//field[@name='task']" position="after">
756+ <field name="issues"/>
757+ </xpath>
758 <field name="priority" position="before">
759 <field name="project_escalation_id"/>
760 <field name="reply_to"/>
761 </field>
762 </field>
763 </record>
764+
765+ <record id="view_project_kanban_inherited" model="ir.ui.view">
766+ <field name="name">project.project.kanban.inherited</field>
767+ <field name="model">project.project</field>
768+ <field name="type">kanban</field>
769+ <field name="inherit_id" ref="project.view_project_kanban"/>
770+ <field name="arch" type="xml">
771+ <field name="task" position="after">
772+ <field name="issues"/>
773+ <field name="total_issues" invisible="1"/>
774+ </field>
775+ <xpath expr="//h4[@id='list']" position="inside">
776+ <a id="2">
777+ <t t-if="record.issues.raw_value">
778+ <button name="open_issues" class="oe_project_buttons" type="object"><t t-if="record.total_issues.value &lt;= 1"> Issue</t><t t-if="record.total_issues.value > 1"> Issues</t>(<t t-esc="record.total_issues.value"/>)</button>
779+ </t>
780+ </a>
781+ </xpath>
782+ </field>
783+ </record>
784+
785+
786
787 </data>
788 </openerp>
789
790=== added file 'project_issue/static/src/img/issue_icon.png'
791Binary files project_issue/static/src/img/issue_icon.png 1970-01-01 00:00:00 +0000 and project_issue/static/src/img/issue_icon.png 2012-04-10 16:40:13 +0000 differ
792=== added directory 'project_issue/static/src/js'
793=== added file 'project_issue/static/src/js/project_issue.js'
794--- project_issue/static/src/js/project_issue.js 1970-01-01 00:00:00 +0000
795+++ project_issue/static/src/js/project_issue.js 2012-04-10 16:40:13 +0000
796@@ -0,0 +1,14 @@
797+openerp.project_issue = function(openerp) {
798+ openerp.web_kanban.ProjectIssueKanban = openerp.web_kanban.KanbanRecord.include({
799+ bind_events: function() {
800+ self = this;
801+ self._super();
802+ if(this.view.dataset.model == 'project.project') {
803+ if(this.record.task.raw_value && this.record.issues.raw_value)$(this.$element).find('.click_button').attr('data-name','open_tasks');
804+ if(!this.record.task.raw_value && this.record.issues.raw_value)$(this.$element).find('.click_button').attr('data-name','open_issues');
805+ //if(!this.record.task.raw_value)$(this.$element).find('.click_button').attr('data-name','dummy');
806+ };
807+
808+ }
809+ });
810+}
811
812=== modified file 'project_long_term/project_long_term.py'
813--- project_long_term/project_long_term.py 2012-01-31 13:36:57 +0000
814+++ project_long_term/project_long_term.py 2012-04-10 16:40:13 +0000
815@@ -123,6 +123,7 @@
816 _defaults = {
817 'state': 'draft',
818 'sequence': 10,
819+ 'project_id':lambda self, cr, uid, context: context.get('active_id',False),
820 'product_uom': lambda self,cr,uid,c: self.pool.get('product.uom').search(cr, uid, [('name', '=', _('Day'))], context=c)[0]
821 }
822 _order = "project_id, date_start, sequence"
823@@ -215,9 +216,46 @@
824
825 class project(osv.osv):
826 _inherit = "project.project"
827+
828+ def _open_phase(self, cr, uid, ids, field_name, arg, context=None):
829+ open_phase={}
830+ phase_pool=self.pool.get('project.phase')
831+ for id in ids:
832+ phase_ids = phase_pool.search(cr, uid, [('project_id', '=', id)])
833+ open_phase[id] = len(phase_ids)
834+ return open_phase
835+
836 _columns = {
837 'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
838- }
839+ 'phases' : fields.boolean('Phase',help = "If you check this field Phases are appears in kanban view"),
840+ 'open_phases' : fields.function(_open_phase , type='integer',string="Open Phases"),
841+
842+ }
843+ _defaults = {
844+ 'phases' : True,
845+ }
846+ def open_phase(self, cr, uid, ids, context=None):
847+ #Open the View for the Tasks for the project
848+ """
849+ This opens Tasks views
850+ @return :Dictionary value for task view
851+ """
852+ if context is None:
853+ context = {}
854+ if ids:
855+ context = dict(context, search_default_project_id=ids[0])
856+ return {
857+ 'name': _('Phase'),
858+ 'view_type': 'form',
859+ 'view_mode': 'tree,calendar,form',
860+ 'res_model': 'project.phase',
861+ 'view_id': False,
862+ 'domain':[('project_id','in',ids)],
863+ 'context': context,
864+ 'type': 'ir.actions.act_window',
865+ 'nodestroy': True
866+ }
867+
868 def schedule_phases(self, cr, uid, ids, context=None):
869 context = context or {}
870 if type(ids) in (long, int,):
871
872=== modified file 'project_long_term/project_long_term_view.xml'
873--- project_long_term/project_long_term_view.xml 2012-03-05 09:57:29 +0000
874+++ project_long_term/project_long_term_view.xml 2012-04-10 16:40:13 +0000
875@@ -98,6 +98,38 @@
876 # Project Phase
877 # ------------------------------------------------------
878
879+ <record id="project_phase_form" model="ir.ui.view">
880+ <field name="name">Inherit project form : Phase</field>
881+ <field name="model">project.project</field>
882+ <field name="type">form</field>
883+ <field name="inherit_id" ref="project.edit_project"/>
884+ <field name="arch" type="xml">
885+ <xpath expr="//field[@name='task']" position="after">
886+ <field name="phases"/>
887+ </xpath>
888+ </field>
889+ </record>
890+
891+ <record id="view_project_kanban_phase" model="ir.ui.view">
892+ <field name="name">project.project.kanban.inherited</field>
893+ <field name="model">project.project</field>
894+ <field name="type">kanban</field>
895+ <field name="inherit_id" ref="project.view_project_kanban"/>
896+ <field name="arch" type="xml">
897+ <field name="task" position="after">
898+ <field name="phases"/>
899+ <field name="open_phases"/>
900+ </field>
901+ <xpath expr="//h4[@id='list']" position="inside">
902+ <a id="4">
903+ <t t-if="record.phases.raw_value">
904+ <button name="open_phase" class="oe_project_buttons" type="object"><t t-if="record.open_phases.value &lt;= 1"> Phase</t><t t-if="record.open_phases.value > 1"> Phases</t>(<t t-esc="record.open_phases.value"/>)</button>
905+ </t>
906+ </a>
907+ </xpath>
908+ </field>
909+ </record>
910+
911 <record id="view_project_phase_form" model="ir.ui.view">
912 <field name="name">project.phase.form</field>
913 <field name="model">project.phase</field>
914
915=== added directory 'project_long_term/static'
916=== added directory 'project_long_term/static/src'
917=== added directory 'project_long_term/static/src/img'
918=== added file 'project_long_term/static/src/img/phases_icon.jpg'
919Binary files project_long_term/static/src/img/phases_icon.jpg 1970-01-01 00:00:00 +0000 and project_long_term/static/src/img/phases_icon.jpg 2012-04-10 16:40:13 +0000 differ
920=== modified file 'project_timesheet/__openerp__.py'
921--- project_timesheet/__openerp__.py 2012-01-31 13:36:57 +0000
922+++ project_timesheet/__openerp__.py 2012-04-10 16:40:13 +0000
923@@ -44,6 +44,7 @@
924 ],
925 'installable': True,
926 'auto_install': False,
927+ 'js': ['static/src/js/project_timesheet.js'],
928 'certificate': '0075123647453',
929 }
930 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
931
932=== modified file 'project_timesheet/project_timesheet.py'
933--- project_timesheet/project_timesheet.py 2012-01-31 13:36:57 +0000
934+++ project_timesheet/project_timesheet.py 2012-04-10 16:40:13 +0000
935@@ -29,6 +29,43 @@
936 class project_project(osv.osv):
937 _inherit = 'project.project'
938
939+ def _to_invoice(self, cr, uid, ids,field_name, arg, context=None):
940+ res = {}
941+ aal_pool = self.pool.get("account.analytic.line")
942+ for project in self.browse(cr,uid,ids,context=context):
943+ line_ids = aal_pool.search(cr, uid, [('account_id','=',project.analytic_account_id.id),('to_invoice','=',1),('invoice_id','=',False)])
944+ res[project.id] = {
945+ 'amt_to_invoice': 0.0,
946+ 'hrs_to_invoice': 0.0,
947+ }
948+ if line_ids:
949+ amt_to_invoice,hrs_to_invoice = 0.0,0.0
950+ for line in aal_pool.browse(cr,uid,line_ids,context=context):
951+ amt_to_invoice += line.amount
952+ hrs_to_invoice += line.unit_amount
953+ res[project.id]['amt_to_invoice'] = (amt_to_invoice)*-1
954+ res[project.id]['hrs_to_invoice'] = hrs_to_invoice
955+
956+ return res
957+
958+ def _compute_timesheet(self, cr, uid, ids, field_name, arg, context=None):
959+ res={}
960+ aal_pool=self.pool.get('account.analytic.line')
961+ for project in self.browse(cr, uid, ids, context=context):
962+ timesheet = aal_pool.search(cr, uid, [("account_id","=", project.analytic_account_id.id)])
963+ res[project.id] = len(timesheet)
964+ return res
965+
966+ _columns = {
967+ 'timesheets' : fields.boolean('Timesheets',help = "If you check this field timesheets appears in kanban view"),
968+ 'amt_to_invoice': fields.function(_to_invoice,string="Amount to Invoice",multi="sums"),
969+ 'hrs_to_invoice': fields.function(_to_invoice,string="Hours to Invoice",multi="sums"),
970+ 'total_timesheet': fields.function(_compute_timesheet , type='integer',string="Issue"),
971+ }
972+ _defaults = {
973+ 'timesheets' : True,
974+ }
975+
976 def onchange_partner_id(self, cr, uid, ids, part=False, context=None):
977 res = super(project_project, self).onchange_partner_id(cr, uid, ids, part, context)
978 if part and res and ('value' in res):
979@@ -40,6 +77,29 @@
980 res['value'].update({'to_invoice': factor_id})
981 return res
982
983+ def open_timesheets(self, cr, uid, ids, context=None):
984+ #Open the View for the Timesheet of the project
985+ """
986+ This opens Timesheets views
987+ @return :Dictionary value for timesheet view
988+ """
989+ if context is None:
990+ context = {}
991+ if ids:
992+ project = self.browse(cr, uid, ids[0], context=context)
993+ context = dict(context, search_default_account_id=project.analytic_account_id.id)
994+
995+ return {
996+ 'name': _('Bill Tasks Works'),
997+ 'context': context,
998+ 'view_type': 'form',
999+ 'view_mode': 'tree,form',
1000+ 'res_model': 'account.analytic.line',
1001+ 'view_id': False,
1002+ 'type': 'ir.actions.act_window',
1003+ 'nodestroy': True
1004+ }
1005+
1006 project_project()
1007
1008 class project_work(osv.osv):
1009
1010=== modified file 'project_timesheet/project_timesheet_view.xml'
1011--- project_timesheet/project_timesheet_view.xml 2012-04-03 08:27:56 +0000
1012+++ project_timesheet/project_timesheet_view.xml 2012-04-10 16:40:13 +0000
1013@@ -7,6 +7,12 @@
1014 <field name="type">form</field>
1015 <field name="inherit_id" ref="project.edit_project"/>
1016 <field name="arch" type="xml">
1017+ <xpath expr="//field[@name='task']" position='after'>
1018+ <field name="timesheets"/>
1019+ <field name="amt_to_invoice" invisible="True"/>
1020+ <field name="hrs_to_invoice" invisible="True"/>
1021+ </xpath>
1022+
1023 <field name="warn_customer" position="after">
1024 <group colspan="4" col="4">
1025 <separator colspan="4" string="Invoicing Data"/>
1026@@ -19,6 +25,42 @@
1027 </field>
1028 </record>
1029
1030+ <record id="view_project_kanban_inherited" model="ir.ui.view">
1031+ <field name="name">project.project.kanban.inherited</field>
1032+ <field name="model">project.project</field>
1033+ <field name="type">kanban</field>
1034+ <field name="inherit_id" ref="project.view_project_kanban"/>
1035+ <field name="arch" type="xml">
1036+ <field name="task" position="after">
1037+ <field name="timesheets"/>
1038+ <field name="total_timesheet"/>
1039+ <field name="currency_id"/>
1040+ </field>
1041+ <xpath expr="//h4[@id='list']" position="inside">
1042+ <a id="3">
1043+ <t t-if="record.timesheets.raw_value">
1044+ <button name="open_timesheets" class="oe_project_buttons" type="object"><t t-if="record.total_timesheet.value &lt;= 1"> Timesheet</t><t t-if="record.total_timesheet.value &gt; 1"> Timesheets</t>(<t t-esc="record.total_timesheet.value"/>)</button>
1045+ </t>
1046+ </a>
1047+ </xpath>
1048+
1049+ <xpath expr="//tr[@id='deadline']" position="before">
1050+ <tr >
1051+ <th align="left">To invoice</th>
1052+ <td align="left">
1053+ <field name="amt_to_invoice"/> <t t-esc="record.currency_id.raw_value[1].split(' ')[1][1]"/>
1054+ </td>
1055+ </tr>
1056+ <tr>
1057+ <th align="left">To hours</th>
1058+ <td align="left">
1059+ <field name="hrs_to_invoice"/> h
1060+ </td>
1061+ </tr>
1062+ </xpath>
1063+ </field>
1064+ </record>
1065+
1066 <record id="project_invoice_form_cutomer" model="ir.ui.view">
1067 <field name="name">Inherit project form : Customer</field>
1068 <field name="model">project.project</field>
1069
1070=== added directory 'project_timesheet/static'
1071=== added directory 'project_timesheet/static/src'
1072=== added directory 'project_timesheet/static/src/img'
1073=== added file 'project_timesheet/static/src/img/timesheet_icon.png'
1074Binary files project_timesheet/static/src/img/timesheet_icon.png 1970-01-01 00:00:00 +0000 and project_timesheet/static/src/img/timesheet_icon.png 2012-04-10 16:40:13 +0000 differ
1075=== added directory 'project_timesheet/static/src/js'
1076=== added file 'project_timesheet/static/src/js/project_timesheet.js'
1077--- project_timesheet/static/src/js/project_timesheet.js 1970-01-01 00:00:00 +0000
1078+++ project_timesheet/static/src/js/project_timesheet.js 2012-04-10 16:40:13 +0000
1079@@ -0,0 +1,21 @@
1080+openerp.project_timesheet = function(openerp) {
1081+ openerp.web_kanban.ProjectTimeSheetKanban = openerp.web_kanban.KanbanRecord.include({
1082+ bind_events: function() {
1083+ self = this;
1084+ self._super();
1085+ if(this.view.dataset.model == 'project.project') {
1086+ function include(arr, obj) {
1087+ for(var i=0; i<arr.length; i++) {
1088+ if (arr[i] == obj) return true;
1089+ }
1090+ }
1091+ if(include(this.view.fields_keys,"issues"))
1092+ {
1093+ if(!this.record.task.raw_value && !this.record.issues.raw_value && this.record.timesheets.raw_value)$(this.$element).find('.click_button').attr('data-name','open_timesheets');
1094+ //if(!this.record.task.raw_value)$(this.$element).find('.click_button').attr('data-name','dummy');
1095+ };
1096+ if(this.record.task.raw_value && this.record.timesheets.raw_value)$(this.$element).find('.click_button').attr('data-name','open_tasks');
1097+ };
1098+ }
1099+ });
1100+}

Subscribers

People subscribed via source and target branches

to all changes: