12 from logilab.mtconverter import html_escape |
12 from logilab.mtconverter import html_escape |
13 |
13 |
14 from cubicweb.selectors import nonempty_rset, match_form_params |
14 from cubicweb.selectors import nonempty_rset, match_form_params |
15 from cubicweb.utils import make_uid |
15 from cubicweb.utils import make_uid |
16 from cubicweb.view import EntityView, AnyRsetView |
16 from cubicweb.view import EntityView, AnyRsetView |
17 from cubicweb.common.uilib import toggle_action, limitsize, jsonize, htmlescape |
17 from cubicweb.common.uilib import toggle_action, limitsize, htmlescape |
|
18 from cubicweb.web import jsonize |
18 from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget, |
19 from cubicweb.web.htmlwidgets import (TableWidget, TableColumn, MenuWidget, |
19 PopupBoxMenu, BoxLink) |
20 PopupBoxMenu, BoxLink) |
20 from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens |
21 from cubicweb.web.facet import prepare_facets_rqlst, filter_hiddens |
21 |
22 |
22 class TableView(AnyRsetView): |
23 class TableView(AnyRsetView): |
42 vidargs={'displaycols': displaycols, |
43 vidargs={'displaycols': displaycols, |
43 'displayactions': displayactions, |
44 'displayactions': displayactions, |
44 'displayfilter': displayfilter}) |
45 'displayfilter': displayfilter}) |
45 return self.show_hide_actions(divid, not hidden) |
46 return self.show_hide_actions(divid, not hidden) |
46 return () |
47 return () |
47 |
48 |
48 def _generate_form(self, divid, baserql, fwidgets, hidden=True, vidargs={}): |
49 def _generate_form(self, divid, baserql, fwidgets, hidden=True, vidargs={}): |
49 """display a form to filter table's content. This should only |
50 """display a form to filter table's content. This should only |
50 occurs when a context eid is given |
51 occurs when a context eid is given |
51 """ |
52 """ |
52 self.req.add_js( ('cubicweb.ajax.js', 'cubicweb.formfilter.js')) |
53 self.req.add_js( ('cubicweb.ajax.js', 'cubicweb.formfilter.js')) |
86 if 'displaycols' in self.req.form: |
87 if 'displaycols' in self.req.form: |
87 displaycols = [int(idx) for idx in self.req.form['displaycols']] |
88 displaycols = [int(idx) for idx in self.req.form['displaycols']] |
88 else: |
89 else: |
89 displaycols = range(len(self.rset.syntax_tree().children[0].selection)) |
90 displaycols = range(len(self.rset.syntax_tree().children[0].selection)) |
90 return displaycols |
91 return displaycols |
91 |
92 |
92 def call(self, title=None, subvid=None, displayfilter=None, headers=None, |
93 def call(self, title=None, subvid=None, displayfilter=None, headers=None, |
93 displaycols=None, displayactions=None, actions=(), divid=None, |
94 displaycols=None, displayactions=None, actions=(), divid=None, |
94 cellvids=None, cellattrs=None): |
95 cellvids=None, cellattrs=None): |
95 """Dumps a table displaying a composite query |
96 """Dumps a table displaying a composite query |
96 |
97 |
167 showlabel = self.req._('show filter form') |
168 showlabel = self.req._('show filter form') |
168 hidelabel = self.req._('hide filter form') |
169 hidelabel = self.req._('hide filter form') |
169 if currentlydisplayed: |
170 if currentlydisplayed: |
170 return [(showhide, showlabel, 'hidden', '%sShow' % divid), |
171 return [(showhide, showlabel, 'hidden', '%sShow' % divid), |
171 (showhide, hidelabel, None, '%sHide' % divid)] |
172 (showhide, hidelabel, None, '%sHide' % divid)] |
172 return [(showhide, showlabel, None, '%sShow' % divid), |
173 return [(showhide, showlabel, None, '%sShow' % divid), |
173 (showhide, hidelabel, 'hidden', '%sHide' % divid)] |
174 (showhide, hidelabel, 'hidden', '%sHide' % divid)] |
174 |
175 |
175 def render_actions(self, divid, actions): |
176 def render_actions(self, divid, actions): |
176 box = MenuWidget('', 'tableActionsBox', _class='', islist=False) |
177 box = MenuWidget('', 'tableActionsBox', _class='', islist=False) |
177 label = '<img src="%s" alt="%s"/>' % ( |
178 label = '<img src="%s" alt="%s"/>' % ( |
182 box.append(menu) |
183 box.append(menu) |
183 for url, label, klass, ident in actions: |
184 for url, label, klass, ident in actions: |
184 menu.append(BoxLink(url, label, klass, ident=ident, escape=True)) |
185 menu.append(BoxLink(url, label, klass, ident=ident, escape=True)) |
185 box.render(w=self.w) |
186 box.render(w=self.w) |
186 self.w(u'<div class="clear"/>') |
187 self.w(u'<div class="clear"/>') |
187 |
188 |
188 def get_columns(self, rqlstdescr, displaycols, headers, subvid, cellvids, |
189 def get_columns(self, rqlstdescr, displaycols, headers, subvid, cellvids, |
189 cellattrs, mainindex): |
190 cellattrs, mainindex): |
190 columns = [] |
191 columns = [] |
191 for colindex, attr in enumerate(rqlstdescr): |
192 for colindex, attr in enumerate(rqlstdescr): |
192 if colindex not in displaycols: |
193 if colindex not in displaycols: |
216 for name, value in cellattrs[colindex].iteritems(): |
217 for name, value in cellattrs[colindex].iteritems(): |
217 column.add_attr(name, value) |
218 column.add_attr(name, value) |
218 # add column |
219 # add column |
219 columns.append(column) |
220 columns.append(column) |
220 return columns |
221 return columns |
221 |
222 |
222 |
223 |
223 def render(self, cellvid, row, col, w): |
224 def render(self, cellvid, row, col, w): |
224 self.view('cell', self.rset, row=row, col=col, cellvid=cellvid, w=w) |
225 self.view('cell', self.rset, row=row, col=col, cellvid=cellvid, w=w) |
225 |
226 |
226 def get_rows(self): |
227 def get_rows(self): |
227 return self.rset |
228 return self.rset |
228 |
229 |
229 @htmlescape |
230 @htmlescape |
230 @jsonize |
231 @jsonize |
249 class EditableTableView(TableView): |
250 class EditableTableView(TableView): |
250 id = 'editable-table' |
251 id = 'editable-table' |
251 finalview = 'editable-final' |
252 finalview = 'editable-final' |
252 title = _('editable-table') |
253 title = _('editable-table') |
253 |
254 |
254 |
255 |
255 class CellView(EntityView): |
256 class CellView(EntityView): |
256 __select__ = nonempty_rset() |
257 __select__ = nonempty_rset() |
257 |
258 |
258 id = 'cell' |
259 id = 'cell' |
259 |
260 |
260 def cell_call(self, row, col, cellvid=None): |
261 def cell_call(self, row, col, cellvid=None): |
261 """ |
262 """ |
262 :param row, col: indexes locating the cell value in view's result set |
263 :param row, col: indexes locating the cell value in view's result set |
263 :param cellvid: cell view (defaults to 'outofcontext') |
264 :param cellvid: cell view (defaults to 'outofcontext') |
264 """ |
265 """ |
275 self.wview(cellvid or 'final', self.rset, 'null', row=row, col=col) |
276 self.wview(cellvid or 'final', self.rset, 'null', row=row, col=col) |
276 |
277 |
277 |
278 |
278 class InitialTableView(TableView): |
279 class InitialTableView(TableView): |
279 """same display as table view but consider two rql queries : |
280 """same display as table view but consider two rql queries : |
280 |
281 |
281 * the default query (ie `rql` form parameter), which is only used to select |
282 * the default query (ie `rql` form parameter), which is only used to select |
282 this view and to build the filter form. This query should have the same |
283 this view and to build the filter form. This query should have the same |
283 structure as the actual without actual restriction (but link to |
284 structure as the actual without actual restriction (but link to |
284 restriction variables) and usually with a limit for efficiency (limit set |
285 restriction variables) and usually with a limit for efficiency (limit set |
285 to 2 is advised) |
286 to 2 is advised) |
286 |
287 |
287 * the actual query (`actualrql` form parameter) whose results will be |
288 * the actual query (`actualrql` form parameter) whose results will be |
288 displayed with default restrictions set |
289 displayed with default restrictions set |
289 """ |
290 """ |
290 id = 'initialtable' |
291 id = 'initialtable' |
291 __select__ = nonempty_rset() & match_form_params('actualrql') |
292 __select__ = nonempty_rset() & match_form_params('actualrql') |
292 # should not be displayed in possible view since it expects some specific |
293 # should not be displayed in possible view since it expects some specific |
293 # parameters |
294 # parameters |
294 title = None |
295 title = None |
295 |
296 |
296 def call(self, title=None, subvid=None, headers=None, divid=None, |
297 def call(self, title=None, subvid=None, headers=None, divid=None, |
297 displaycols=None, displayactions=None): |
298 displaycols=None, displayactions=None): |
298 """Dumps a table displaying a composite query""" |
299 """Dumps a table displaying a composite query""" |
299 actrql = self.req.form['actualrql'] |
300 actrql = self.req.form['actualrql'] |
300 self.ensure_ro_rql(actrql) |
301 self.ensure_ro_rql(actrql) |