sorting by link on column header on reporting results
This commit is contained in:
parent
ef61a836a4
commit
d317612187
4 changed files with 93 additions and 18 deletions
|
@ -132,7 +132,55 @@ class EditForm(form.EditForm):
|
||||||
return parentUrl + '/contents.html'
|
return parentUrl + '/contents.html'
|
||||||
|
|
||||||
|
|
||||||
class BaseView(GenericView, I18NView):
|
class SortableMixin(object):
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def sortInfo(self):
|
||||||
|
result = {}
|
||||||
|
for k, v in self.request.form.items():
|
||||||
|
if k.startswith('sortinfo_'):
|
||||||
|
tableName = k[len('sortinfo_'):]
|
||||||
|
if ',' in v:
|
||||||
|
fn, dir = v.split(',')
|
||||||
|
else:
|
||||||
|
fn = v
|
||||||
|
dir = 'asc'
|
||||||
|
result[tableName] = dict(colName=fn, ascending=(dir=='asc'))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def isSortableColumn(self, tableName, colName):
|
||||||
|
return False # overwrite in subclass
|
||||||
|
|
||||||
|
def getSortUrl(self, tableName, colName):
|
||||||
|
url = str(self.request.URL)
|
||||||
|
paramChar = '?' in url and '&' or '?'
|
||||||
|
si = self.sortInfo.get(tableName)
|
||||||
|
if si is not None and si.get('colName') == colName:
|
||||||
|
dir = si['ascending'] and 'desc' or 'asc'
|
||||||
|
else:
|
||||||
|
dir = 'asc'
|
||||||
|
return '%s%ssortinfo_%s=%s,%s' % (url, paramChar, tableName, colName, dir)
|
||||||
|
|
||||||
|
def getSortParams(self, tableName):
|
||||||
|
url = str(self.request.URL)
|
||||||
|
paramChar = '?' in url and '&' or '?'
|
||||||
|
si = self.sortInfo.get(tableName)
|
||||||
|
if si is not None:
|
||||||
|
colName = si['colName']
|
||||||
|
dir = si['ascending'] and 'asc' or 'desc'
|
||||||
|
return '%ssortinfo_%s=%s,%s' % (paramChar, tableName, colName, dir)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def getSortImage(self, tableName, colName):
|
||||||
|
si = self.sortInfo.get(tableName)
|
||||||
|
if si is not None and si.get('colName') == colName:
|
||||||
|
if si['ascending']:
|
||||||
|
return '/@@/cybertools.icons/arrowdown.gif'
|
||||||
|
else:
|
||||||
|
return '/@@/cybertools.icons/arrowup.gif'
|
||||||
|
|
||||||
|
|
||||||
|
class BaseView(GenericView, I18NView, SortableMixin):
|
||||||
|
|
||||||
actions = {}
|
actions = {}
|
||||||
portlet_actions = []
|
portlet_actions = []
|
||||||
|
|
|
@ -192,6 +192,13 @@ class ResultsConceptView(ConceptView):
|
||||||
ri = component.getAdapter(self.report, IReportInstance,
|
ri = component.getAdapter(self.report, IReportInstance,
|
||||||
name=reportType)
|
name=reportType)
|
||||||
ri.view = self
|
ri.view = self
|
||||||
|
if not ri.sortCriteria:
|
||||||
|
si = self.sortInfo.get('results')
|
||||||
|
if si is not None:
|
||||||
|
fnames = (si['colName'],)
|
||||||
|
ri.sortCriteria = [f for f in ri.getSortFields()
|
||||||
|
if f.name in fnames]
|
||||||
|
ri.sortDescending = not si['ascending']
|
||||||
return ri
|
return ri
|
||||||
|
|
||||||
def results(self):
|
def results(self):
|
||||||
|
@ -212,6 +219,12 @@ class ResultsConceptView(ConceptView):
|
||||||
if opt:
|
if opt:
|
||||||
return opt[0]
|
return opt[0]
|
||||||
|
|
||||||
|
def isSortableColumn(self, tableName, colName):
|
||||||
|
if tableName == 'results':
|
||||||
|
if colName in [f.name for f in self.reportInstance.getSortFields()]:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class EmbeddedResultsConceptView(ResultsConceptView):
|
class EmbeddedResultsConceptView(ResultsConceptView):
|
||||||
|
|
||||||
|
|
|
@ -35,38 +35,50 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div metal:define-macro="results">
|
<div metal:define-macro="results"
|
||||||
|
tal:define="tableName string:results">
|
||||||
<br />
|
<br />
|
||||||
<tal:download condition="item/downloadLink">
|
<tal:download condition="item/downloadLink">
|
||||||
<div class="button">
|
<div class="button">
|
||||||
<a i18n:translate=""
|
<a i18n:translate=""
|
||||||
tal:attributes="href item/downloadLink">Download Data</a>
|
tal:define="params python:item.getSortParams(tableName)"
|
||||||
|
tal:attributes="href string:${item/downloadLink}$params">Download Data</a>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
</tal:download>
|
</tal:download>
|
||||||
<table class="report"
|
<table class="report"
|
||||||
tal:define="results reportView/results">
|
tal:define="results reportView/results">
|
||||||
<tr>
|
<tr>
|
||||||
<th tal:repeat="col results/displayedColumns"
|
<th style="white-space: nowrap"
|
||||||
tal:content="col/title"
|
tal:repeat="col results/displayedColumns">
|
||||||
tal:attributes="class col/cssClass"
|
<a tal:define="colName col/name"
|
||||||
i18n:translate="" />
|
tal:attributes="href python:
|
||||||
|
item.getSortUrl(tableName, colName)"
|
||||||
|
tal:omit-tag="python:not item.isSortableColumn(tableName, colName)">
|
||||||
|
<span tal:content="col/title"
|
||||||
|
tal:attributes="class col/cssClass"
|
||||||
|
i18n:translate="" />
|
||||||
|
<img tal:define="src python:item.getSortImage(tableName, colName)"
|
||||||
|
tal:condition="src"
|
||||||
|
tal:attributes="src src" />
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:repeat="row results"
|
<tr tal:repeat="row results"
|
||||||
tal:attributes="class python:(repeat['row'].index() % 2) and 'even' or 'odd'">
|
tal:attributes="class python:(repeat['row'].index() % 2) and 'even' or 'odd'">
|
||||||
<td tal:repeat="col results/displayedColumns"
|
<td tal:repeat="col results/displayedColumns"
|
||||||
tal:attributes="class col/cssClass">
|
tal:attributes="class col/cssClass">
|
||||||
<metal:column use-macro="python:
|
<metal:column use-macro="python:
|
||||||
reportView.getColumnRenderer(col)" />
|
reportView.getColumnRenderer(col)" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr tal:define="row nocall:results/totals"
|
<tr tal:define="row nocall:results/totals"
|
||||||
tal:condition="nocall:row">
|
tal:condition="nocall:row">
|
||||||
<td tal:repeat="col results/displayedColumns"
|
<td tal:repeat="col results/displayedColumns"
|
||||||
tal:attributes="class col/cssClass">
|
tal:attributes="class col/cssClass">
|
||||||
<metal:column use-macro="python:
|
<metal:column use-macro="python:
|
||||||
reportView.getColumnRenderer(col)" />
|
reportView.getColumnRenderer(col)" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -120,7 +120,9 @@ class ReportInstance(BaseReport):
|
||||||
result = list(self.selectObjects(parts)) # may modify parts
|
result = list(self.selectObjects(parts)) # may modify parts
|
||||||
qc = CompoundQueryCriteria(parts)
|
qc = CompoundQueryCriteria(parts)
|
||||||
return ResultSet(self, result, rowFactory=self.rowFactory,
|
return ResultSet(self, result, rowFactory=self.rowFactory,
|
||||||
sortCriteria=self.getSortCriteria(), queryCriteria=qc,
|
sortCriteria=self.getSortCriteria(),
|
||||||
|
sortDescending=self.sortDescending,
|
||||||
|
queryCriteria=qc,
|
||||||
limits=limits)
|
limits=limits)
|
||||||
|
|
||||||
def selectObjects(self, parts):
|
def selectObjects(self, parts):
|
||||||
|
|
Loading…
Add table
Reference in a new issue