author | Aurelien Campeas <aurelien.campeas@logilab.fr> |
Fri, 16 Apr 2010 16:40:25 +0200 | |
branch | stable |
changeset 5312 | d2dbba898a96 |
parent 4618 | 412a9f1f5fd0 |
child 5328 | c51e8f62652a |
child 5377 | 84d14ddfae13 |
permissions | -rw-r--r-- |
0 | 1 |
"""generic table view, including filtering abilities |
2 |
||
3 |
||
4 |
:organization: Logilab |
|
4212
ab6573088b4a
update copyright: welcome 2010
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3842
diff
changeset
|
5 |
:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2. |
0 | 6 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
1977
606923dff11b
big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
1730
diff
changeset
|
7 |
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses |
0 | 8 |
""" |
9 |
__docformat__ = "restructuredtext en" |
|
10 |
||
11 |
from simplejson import dumps |
|
12 |
||
2312
af4d8f75c5db
use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2226
diff
changeset
|
13 |
from logilab.mtconverter import xml_escape |
0 | 14 |
|
1132 | 15 |
from cubicweb.selectors import nonempty_rset, match_form_params |
762 | 16 |
from cubicweb.utils import make_uid |
17 |
from cubicweb.view import EntityView, AnyRsetView |
|
4023
eae23c40627a
drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3890
diff
changeset
|
18 |
from cubicweb import tags |
eae23c40627a
drop common subpackage
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3890
diff
changeset
|
19 |
from cubicweb.uilib import toggle_action, limitsize, htmlescape |
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
20 |
from cubicweb.web import jsonize |
0 | 21 |
from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget, |
762 | 22 |
PopupBoxMenu, BoxLink) |
0 | 23 |
from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens |
24 |
||
25 |
class TableView(AnyRsetView): |
|
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
26 |
"""The table view accepts any non-empty rset. It uses |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
27 |
introspection on the result set to compute column names and the |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
28 |
proper way to display the cells. |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
29 |
It is however highly configurable and accepts a wealth of options. |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
30 |
""" |
3377
dd9d292b6a6d
use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3230
diff
changeset
|
31 |
__regid__ = 'table' |
0 | 32 |
title = _('table') |
33 |
finalview = 'final' |
|
497
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
34 |
|
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
35 |
def form_filter(self, divid, displaycols, displayactions, displayfilter, |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
36 |
hidden=True): |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
37 |
rqlst = self.cw_rset.syntax_tree() |
497
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
38 |
# union not yet supported |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
39 |
if len(rqlst.children) != 1: |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
40 |
return () |
4616
2f296c34aec4
fix table view facet retreival, necessary since 95ccd84c892b. Also some cleanup in facet box
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
41 |
rqlst = rqlst.copy() |
2f296c34aec4
fix table view facet retreival, necessary since 95ccd84c892b. Also some cleanup in facet box
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4252
diff
changeset
|
42 |
self._cw.vreg.rqlhelper.annotate(rqlst) |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
43 |
mainvar, baserql = prepare_facets_rqlst(rqlst, self.cw_rset.args) |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
44 |
wdgs = [facet.get_widget() for facet in self._cw.vreg['facets'].poss_visible_objects( |
4618
412a9f1f5fd0
[facet] rqlst should be the select node
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
4617
diff
changeset
|
45 |
self._cw, rset=self.cw_rset, rqlst=rqlst.children[0], context='tablefilter', |
521
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
46 |
filtered_variable=mainvar)] |
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
47 |
wdgs = [wdg for wdg in wdgs if wdg is not None] |
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
48 |
if wdgs: |
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
49 |
self._generate_form(divid, baserql, wdgs, hidden, |
497
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
50 |
vidargs={'displaycols': displaycols, |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
51 |
'displayactions': displayactions, |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
52 |
'displayfilter': displayfilter}) |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
53 |
return self.show_hide_actions(divid, not hidden) |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
54 |
return () |
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
55 |
|
521
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
56 |
def _generate_form(self, divid, baserql, fwidgets, hidden=True, vidargs={}): |
0 | 57 |
"""display a form to filter table's content. This should only |
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
58 |
occur when a context eid is given |
0 | 59 |
""" |
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
60 |
w = self.w |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
61 |
self._cw.add_css('cubicweb.facets.css') |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
62 |
self._cw.add_js( ('cubicweb.ajax.js', 'cubicweb.facets.js')) |
0 | 63 |
# drop False / None values from vidargs |
64 |
vidargs = dict((k, v) for k, v in vidargs.iteritems() if v) |
|
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
65 |
w(u'<form method="post" cubicweb:facetargs="%s" action="">' % |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
66 |
xml_escape(dumps([divid, 'table', False, vidargs]))) |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
67 |
w(u'<fieldset id="%sForm" class="%s">' % (divid, hidden and 'hidden' or '')) |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
68 |
w(u'<input type="hidden" name="divid" value="%s" />' % divid) |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
69 |
w(u'<input type="hidden" name="fromformfilter" value="1" />') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
70 |
filter_hiddens(w, facets=','.join(wdg.facet.__regid__ for wdg in fwidgets), |
3129
fab471bee6c1
[facets] duhh, necessary fromformfilter hidden was missing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3128
diff
changeset
|
71 |
baserql=baserql) |
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
72 |
w(u'<table class="filter">\n') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
73 |
w(u'<tr>\n') |
521
b3430af22580
fix table filter form: get_widget shouldn't be called once rqlst has been recovered
sylvain.thenault@logilab.fr
parents:
513
diff
changeset
|
74 |
for wdg in fwidgets: |
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
75 |
w(u'<td>') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
76 |
wdg.render(w=w) |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
77 |
w(u'</td>\n') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
78 |
w(u'</tr>\n') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
79 |
w(u'</table>\n') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
80 |
w(u'</fieldset>\n') |
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
81 |
w(u'</form>\n') |
0 | 82 |
|
83 |
def main_var_index(self): |
|
84 |
"""returns the index of the first non-attribute variable among the RQL |
|
85 |
selected variables |
|
86 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
87 |
eschema = self._cw.vreg.schema.eschema |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
88 |
for i, etype in enumerate(self.cw_rset.description[0]): |
0 | 89 |
try: |
3689
deb13e88e037
follow yams 0.25 api changes to improve performance
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3228
diff
changeset
|
90 |
if not eschema(etype).final: |
0 | 91 |
return i |
92 |
except KeyError: # XXX possible? |
|
93 |
continue |
|
94 |
return None |
|
95 |
||
96 |
def displaycols(self, displaycols): |
|
97 |
if displaycols is None: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
98 |
if 'displaycols' in self._cw.form: |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
99 |
displaycols = [int(idx) for idx in self._cw.form['displaycols']] |
0 | 100 |
else: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
101 |
displaycols = range(len(self.cw_rset.syntax_tree().children[0].selection)) |
0 | 102 |
return displaycols |
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
103 |
|
0 | 104 |
def call(self, title=None, subvid=None, displayfilter=None, headers=None, |
469 | 105 |
displaycols=None, displayactions=None, actions=(), divid=None, |
2226
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
106 |
cellvids=None, cellattrs=None, mainindex=None): |
5312
d2dbba898a96
[doc/book] misc on views, docstrings
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
4618
diff
changeset
|
107 |
"""Produces a table displaying a composite query |
0 | 108 |
|
109 |
:param title: title added before table |
|
110 |
:param subvid: cell view |
|
111 |
:param displayfilter: filter that selects rows to display |
|
112 |
:param headers: columns' titles |
|
113 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
114 |
req = self._cw |
0 | 115 |
req.add_js('jquery.tablesorter.js') |
853
4f6cd02bd71f
Use specific css files directly in views code
Julien Jehannet <julien.jehannet@logilab.fr>
parents:
527
diff
changeset
|
116 |
req.add_css(('cubicweb.tablesorter.css', 'cubicweb.tableview.css')) |
2226
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
117 |
# compute label first since the filter form may remove some necessary |
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
118 |
# information from the rql syntax tree |
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
119 |
if mainindex is None: |
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
120 |
mainindex = self.main_var_index() |
2206
009e2856afcb
columns_labels is an AnyRsetView method...
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2204
diff
changeset
|
121 |
computed_labels = self.columns_labels(mainindex) |
0 | 122 |
hidden = True |
123 |
if not subvid and 'subvid' in req.form: |
|
124 |
subvid = req.form.pop('subvid') |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
125 |
divid = divid or req.form.get('divid') or 'rs%s' % make_uid(id(self.cw_rset)) |
0 | 126 |
actions = list(actions) |
127 |
if mainindex is None: |
|
128 |
displayfilter, displayactions = False, False |
|
129 |
else: |
|
130 |
if displayfilter is None and 'displayfilter' in req.form: |
|
131 |
displayfilter = True |
|
132 |
if req.form['displayfilter'] == 'shown': |
|
133 |
hidden = False |
|
134 |
if displayactions is None and 'displayactions' in req.form: |
|
135 |
displayactions = True |
|
136 |
displaycols = self.displaycols(displaycols) |
|
137 |
fromformfilter = 'fromformfilter' in req.form |
|
138 |
# if fromformfilter is true, this is an ajax call and we only want to |
|
139 |
# replace the inner div, so don't regenerate everything under the if |
|
140 |
# below |
|
141 |
if not fromformfilter: |
|
3009 | 142 |
self.w(u'<div class="section">') |
0 | 143 |
if not title and 'title' in req.form: |
144 |
title = req.form['title'] |
|
145 |
if title: |
|
146 |
self.w(u'<h2 class="tableTitle">%s</h2>\n' % title) |
|
147 |
if displayfilter: |
|
497
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
148 |
actions += self.form_filter(divid, displaycols, displayfilter, |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
149 |
displayactions) |
0 | 150 |
elif displayfilter: |
151 |
actions += self.show_hide_actions(divid, True) |
|
152 |
self.w(u'<div id="%s"' % divid) |
|
153 |
if displayactions: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
154 |
actionsbycat = self._cw.vreg['actions'].possible_actions(req, self.cw_rset) |
3228
7b05b2709439
[actions] refactor: extract actual_actions from fill_menu to work with table filter form
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3129
diff
changeset
|
155 |
for action in actionsbycat.get('mainactions', ()): |
7b05b2709439
[actions] refactor: extract actual_actions from fill_menu to work with table filter form
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3129
diff
changeset
|
156 |
for action in action.actual_actions(): |
7b05b2709439
[actions] refactor: extract actual_actions from fill_menu to work with table filter form
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3129
diff
changeset
|
157 |
actions.append( (action.url(), req._(action.title), |
7b05b2709439
[actions] refactor: extract actual_actions from fill_menu to work with table filter form
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3129
diff
changeset
|
158 |
action.html_class(), None) ) |
0 | 159 |
self.w(u' cubicweb:displayactions="1">') # close <div tag |
160 |
else: |
|
161 |
self.w(u'>') # close <div tag |
|
162 |
# render actions menu |
|
163 |
if actions: |
|
164 |
self.render_actions(divid, actions) |
|
165 |
# render table |
|
166 |
table = TableWidget(self) |
|
2204
3472c5498478
use column_labels instead of rqlst.get_description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2115
diff
changeset
|
167 |
for column in self.get_columns(computed_labels, displaycols, headers, |
3472c5498478
use column_labels instead of rqlst.get_description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2115
diff
changeset
|
168 |
subvid, cellvids, cellattrs, mainindex): |
0 | 169 |
table.append_column(column) |
170 |
table.render(self.w) |
|
171 |
self.w(u'</div>\n') |
|
172 |
if not fromformfilter: |
|
173 |
self.w(u'</div>\n') |
|
174 |
||
175 |
def show_hide_actions(self, divid, currentlydisplayed=False): |
|
176 |
showhide = u';'.join(toggle_action('%s%s' % (divid, what))[11:] |
|
177 |
for what in ('Form', 'Show', 'Hide', 'Actions')) |
|
178 |
showhide = 'javascript:' + showhide |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
179 |
showlabel = self._cw._('show filter form') |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
180 |
hidelabel = self._cw._('hide filter form') |
0 | 181 |
if currentlydisplayed: |
182 |
return [(showhide, showlabel, 'hidden', '%sShow' % divid), |
|
183 |
(showhide, hidelabel, None, '%sHide' % divid)] |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
184 |
return [(showhide, showlabel, None, '%sShow' % divid), |
0 | 185 |
(showhide, hidelabel, 'hidden', '%sHide' % divid)] |
186 |
||
187 |
def render_actions(self, divid, actions): |
|
188 |
box = MenuWidget('', 'tableActionsBox', _class='', islist=False) |
|
3890
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
189 |
label = tags.img(src=self._cw.external_resource('PUCE_DOWN'), |
d7a270f50f54
backport stable branch (one more time painfully)
Sylvain Thénault <sylvain.thenault@logilab.fr>
diff
changeset
|
190 |
alt=xml_escape(self._cw._('action(s) on this selection'))) |
0 | 191 |
menu = PopupBoxMenu(label, isitem=False, link_class='actionsBox', |
192 |
ident='%sActions' % divid) |
|
193 |
box.append(menu) |
|
194 |
for url, label, klass, ident in actions: |
|
195 |
menu.append(BoxLink(url, label, klass, ident=ident, escape=True)) |
|
196 |
box.render(w=self.w) |
|
197 |
self.w(u'<div class="clear"/>') |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
198 |
|
2204
3472c5498478
use column_labels instead of rqlst.get_description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2115
diff
changeset
|
199 |
def get_columns(self, computed_labels, displaycols, headers, subvid, |
3472c5498478
use column_labels instead of rqlst.get_description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2115
diff
changeset
|
200 |
cellvids, cellattrs, mainindex): |
0 | 201 |
columns = [] |
3729
e4f20b74af51
remove some warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3720
diff
changeset
|
202 |
eschema = self._cw.vreg.schema.eschema |
2204
3472c5498478
use column_labels instead of rqlst.get_description
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2115
diff
changeset
|
203 |
for colindex, label in enumerate(computed_labels): |
0 | 204 |
if colindex not in displaycols: |
205 |
continue |
|
206 |
# compute column header |
|
207 |
if headers is not None: |
|
208 |
label = headers[displaycols.index(colindex)] |
|
209 |
if colindex == mainindex: |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
210 |
label += ' (%s)' % self.cw_rset.rowcount |
0 | 211 |
column = TableColumn(label, colindex) |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
212 |
coltype = self.cw_rset.description[0][colindex] |
0 | 213 |
# compute column cell view (if coltype is None, it's a left outer |
214 |
# join, use the default non final subvid) |
|
215 |
if cellvids and colindex in cellvids: |
|
216 |
column.append_renderer(cellvids[colindex], colindex) |
|
3729
e4f20b74af51
remove some warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3720
diff
changeset
|
217 |
elif coltype is not None and eschema(coltype).final: |
0 | 218 |
column.append_renderer(self.finalview, colindex) |
219 |
else: |
|
220 |
column.append_renderer(subvid or 'incontext', colindex) |
|
221 |
if cellattrs and colindex in cellattrs: |
|
222 |
for name, value in cellattrs[colindex].iteritems(): |
|
1138
22f634977c95
make pylint happy, fix some bugs on the way
sylvain.thenault@logilab.fr
parents:
1132
diff
changeset
|
223 |
column.add_attr(name, value) |
0 | 224 |
# add column |
225 |
columns.append(column) |
|
226 |
return columns |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
227 |
|
0 | 228 |
|
1730
cec526a96535
fix 'render' method name conflict
sylvain.thenault@logilab.fr
parents:
1635
diff
changeset
|
229 |
def render_cell(self, cellvid, row, col, w): |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
230 |
self._cw.view('cell', self.cw_rset, row=row, col=col, cellvid=cellvid, w=w) |
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
231 |
|
0 | 232 |
def get_rows(self): |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
233 |
return self.cw_rset |
0 | 234 |
|
235 |
@htmlescape |
|
236 |
@jsonize |
|
237 |
@limitsize(10) |
|
238 |
def sortvalue(self, row, col): |
|
239 |
# XXX it might be interesting to try to limit value's |
|
240 |
# length as much as possible (e.g. by returning the 10 |
|
241 |
# first characters of a string) |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
242 |
val = self.cw_rset[row][col] |
0 | 243 |
if val is None: |
244 |
return u'' |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
245 |
etype = self.cw_rset.description[row][col] |
3729
e4f20b74af51
remove some warnings
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3720
diff
changeset
|
246 |
if self._cw.vreg.schema.eschema(etype).final: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
247 |
entity, rtype = self.cw_rset.related_entity(row, col) |
0 | 248 |
if entity is None: |
249 |
return val # remove_html_tags() ? |
|
250 |
return entity.sortvalue(rtype) |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
251 |
entity = self.cw_rset.get_entity(row, col) |
0 | 252 |
return entity.sortvalue() |
253 |
||
843 | 254 |
|
0 | 255 |
class EditableTableView(TableView): |
3377
dd9d292b6a6d
use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3230
diff
changeset
|
256 |
__regid__ = 'editable-table' |
0 | 257 |
finalview = 'editable-final' |
258 |
title = _('editable-table') |
|
259 |
||
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
260 |
|
0 | 261 |
class CellView(EntityView): |
3377
dd9d292b6a6d
use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3230
diff
changeset
|
262 |
__regid__ = 'cell' |
742
99115e029dca
replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
692
diff
changeset
|
263 |
__select__ = nonempty_rset() |
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
264 |
|
0 | 265 |
def cell_call(self, row, col, cellvid=None): |
266 |
""" |
|
267 |
:param row, col: indexes locating the cell value in view's result set |
|
268 |
:param cellvid: cell view (defaults to 'outofcontext') |
|
269 |
""" |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
270 |
etype, val = self.cw_rset.description[row][col], self.cw_rset[row][col] |
4045
f4a52abb6f4f
cw 3.6 api update
Sandrine Ribeau <sandrine.ribeau@logilab.fr>
parents:
4023
diff
changeset
|
271 |
if val is not None and not self._cw.vreg.schema.eschema(etype).final: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
272 |
e = self.cw_rset.get_entity(row, col) |
0 | 273 |
e.view(cellvid or 'outofcontext', w=self.w) |
274 |
elif val is None: |
|
275 |
# This is usually caused by a left outer join and in that case, |
|
276 |
# regular views will most certainly fail if they don't have |
|
277 |
# a real eid |
|
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
278 |
self.wview('final', self.cw_rset, row=row, col=col) |
0 | 279 |
else: |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
280 |
self.wview(cellvid or 'final', self.cw_rset, 'null', row=row, col=col) |
0 | 281 |
|
282 |
||
283 |
class InitialTableView(TableView): |
|
284 |
"""same display as table view but consider two rql queries : |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
285 |
|
0 | 286 |
* the default query (ie `rql` form parameter), which is only used to select |
287 |
this view and to build the filter form. This query should have the same |
|
288 |
structure as the actual without actual restriction (but link to |
|
289 |
restriction variables) and usually with a limit for efficiency (limit set |
|
290 |
to 2 is advised) |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
291 |
|
0 | 292 |
* the actual query (`actualrql` form parameter) whose results will be |
293 |
displayed with default restrictions set |
|
294 |
""" |
|
3377
dd9d292b6a6d
use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3230
diff
changeset
|
295 |
__regid__ = 'initialtable' |
742
99115e029dca
replaced most of __selectors__ assignments with __select__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
692
diff
changeset
|
296 |
__select__ = nonempty_rset() & match_form_params('actualrql') |
0 | 297 |
# should not be displayed in possible view since it expects some specific |
298 |
# parameters |
|
299 |
title = None |
|
1635
866563e2d0fc
don't depends on simplejson outside web/
sylvain.thenault@logilab.fr
parents:
1370
diff
changeset
|
300 |
|
469 | 301 |
def call(self, title=None, subvid=None, headers=None, divid=None, |
2226
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
302 |
displaycols=None, displayactions=None, mainindex=None): |
0 | 303 |
"""Dumps a table displaying a composite query""" |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
304 |
actrql = self._cw.form['actualrql'] |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
305 |
self._cw.ensure_ro_rql(actrql) |
0 | 306 |
displaycols = self.displaycols(displaycols) |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
307 |
if displayactions is None and 'displayactions' in self._cw.form: |
0 | 308 |
displayactions = True |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
309 |
if divid is None and 'divid' in self._cw.form: |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
310 |
divid = self._cw.form['divid'] |
0 | 311 |
self.w(u'<div class="section">') |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
312 |
if not title and 'title' in self._cw.form: |
0 | 313 |
# pop title so it's not displayed by the table view as well |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
314 |
title = self._cw.form.pop('title') |
0 | 315 |
if title: |
316 |
self.w(u'<h2>%s</h2>\n' % title) |
|
2226
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
317 |
if mainindex is None: |
f5216e540168
allow to specify mainindex
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
2206
diff
changeset
|
318 |
mainindex = self.main_var_index() |
0 | 319 |
if mainindex is not None: |
497
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
320 |
actions = self.form_filter(divid, displaycols, displayactions, True) |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
321 |
else: |
68d4211518c5
refactor table views to share more code and to avoid empty filter table in some case
sylvain.thenault@logilab.fr
parents:
469
diff
changeset
|
322 |
actions = () |
3451
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
323 |
if not subvid and 'subvid' in self._cw.form: |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
324 |
subvid = self._cw.form.pop('subvid') |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
325 |
self._cw.view('table', self._cw.execute(actrql), |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
326 |
'noresult', w=self.w, displayfilter=False, subvid=subvid, |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
327 |
displayactions=displayactions, displaycols=displaycols, |
6b46d73823f5
[api] work in progress, use __regid__, cw_*, etc.
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
3377
diff
changeset
|
328 |
actions=actions, headers=headers, divid=divid) |
0 | 329 |
self.w(u'</div>\n') |
330 |
||
331 |
||
527 | 332 |
class EditableInitialTableTableView(InitialTableView): |
3377
dd9d292b6a6d
use __regid__ instead of id on appobject classes
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents:
3230
diff
changeset
|
333 |
__regid__ = 'editable-initialtable' |
0 | 334 |
finalview = 'editable-final' |