openerp-dev-web team mailing list archive
-
openerp-dev-web team
-
Mailing list archive
-
Message #00027
[Merge] lp:~openerp-dev-web/openobject-client-web/group_by into lp:~openerp-dev/openobject-client-web/trunk-dev-web
vda(Open ERP) has proposed merging lp:~openerp-dev-web/openobject-client-web/group_by into lp:~openerp-dev/openobject-client-web/trunk-dev-web.
Requested reviews:
OpenERP SA's Web Client R&D (openerp-dev-web)
Improved Group-by
(multiple group-by)
--
https://code.launchpad.net/~openerp-dev-web/openobject-client-web/group_by/+merge/25140
Your team OpenERP SA's Web Client R&D is requested to review the proposed merge of lp:~openerp-dev-web/openobject-client-web/group_by into lp:~openerp-dev/openobject-client-web/trunk-dev-web.
=== modified file 'addons/openerp/controllers/listgrid.py'
--- addons/openerp/controllers/listgrid.py 2010-05-10 12:50:52 +0000
+++ addons/openerp/controllers/listgrid.py 2010-05-12 11:20:48 +0000
@@ -28,7 +28,7 @@
###############################################################################
import cherrypy
from openerp.controllers import SecuredController
-from openerp.utils import rpc, TinyDict, TinyForm, TinyFormError, context_with_concurrency_info
+from openerp.utils import rpc, TinyDict, TinyForm, TinyFormError, context_with_concurrency_info, cache
from openerp.widgets import listgrid
import form
@@ -126,7 +126,22 @@
error = ustr(e)
return dict(error=error)
-
+
+ @expose()
+ def multiple_groupby(self, model, name, grp_domain, group_by, view_id, view_type, parent, padding, groups):
+ grp_domain = ast.literal_eval(grp_domain)
+ view = cache.fields_view_get(model, view_id, view_type, rpc.session.context.copy(), True, True)
+ group_by = ast.literal_eval(group_by)
+ domain = grp_domain
+ padding = ast.literal_eval(padding)
+ groups = ast.literal_eval(groups)
+ context = {'group_by_no_leaf': False, 'group_by': group_by, '__domain': domain}
+ args = {'editable': True, 'view_mode': ['tree', 'form', 'calendar', 'graph'], 'nolinks': 1, 'group_by_ctx': group_by, 'selectable': 2, 'multiple_group_by': True}
+
+ from openerp import widgets as tw
+ listgrp = tw.listgroup.MultipleGroup(name, model, view, ids=None, domain= domain, parent=parent, padding=padding, groups=groups, context=context, **args)
+ return listgrp.render()
+
@expose('json')
def get(self, **kw):
params, data = TinyDict.split(kw)
=== modified file 'addons/openerp/static/javascript/listgrid.js'
--- addons/openerp/static/javascript/listgrid.js 2010-05-06 06:24:46 +0000
+++ addons/openerp/static/javascript/listgrid.js 2010-05-12 11:20:48 +0000
@@ -308,6 +308,46 @@
this.sort_key_order = order;
}
},
+
+ group_by: function(id, record, group) {
+ var group_by_context = jQuery('[records="'+record+'"]').attr('grp_context');
+ var domain = jQuery('[records="'+record+'"]').attr('grp_domain');
+ var group_id = jQuery(group).attr('id').split('img_')[1];
+ var total_groups = jQuery('table[id="'+this.name+'"]').attr('groups')
+
+ if(group_by_context == '[]') {
+
+ if(jQuery('[records="'+record+'"]').attr('parent')) {
+ jQuery('[parent_grp_id="'+id+'"][id$="'+record+'"]').toggle()
+ }
+ else {
+ jQuery('[parent_grp_id="'+id+'"][id$="'+record+'"]').toggle()
+ }
+
+ jQuery(group).toggleClass('group_collapse',200)
+ }
+ else {
+ if(jQuery(group).attr('class').indexOf('collapse') < 0) {
+
+ jQuery.ajax({
+ url: '/listgrid/multiple_groupby',
+ type: 'POST',
+ data : {'model': this.model, 'name': this.name, 'grp_domain': domain, 'group_by': group_by_context, 'view_id': jQuery('#_terp_view_id').val(), 'view_type': jQuery('#_terp_view_type').val(), 'parent': record, 'padding': jQuery(group).parent().index()+1, 'groups': total_groups},
+ dataType: 'html',
+ success: function(xmlHttp) {
+ jQuery('[records="'+record+'"]').after(xmlHttp);
+ }
+ })
+
+ jQuery(group).toggleClass('group_collapse',200)
+ }
+ else {
+ jQuery('[parent="'+record+'"]').remove()
+ jQuery(group).toggleClass('group_collapse',200)
+ }
+ }
+
+ },
groupbyDrag: function(drag, drop) {
var view = jQuery('table.grid[id$=grid]').attr('id').split("_grid")[0];
=== modified file 'addons/openerp/static/javascript/search.js'
--- addons/openerp/static/javascript/search.js 2010-04-27 07:19:17 +0000
+++ addons/openerp/static/javascript/search.js 2010-05-12 11:20:48 +0000
@@ -256,6 +256,8 @@
});
}
+var group_by = new Array();
+
var search_filter = function(src, id) {
var all_domains = {};
var check_domain = 'None';
@@ -269,10 +271,16 @@
if(src.checked==false) {
src.checked = true
id.className = 'active_filter';
+ if(jQuery(src).attr('group_by_ctx')) {
+ group_by.push(jQuery(src).attr('group_by_ctx'))
+ }
}
else {
src.checked = false
id.className = 'inactive_filter';
+ group_by = jQuery.grep(group_by, function(grp) {
+ return grp != jQuery(src).attr('group_by_ctx');
+ })
}
}
var filter_table = $('filter_table');
@@ -304,13 +312,13 @@
if (box.id && box.checked && box.value != '[]') {
all_boxes = all_boxes.concat(box.value);
}
- if (box.id && box.checked && getNodeAttribute(box, 'group_by_ctx').length > 0) {
- group = getNodeAttribute(box, 'group_by_ctx');
- group_by_ctx = group_by_ctx.concat(group);
- }
+// if (box.id && box.checked && getNodeAttribute(box, 'group_by_ctx').length > 0) {
+// group = getNodeAttribute(box, 'group_by_ctx');
+// group_by_ctx = group_by_ctx.concat(group);
+// }
});
- openobject.dom.get('_terp_group_by_ctx').value = group_by_ctx;
+ openobject.dom.get('_terp_group_by_ctx').value = group_by;
checked_button = all_boxes.toString();
check_domain = checked_button.length > 0? checked_button.replace(/(]\,\[)/g, ', ') : 'None';
@@ -327,11 +335,11 @@
if (filter_table.style.display == 'none'){
filter_table.style.display = '';
}
- display_Customfilters(all_domains, group_by_ctx);
+ display_Customfilters(all_domains, group_by);
}
else {
custom_domain = fil_dom ? fil_dom.value : '[]';
- final_search_domain(custom_domain, all_domains, group_by_ctx);
+ final_search_domain(custom_domain, all_domains, group_by);
}
}
=== modified file 'addons/openerp/widgets/form/_form.py'
--- addons/openerp/widgets/form/_form.py 2010-04-21 14:22:43 +0000
+++ addons/openerp/widgets/form/_form.py 2010-05-12 11:20:48 +0000
@@ -644,7 +644,7 @@
def __init__(self, **attrs):
super(Group, self).__init__(**attrs)
- self.default = False
+ self.default = attrs.get('expand', False)
self.frame = Frame(**attrs)
self.nolabel = True
self.view_type = cherrypy.request.terp_params.get('_terp_view_type')
=== modified file 'addons/openerp/widgets/listgrid.py'
--- addons/openerp/widgets/listgrid.py 2010-05-10 09:05:26 +0000
+++ addons/openerp/widgets/listgrid.py 2010-05-12 11:20:48 +0000
@@ -82,8 +82,8 @@
self.context = context or {}
self.domain = domain or []
- custom_search_domain = cherrypy.request.custom_search_domain
- custom_filter_domain = cherrypy.request.custom_filter_domain
+ custom_search_domain = getattr(cherrypy.request, 'custom_search_domain', [])
+ custom_filter_domain = getattr(cherrypy.request, 'custom_filter_domain', [])
if name.endswith('/'):
self._name = name[:-1]
=== modified file 'addons/openerp/widgets/listgroup.py'
--- addons/openerp/widgets/listgroup.py 2010-05-06 13:14:37 +0000
+++ addons/openerp/widgets/listgroup.py 2010-05-12 11:20:48 +0000
@@ -33,6 +33,78 @@
from listgrid import List, CELLTYPES
+def parse(group_by, hiddens, headers, padding, groups):
+
+ for grp in range(len(group_by)):
+ if 'group_' in group_by[grp]:
+ group_by[grp] = group_by[grp].split("group_")[-1]
+
+ new_hidden = ()
+ for grp_by in groups:
+ for hidden in hiddens:
+ if grp_by == hidden[0]:
+ hiden = {}
+ for h in hidden[1]:
+ if h != 'invisible':
+ hiden[h] = hidden[1].get(h)
+ new_hidden = (grp_by, hiden)
+ if padding is None:
+ headers.insert(groups.index(grp_by), new_hidden)
+ else:
+ headers.insert(groups.index(grp_by), new_hidden)
+
+ if not new_hidden:
+ for grp_by in groups:
+ for cnt, header in enumerate(headers):
+ if header[0] == grp_by:
+ head = header
+ headers.pop(cnt)
+ if padding is None:
+ headers.insert(groups.index(grp_by), head)
+ else:
+ headers.insert(groups.index(grp_by), head)
+
+ return group_by, hiddens, headers
+
+def parse_groups(group_by, grp_records, headers, ids, model, offset, limit, context, data):
+ proxy = rpc.RPCProxy(model)
+ grouped = []
+ grp_ids = []
+ for grp in grp_records:
+ inner = {}
+ for key, head in headers:
+ if not isinstance(head, int):
+ kind = head.get('type')
+ if kind == 'progressbar':
+ inner[key] = CELLTYPES[kind](value=grp.get(key), **head)
+ grouped.append(inner)
+
+ if len(group_by) > 1:
+ child = False
+ else:
+ child = True
+
+ if grp_records:
+ for rec in grp_records:
+ for grp_by in group_by:
+ if not rec.get(grp_by):
+ rec[grp_by] = ''
+
+ rec_dom = rec.get('__domain')
+ dom = [('id', 'in', ids), rec_dom[0]]
+ ch_ids = []
+ if child:
+ grp_ids = proxy.search(dom, offset, limit, 0, context)
+ for id in grp_ids:
+ for d in data:
+ if d.get('id') == id:
+ ch_ids.append(d)
+ rec['child_rec'] = ch_ids
+ rec['group_id'] = 'group_' + str(random.randrange(1, 10000))
+ rec['group_by_id'] = group_by[0]+'_'+str(grp_records.index(rec))
+
+ return grouped, grp_ids
+
class ListGroup(List):
@@ -52,7 +124,7 @@
self.limit = kw.get('limit', 0)
self.count = kw.get('count', 0)
self.link = kw.get('nolinks')
-
+
proxy = rpc.RPCProxy(model)
if ids == None:
@@ -77,88 +149,88 @@
if not isinstance(self.group_by_ctx, list):
self.group_by_ctx = [self.group_by_ctx]
-
+
fields = view['fields']
self.grp_records = []
group_field = None
-
+
self.context.update(rpc.session.context.copy())
- grp = self.context.get('group_by', False)
- self.no_leaf = self.context.get('group_by_no_leaf', False)
- if self.no_leaf:
- self.editable = False
super(ListGroup, self).__init__(
name=name, model=model, view=view, ids=self.ids, domain=self.domain,
context=self.context, limit=self.limit, count=self.count,
offset=self.offset, editable=self.editable,
selectable=self.selectable)
-
- if self.group_by_ctx:
- t = []
- if self.group_by_ctx and isinstance(self.group_by_ctx[0], basestring):
- self.group_by_ctx = self.group_by_ctx[0].split(',')
-
- for i in self.group_by_ctx:
- if 'group_' in i:
- t.append((i.split('group_'))[1])
- else:
- t.append(i)
-
- gb = t[0]
- self.group_by_ctx = gb
-
- new_hidden = ()
- for hidden in self.hiddens:
- if gb == hidden[0]:
- hiden = {}
- for h in hidden[1]:
- if h != 'invisible':
- hiden[h] = hidden[1].get(h)
- new_hidden = (gb, hiden)
- self.headers.insert(0, new_hidden)
- if not new_hidden:
- for cnt, header in enumerate(self.headers):
- head = header
- if header[0] == gb:
- self.headers.pop(cnt)
- self.headers.insert(0, head)
-
- self.grp_records = proxy.read_group(self.context.get('__domain', []) + (self.domain or []),
- fields.keys(), gb, 0, False, self.context)
-
- self.grouped = []
-
- for grp in self.grp_records:
- inner = {}
- for key, head in self.headers:
- if not isinstance(head, int):
- kind = head.get('type')
- if kind == 'progressbar':
- inner[key] = CELLTYPES[kind](value=grp.get(key), **head)
- self.grouped.append(inner)
+
+ self.group_by_ctx, self.hiddens, self.headers = parse(self.group_by_ctx, self.hiddens, self.headers, None, self.group_by_ctx)
+
+ self.context['group_by'] = self.group_by_ctx
+
+
+ self.grp_records = proxy.read_group(self.context.get('__domain', []) + (self.domain or []),
+ fields.keys(), self.group_by_ctx, 0, False, self.context)
+
+ self.grouped, grp_ids = parse_groups(self.group_by_ctx, self.grp_records, self.headers, self.ids, model, self.offset, self.limit, self.context, self.data)
+
- grp_ids = []
+class MultipleGroup(List):
+
+ template = "templates/multiple_group.mako"
+ params = ['grp_records', 'group_by_ctx', 'grouped', 'parent', 'padding']
+
+ def __init__(self, name, model, view, ids=[], domain=[], parent=None, padding=0, groups = [], context={}, **kw):
+ self.context = context or {}
+ self.domain = domain or []
+
+ self.selectable = kw.get('selectable', 0)
+ self.editable = kw.get('editable', False)
+ self.pageable = kw.get('pageable', True)
+
+ self.offset = kw.get('offset', 0)
+ self.limit = kw.get('limit', 80)
+ self.count = kw.get('count', 0)
+ self.link = kw.get('nolinks')
+ self.parent = parent or None
+ self.padding = padding or 0
- if self.grp_records:
- for rec in self.grp_records:
- child = True
- if not rec.get(self.group_by_ctx):
- rec[self.group_by_ctx] = ''
-
- rec_dom = rec.get('__domain')
- dom = [('id', 'in', self.ids), rec_dom[0]]
- inner_gb = self.context.get('group_by', [])
- if self.no_leaf and not len(inner_gb):
- child = False
- ch_ids = []
- if child:
- grp_ids = proxy.search(dom, self.offset, self.limit, 0, self.context)
- for id in grp_ids:
- for d in self.data:
- if d.get('id') == id:
- ch_ids.append(d)
- rec['child_rec'] = ch_ids
- rec['group_id'] = 'group_' + str(random.randrange(1, 10000))
+ proxy = rpc.RPCProxy(model)
+ if ids == None:
+ if self.limit > 0:
+ ids = proxy.search(self.domain, self.offset, self.limit, 0, rpc.session.context.copy())
+ else:
+ ids = proxy.search(self.domain, 0, 0, 0, rpc.session.context.copy())
+
+ if len(ids) < self.limit:
+ self.count = len(ids)
+ else:
+ self.count = proxy.search_count(domain, rpc.session.context.copy())
+
+ if ids and not isinstance(ids, list):
+ ids = [ids]
+
+ self.ids = ids
+
+ self.concurrency_info = None
+
+ self.group_by_ctx = kw.get('group_by_ctx', [])
+
+ if not isinstance(self.group_by_ctx, list):
+ self.group_by_ctx = [self.group_by_ctx]
+
+ fields = view['fields']
+
+ self.grp_records = []
+ group_field = None
+ super(MultipleGroup, self).__init__(
+ name=name, model=model, view=view, ids=self.ids, domain=self.domain,
+ parent=parent, padding=padding, groups=groups, context=self.context, limit=self.limit,
+ count=self.count,offset=self.offset, editable=self.editable,
+ selectable=self.selectable)
+ self.group_by_ctx, self.hiddens, self.headers = parse(self.group_by_ctx, self.hiddens, self.headers, self.padding, groups)
+
+ self.grp_records = proxy.read_group(self.context.get('__domain', []),
+ fields.keys(), self.group_by_ctx, 0, False, self.context)
+
+ self.grouped, grp_ids = parse_groups(self.group_by_ctx, self.grp_records, self.headers, self.ids, model, self.offset, self.limit, rpc.session.context.copy(), self.data)
\ No newline at end of file
=== modified file 'addons/openerp/widgets/templates/listgroup.mako'
--- addons/openerp/widgets/templates/listgroup.mako 2010-04-09 13:06:28 +0000
+++ addons/openerp/widgets/templates/listgroup.mako 2010-05-12 11:20:48 +0000
@@ -3,7 +3,7 @@
background = '#DEDEDE'
%>
-<table id="${name}" class="gridview" width="100%" cellspacing="0" cellpadding="0">
+<table id="${name}" groups="${group_by_ctx}" class="gridview" width="100%" cellspacing="0" cellpadding="0">
% if pageable:
<tr class="pagerbar">
<td colspan="2" class="pagerbar-cell" align="right">${pager.display()}</td>
@@ -33,10 +33,10 @@
<tbody>
% for j, grp_row in enumerate(grp_records):
- <tr class="grid-row-group" records="${grp_row.get('group_id')}" style="cursor: pointer;" ch_records="${map(lambda x: x['id'],grp_row['child_rec'])}" grp_domain="${grp_row['__domain']}">
+ <tr class="grid-row-group" grp_by_id="${grp_row.get('group_by_id')}" records="${grp_row.get('group_id')}" style="cursor: pointer;" ch_records="${map(lambda x: x['id'],grp_row['child_rec'])}" grp_domain="${grp_row['__domain']}" grp_context="${grp_row['__context']['group_by']}">
% if editable:
<td class="grid-cell" style="background-color: ${background};">
- <img id="img_${grp_row.get('group_id')}" src="/openerp/static/images/treegrid/expand.gif" onclick="toggle_group_data('${grp_row.get('group_id')}');"></img>
+ <img id="img_${grp_row.get('group_id')}" class="group_expand" onclick="new ListView('${name}').group_by('${grp_row.get('group_by_id')}', '${grp_row.get('group_id')}', this)"></img>
</td>
% endif
@@ -65,7 +65,7 @@
</tr>
% for ch in grp_row.get('child_rec'):
- <tr class="grid-row-group" id="grid-row ${grp_row.get('group_id')}" record="${ch.get('id')}"
+ <tr class="grid-row-group" id="grid-row ${grp_row.get('group_id')}" parent_grp_id="${grp_row.get('group_by_id')}" record="${ch.get('id')}"
style="cursor: pointer; display: none;">
% if editable:
<td class="grid-cell">
=== added file 'addons/openerp/widgets/templates/multiple_group.mako'
--- addons/openerp/widgets/templates/multiple_group.mako 1970-01-01 00:00:00 +0000
+++ addons/openerp/widgets/templates/multiple_group.mako 2010-05-12 11:20:48 +0000
@@ -0,0 +1,67 @@
+<%!
+import itertools
+background = '#DEDEDE'
+%>
+% for j, grp_row in enumerate(grp_records):
+ <tr class="grid-row-group" parent="${parent}" grp_by_id="${grp_row.get('group_by_id')}" records="${grp_row.get('group_id')}" style="cursor: pointer;" ch_records="${map(lambda x: x['id'],grp_row['child_rec'])}" grp_domain="${grp_row['__domain']}" grp_context="${grp_row['__context']['group_by']}">
+ % if editable:
+ <td class="grid-cell" style="background-color: ${background};">
+ </td>
+ % endif
+ % for i, (field, field_attrs) in enumerate(headers):
+ % if field != 'button':
+ <td class="grid-cell ${field_attrs.get('type', 'char')}"
+ style="background-color: ${background};">
+ % if field_attrs.get('type') == 'progressbar':
+ <span>${grouped[j][field].display()}</span>
+ % else:
+ % if i == padding-1:
+ <img id="img_${grp_row.get('group_id')}" class="group_expand" onclick="new ListView('${name}').group_by('${grp_row.get('group_by_id')}', '${grp_row.get('group_id')}', this)"></img>
+ % else:
+ <span>${grp_row.get(field)}</span>
+ % endif
+ % endif
+ </td>
+ % else:
+ <td class="grid-cell button" nowrap="nowrap" style="background-color: ${background};">
+ <span></span>
+ </td>
+ % endif
+ % endfor
+ % if editable:
+ <td class="grid-cell selector" style="background-color: ${background};">
+ <div style="width: 0px;"></div>
+ </td>
+ % endif
+ </tr>
+ % for ch in grp_row.get('child_rec'):
+ <tr class="grid-row-group" id="grid-row ${grp_row.get('group_id')}" parent="${parent}" parent_grp_id="${grp_row.get('group_by_id')}" record="${ch.get('id')}"
+ style="cursor: pointer; display:none;">
+ % if editable:
+ <td class="grid-cell">
+ <img src="/openerp/static/images/listgrid/edit_inline.gif" class="listImage" border="0"
+ title="${_('Edit')}" onclick="editRecord(${ch.get('id')}, '${source}')"/>
+ </td>
+ % endif
+ % for i, (field, field_attrs) in enumerate(headers):
+ % if field != 'button':
+ <td class="grid-cell ${field_attrs.get('type', 'char')}"
+ style="padding-left: 15px; ${(ch.get(field).color or None) and 'color: ' + ch.get(field).color};"
+ sortable_value="${ch.get(field).get_sortable_text()}">
+ <span>${ch[field].display()}</span>
+ </td>
+ % else:
+ <td class="grid-cell button" nowrap="nowrap">
+ ${buttons[field_attrs-1].display(parent_grid=name, **buttons[field_attrs-1].params_from(ch))}
+ </td>
+ % endif
+ % endfor
+ % if editable:
+ <td class="grid-cell selector">
+ <img src="/openerp/static/images/listgrid/delete_inline.gif" class="listImage" border="0"
+ title="${_('Delete')}" onclick="new ListView('${name}').remove(${ch.get('id')})"/>
+ </td>
+ % endif
+ </tr>
+ % endfor
+% endfor
\ No newline at end of file
Follow ups