[IMP] website: create generic kanban view
bzr revid: chm@openerp.com-20130821160632-tsl5v1l5cj10w92c
This commit is contained in:
parent
98f19d8890
commit
b806728af1
|
@ -218,4 +218,8 @@ class Website(openerp.addons.web.controllers.main.Home):
|
||||||
|
|
||||||
return obj.website_published and "1" or "0"
|
return obj.website_published and "1" or "0"
|
||||||
|
|
||||||
|
@http.route(['/website/kanban/'], type='http', auth="public")
|
||||||
|
def kanban(self, **post):
|
||||||
|
return request.registry['website'].kanban_col(**post)
|
||||||
|
|
||||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -421,5 +421,125 @@
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template id="kanban">
|
||||||
|
<t t-set="step"><t t-esc="step or 0"/></t>
|
||||||
|
<t t-set="scope"><t t-esc="scope or 0"/></t>
|
||||||
|
<t t-set="orderby"><t t-esc="orderby or 'name'"/></t>
|
||||||
|
<t t-raw="snipped['kanban'](model, domain, column, content, step=step, scope=scope, orderby=orderby)"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="kanban_contain">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<t t-set="width" t-value="'%%s%%%%' % (100/len(objects))"/>
|
||||||
|
<t t-foreach="objects">
|
||||||
|
<th t-att-width="width">
|
||||||
|
<div t-field="column_id.name" class="text-center"/>
|
||||||
|
</th>
|
||||||
|
</t>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<t t-foreach="objects">
|
||||||
|
|
||||||
|
<t t-set="pager">
|
||||||
|
<div t-if="1 != page_end" class="pagination pagination-centered">
|
||||||
|
<ul>
|
||||||
|
<li t-attf-class="prev #{'active' if page == 1 else '' }" >
|
||||||
|
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page > 1 and page-1 or 1)) ">Prev</a>
|
||||||
|
</li>
|
||||||
|
<t t-foreach="range(page_start, page_end+1)" t-as="p">
|
||||||
|
<li t-att-class=" 'active' if page == p else '' ">
|
||||||
|
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, p)" t-esc="p"/>
|
||||||
|
</li>
|
||||||
|
</t>
|
||||||
|
<li t-attf-class="next #{'active' if page == page_end else '' }" >
|
||||||
|
<a t-att-href=" '%s,%s-%s' % (kanban_url, column_id.id, (page < page_end and page+1 or page_end) )">Next</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<td class="js_kanban_col"
|
||||||
|
t-att-data-content="content"
|
||||||
|
t-att-data-domain="domain"
|
||||||
|
t-att-data-page_count="page_count"
|
||||||
|
t-att-data-model="model"
|
||||||
|
t-att-data-step="step"
|
||||||
|
t-att-data-orderby="orderby">
|
||||||
|
<t t-raw="pager"/>
|
||||||
|
<div t-foreach="object_ids" t-as="object_id" class="thumbnail">
|
||||||
|
<t t-call="website_project.kanban_card"/>
|
||||||
|
</div>
|
||||||
|
<t t-raw="pager"/>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</t>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
$('.js_kanban_col').each(function () {
|
||||||
|
var $col = $(this);
|
||||||
|
var $pagination = $('.pagination', $col);
|
||||||
|
if(!$pagination.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var page_count = $col.data('page_count');
|
||||||
|
var scope = $pagination.first().find("li").size()-2;
|
||||||
|
var kanban_url_col = $pagination.find("li a:first").attr("href").replace(/[0-9]+$/, '');
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
'domain': $col.data('domain'),
|
||||||
|
'model': $col.data('model'),
|
||||||
|
'content': $col.data('content'),
|
||||||
|
'step': $col.data('step'),
|
||||||
|
'orderby': $col.data('orderby')
|
||||||
|
};
|
||||||
|
|
||||||
|
$pagination.on('click', 'a', function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
var $a = $(ev.target);
|
||||||
|
if($a.hasClass('active')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var page = +$a.attr("href").split(",").pop().split('-')[1];
|
||||||
|
data['page'] = page;
|
||||||
|
|
||||||
|
$.post('/website/kanban/', data, function (col) {
|
||||||
|
$col.find("> .thumbnail").remove();
|
||||||
|
$pagination.first().after('<div class="thumbnail">'+col+'</div>');
|
||||||
|
});
|
||||||
|
|
||||||
|
var page_start = page - parseInt(Math.floor((scope-1)/2));
|
||||||
|
if (page_start < 1 ) page_start = 1;
|
||||||
|
var page_end = page_start + (scope-1);
|
||||||
|
if (page_end > page_count ) page_end = page_count;
|
||||||
|
|
||||||
|
if (page_end - page_start < scope) {
|
||||||
|
page_start = page_end - scope > 0 ? page_end - scope : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pagination.find('li.prev a').attr("href", kanban_url_col+(page-1 > 0 ? page-1 : 1));
|
||||||
|
$pagination.find('li.next a').attr("href", kanban_url_col+(page+1));
|
||||||
|
for(var i=0; i < scope; i++) {
|
||||||
|
$pagination.find('li:not(.prev):not(.next):eq('+i+') a').attr("href", kanban_url_col+(page_start+i)).html(page_start+i);
|
||||||
|
}
|
||||||
|
$pagination.find('li.active').removeClass('active');
|
||||||
|
$pagination.find('li:has(a[href="'+kanban_url_col+page+'"])').addClass('active');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</openerp>
|
</openerp>
|
||||||
|
|
|
@ -9,6 +9,7 @@ from openerp.addons.web.http import request
|
||||||
import urllib
|
import urllib
|
||||||
import math
|
import math
|
||||||
import traceback
|
import traceback
|
||||||
|
from openerp.tools.safe_eval import safe_eval
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -63,6 +64,9 @@ class website(osv.osv):
|
||||||
'host_url': request.httprequest.host_url,
|
'host_url': request.httprequest.host_url,
|
||||||
'res_company': request.registry['res.company'].browse(request.cr, openerp.SUPERUSER_ID, 1),
|
'res_company': request.registry['res.company'].browse(request.cr, openerp.SUPERUSER_ID, 1),
|
||||||
'json': simplejson,
|
'json': simplejson,
|
||||||
|
'snipped': {
|
||||||
|
'kanban': self.kanban
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if additional_values:
|
if additional_values:
|
||||||
values.update(additional_values)
|
values.update(additional_values)
|
||||||
|
@ -75,10 +79,10 @@ class website(osv.osv):
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
return view.render(request.cr, request.uid, template, values, context=context)
|
return view.render(request.cr, request.uid, template, values, context=context)
|
||||||
except (osv.except_osv, orm.except_orm), err:
|
# except (osv.except_osv, orm.except_orm), err:
|
||||||
logger.error(err)
|
# logger.error(err)
|
||||||
values['error'] = err[1]
|
# values['error'] = err[1]
|
||||||
return self.render('website.401', values)
|
# return self.render('website.401', values)
|
||||||
# except ValueError:
|
# except ValueError:
|
||||||
# logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
|
# logger.error("Website Rendering Error.\n\n%s" % (traceback.format_exc()))
|
||||||
# return self.render('website.404', values)
|
# return self.render('website.404', values)
|
||||||
|
@ -146,6 +150,77 @@ class website(osv.osv):
|
||||||
if xids[view['id']]
|
if xids[view['id']]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def kanban(self, model, domain, column, content, step=None, scope=None, orderby=None):
|
||||||
|
step = step and int(step) or 10
|
||||||
|
scope = scope and int(scope) or 5
|
||||||
|
orderby = orderby or "name"
|
||||||
|
|
||||||
|
get_args = dict(request.httprequest.args or {})
|
||||||
|
model_obj = request.registry[model]
|
||||||
|
relation = model_obj._columns.get(column)._obj
|
||||||
|
relation_obj = request.registry[relation]
|
||||||
|
|
||||||
|
get_args.setdefault('kanban', "")
|
||||||
|
kanban = get_args.pop('kanban')
|
||||||
|
kanban_url = "?%s&kanban=" % urllib.urlencode(get_args)
|
||||||
|
|
||||||
|
pages = {}
|
||||||
|
for col in kanban.split(","):
|
||||||
|
if col:
|
||||||
|
col = col.split("-")
|
||||||
|
pages[int(col[0])] = int(col[1])
|
||||||
|
|
||||||
|
objects = []
|
||||||
|
for group in model_obj.read_group(request.cr, request.uid, domain, ["id", column], groupby=column):
|
||||||
|
obj = {}
|
||||||
|
|
||||||
|
# browse column
|
||||||
|
relation_id = group[column][0]
|
||||||
|
obj['column_id'] = relation_obj.browse(request.cr, request.uid, relation_id)
|
||||||
|
|
||||||
|
obj['kanban_url'] = kanban_url
|
||||||
|
for k, v in pages.items():
|
||||||
|
if k != relation_id:
|
||||||
|
obj['kanban_url'] += "%s-%s" % (k, v)
|
||||||
|
|
||||||
|
# pager
|
||||||
|
number = model_obj.search(request.cr, request.uid, group['__domain'], count=True)
|
||||||
|
obj['page'] = pages.get(relation_id) or 1
|
||||||
|
obj['page_count'] = int(math.ceil(float(number) / step))
|
||||||
|
offset = (obj['page']-1) * step
|
||||||
|
obj['page_start'] = max(obj['page'] - int(math.floor((scope-1)/2)), 1)
|
||||||
|
obj['page_end'] = min(obj['page_start'] + (scope-1), obj['page_count'])
|
||||||
|
|
||||||
|
# view data
|
||||||
|
obj['domain'] = group['__domain']
|
||||||
|
obj['model'] = model
|
||||||
|
obj['step'] = step
|
||||||
|
obj['orderby'] = orderby
|
||||||
|
|
||||||
|
# browse objects
|
||||||
|
object_ids = model_obj.search(request.cr, request.uid, group['__domain'], limit=step, offset=offset, order=orderby)
|
||||||
|
obj['object_ids'] = model_obj.browse(request.cr, request.uid, object_ids)
|
||||||
|
|
||||||
|
objects.append(obj)
|
||||||
|
|
||||||
|
values = self.get_rendering_context({
|
||||||
|
'objects': objects,
|
||||||
|
'range': range,
|
||||||
|
'content': content,
|
||||||
|
})
|
||||||
|
return self.render("website.kanban_contain", values)
|
||||||
|
|
||||||
|
def kanban_col(self, model, domain, page, content, step, orderby):
|
||||||
|
html = ""
|
||||||
|
model_obj = request.registry[model]
|
||||||
|
domain = safe_eval(domain)
|
||||||
|
step = int(step)
|
||||||
|
offset = (int(page)-1) * step
|
||||||
|
object_ids = model_obj.search(request.cr, request.uid, domain, limit=step, offset=offset, order=orderby)
|
||||||
|
object_ids = model_obj.browse(request.cr, request.uid, object_ids)
|
||||||
|
for object_id in object_ids:
|
||||||
|
html += self.render(content, self.get_rendering_context({'object_id': object_id}))
|
||||||
|
return html
|
||||||
|
|
||||||
class res_partner(osv.osv):
|
class res_partner(osv.osv):
|
||||||
_inherit = "res.partner"
|
_inherit = "res.partner"
|
||||||
|
|
|
@ -24,20 +24,10 @@ class website_project(http.Controller):
|
||||||
def blog(self, project_id=None, **post):
|
def blog(self, project_id=None, **post):
|
||||||
website = request.registry['website']
|
website = request.registry['website']
|
||||||
project_obj = request.registry['project.project']
|
project_obj = request.registry['project.project']
|
||||||
task_obj = request.registry['project.task']
|
|
||||||
stage_obj = request.registry['project.task.type']
|
|
||||||
|
|
||||||
project = project_obj.browse(request.cr, request.uid, project_id)
|
project = project_obj.browse(request.cr, request.uid, project_id)
|
||||||
|
|
||||||
domain = [('id', 'in', [task.id for task in project.tasks])]
|
|
||||||
stages = task_obj.read_group(request.cr, request.uid, domain, ["id", "stage_id"], groupby="stage_id")
|
|
||||||
for stage in stages:
|
|
||||||
stage['stage_id'] = stage_obj.browse(request.cr, request.uid, stage['stage_id'][0])
|
|
||||||
task_ids = task_obj.search(request.cr, request.uid, stage['__domain'])
|
|
||||||
stage['task_ids'] = task_obj.browse(request.cr, request.uid, task_ids)
|
|
||||||
|
|
||||||
values = website.get_rendering_context({
|
values = website.get_rendering_context({
|
||||||
'project_id': project,
|
'project_id': project,
|
||||||
'stages': stages,
|
|
||||||
})
|
})
|
||||||
return website.render("website_project.index", values)
|
return website.render("website_project.index", values)
|
||||||
|
|
|
@ -13,41 +13,34 @@
|
||||||
|
|
||||||
<!-- Page -->
|
<!-- Page -->
|
||||||
|
|
||||||
|
|
||||||
|
<template id="kanban_card" name="Project">
|
||||||
|
<a t-attf-href="/task/#{ object_id.id }/"><span t-field="object_id.name"/></a>
|
||||||
|
<div>
|
||||||
|
Assigned to <span t-field="object_id.user_id"/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span t-foreach="object_id.categ_ids" t-as="categ_id" class="label">
|
||||||
|
<t t-esc="categ_id.name"/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<small>
|
||||||
|
<i class="icon-time"></i> <span t-field="object_id.date_start"/><br/>
|
||||||
|
<t t-if="object_id.date_end">Ending Date: <span t-field="object_id.date_end"/></t>
|
||||||
|
</small>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="index" name="Project">
|
<template id="index" name="Project">
|
||||||
<t t-call="website.layout">
|
<t t-call="website.layout">
|
||||||
<t t-set="title">Project</t>
|
<t t-set="title">Project</t>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h4 t-field="project_id.name"/>
|
<h4 t-field="project_id.name"/>
|
||||||
<table class="table">
|
<t t-call="website.kanban">
|
||||||
<thead>
|
<t t-set="model">project.task</t>
|
||||||
<tr>
|
<t t-set="domain" t-value="[('project_id', '=', project_id.id)]"/>
|
||||||
<th t-foreach="stages">
|
<t t-set="column">stage_id</t>
|
||||||
<span t-field="stage_id.name"/>
|
<t t-set="content">website_project.kanban_card</t>
|
||||||
</th>
|
</t>
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td t-foreach="stages" t-as="stage">
|
|
||||||
<div t-foreach="stage['task_ids']" t-as="task" class="thumbnail">
|
|
||||||
<a t-attf-href="/task/#{ task.id }/"><span t-field="task.name"/></a>
|
|
||||||
<div>
|
|
||||||
Assigned to <span t-field="task.user_id"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span t-foreach="task.categ_ids" t-as="categ" class="label">
|
|
||||||
<t t-esc="categ.name"/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<small>
|
|
||||||
<i class="icon-time"></i> <span t-field="task.date_start"/><br/>
|
|
||||||
<t t-if="task.date_end">Ending Date: <span t-field="task.date_end"/></t>
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue