backoffice: set listing as main form page, with a fields selection sidebar
https://dev.entrouvert.org/issues/1275
This commit is contained in:
parent
03d0efa0e3
commit
601c0a8d2b
|
@ -208,6 +208,22 @@ class RootDirectory(BackofficeRootDirectory):
|
|||
return FormPage(component)
|
||||
|
||||
|
||||
class FakeField:
|
||||
def __init__(self, id, type_, label):
|
||||
self.id = id
|
||||
self.type = type_
|
||||
self.label = label
|
||||
|
||||
def get_view_value(self, value):
|
||||
# just here to quack like a duck
|
||||
return None
|
||||
|
||||
def get_csv_heading(self):
|
||||
return [self.label]
|
||||
|
||||
def get_csv_value(self, element):
|
||||
return [element]
|
||||
|
||||
class FormPage(Directory):
|
||||
_q_exports = ['', 'listing', 'csv', 'stats', 'xls', 'pending']
|
||||
|
||||
|
@ -231,31 +247,76 @@ class FormPage(Directory):
|
|||
raise errors.AccessUnauthorizedError()
|
||||
get_response().breadcrumb.append( (component + '/', self.formdef.name) )
|
||||
|
||||
def _q_index [html] (self):
|
||||
get_logger().info('backoffice - form %s' % self.formdef.name)
|
||||
html_top('%s - %s' % (_('Back Office'), self.formdef.name))
|
||||
get_session().display_message()
|
||||
'<h2>%s</h2>' % self.formdef.name
|
||||
|
||||
def get_formdata_sidebar [html] (self, qs=''):
|
||||
'<ul>'
|
||||
'<li><a href="listing">%s</a></li>' % _('Listing')
|
||||
'<li><a href="csv">%s</a></li>' % _('Listing in CSV format')
|
||||
#' <li><a href="list%s">%s</a></li>' % (qs, _('List of results'))
|
||||
' <li><a href="csv">%s</a></li>' % _('CSV Export')
|
||||
if xlwt:
|
||||
'<li><a href="xls">%s</a></li>' % _('Listing in Excel format')
|
||||
'<li><a href="pending">%s</a></li>' % _('Pending Forms')
|
||||
'<li><a href="stats">%s</a></li>' % _('Statistics')
|
||||
'<li><a href="xls">%s</a></li>' % _('Excel Export')
|
||||
' <li><a href="stats">%s</a></li>' % _('Statistics')
|
||||
'</ul>'
|
||||
|
||||
'<a href="..">%s</a>' % _('Back')
|
||||
def get_fields_sidebar [html] (self, fields):
|
||||
'<h3>%s</h3>' % _('Fields to display')
|
||||
'<form>'
|
||||
'<ul>'
|
||||
for field in self.get_formdef_fields():
|
||||
if not hasattr(field, str('get_view_value')):
|
||||
continue
|
||||
'<li><input type="checkbox" name="%s"' % field.id
|
||||
if field.id in [x.id for x in fields]:
|
||||
' checked="checked"'
|
||||
'/>'
|
||||
'<label for="%s">%s</label>' % (field.id, field.label)
|
||||
'</li>'
|
||||
'</ul>'
|
||||
'<input type="submit" value="%s"/>' % _('Reload')
|
||||
'</form>'
|
||||
|
||||
def get_formdef_fields(self):
|
||||
fields = []
|
||||
fields.append(FakeField('id', 'id', _('Identifier')))
|
||||
fields.append(FakeField('time', 'time', _('Time')))
|
||||
fields.append(FakeField('user-label', 'user-label', _('User Label')))
|
||||
|
||||
def listing [html] (self):
|
||||
fields.extend(self.formdef.fields)
|
||||
|
||||
if self.formdef.workflow is None or len(
|
||||
self.formdef.workflow.possible_status) > 1:
|
||||
fields.append(FakeField('status', 'status', _('Status')))
|
||||
|
||||
return fields
|
||||
|
||||
def get_fields_from_query(self):
|
||||
field_ids = [x for x in get_request().form.keys()]
|
||||
if not field_ids:
|
||||
for field in self.formdef.fields:
|
||||
if not hasattr(field, str('get_view_value')):
|
||||
continue
|
||||
field_ids = ['id', 'time', 'user-label', field.id, 'status']
|
||||
break
|
||||
|
||||
fields = []
|
||||
for field in self.get_formdef_fields():
|
||||
if field.id in field_ids:
|
||||
fields.append(field)
|
||||
|
||||
return fields
|
||||
|
||||
def _q_index [html] (self):
|
||||
get_logger().info('backoffice - form %s - listing' % self.formdef.name)
|
||||
|
||||
fields = self.get_fields_from_query()
|
||||
qs = ''
|
||||
if get_request().get_query():
|
||||
qs = '?' + get_request().get_query()
|
||||
|
||||
get_response().breadcrumb.append( ('listing', _('Listing')) )
|
||||
html_top('forms', '%s - %s' % (_('Listing'), self.formdef.name))
|
||||
'<h2>%s - %s</h2>' % (self.formdef.name, _('Listing'))
|
||||
FormDefUI(self.formdef).listing(include_form = True)
|
||||
'<a href=".">%s</a>' % _('Back')
|
||||
FormDefUI(self.formdef).listing(fields=fields, include_form=True)
|
||||
|
||||
get_response().filter['sidebar'] = self.get_formdata_sidebar(qs) + self.get_fields_sidebar(fields)
|
||||
|
||||
def pending [html] (self):
|
||||
get_logger().info('backoffice - form %s - pending' % self.formdef.name)
|
||||
|
@ -311,16 +372,28 @@ class FormPage(Directory):
|
|||
userlabel = get_publisher().user_class.get(filled.user_id).name
|
||||
except:
|
||||
userlabel = ''
|
||||
elements = [str(data.id), misc.localstrftime(data.receipt_time),
|
||||
userlabel, data.get_status_label()]
|
||||
elements = []
|
||||
for field in fields:
|
||||
element = data.data.get(field.id, '') or ''
|
||||
elements.extend(field.get_csv_value(element))
|
||||
if field.type == 'id':
|
||||
element = str(data.id)
|
||||
elif field.type == 'time':
|
||||
element = misc.localstrftime(data.receipt_time)
|
||||
elif field.type == 'user-label':
|
||||
try:
|
||||
element = User.get(data.user_id).display_name
|
||||
except:
|
||||
element = ''
|
||||
pass
|
||||
elif field.type == 'status':
|
||||
element = data.get_status_label()
|
||||
else:
|
||||
element = data.data.get(field.id, '') or ''
|
||||
elements.extend(['type:%s'%field.type]+field.get_csv_value(element))
|
||||
return elements
|
||||
|
||||
def csv(self):
|
||||
get_logger().info('backoffice - form %s - listing csv' % self.formdef.name)
|
||||
fields = FormDefUI(self.formdef).get_listing_fields()
|
||||
fields = self.get_formdef_fields()
|
||||
|
||||
output = cStringIO.StringIO()
|
||||
csv_output = csv.writer(output)
|
||||
|
@ -331,8 +404,9 @@ class FormPage(Directory):
|
|||
for filled in items:
|
||||
csv_output.writerow(self.csv_tuple(fields, filled))
|
||||
response = get_response()
|
||||
response.set_content_type('text/csv')
|
||||
response.set_header('content-disposition', 'attachment; filename=export.csv')
|
||||
response.set_content_type('text/plain')
|
||||
#response.set_content_type('text/csv')
|
||||
#response.set_header('content-disposition', 'attachment; filename=export.csv')
|
||||
return output.getvalue()
|
||||
|
||||
def xls(self):
|
||||
|
|
|
@ -25,49 +25,22 @@ class FormDefUI:
|
|||
def __init__(self, formdef):
|
||||
self.formdef = formdef
|
||||
|
||||
|
||||
def get_listing_fields(self):
|
||||
fields = []
|
||||
for f in self.formdef.fields:
|
||||
if f.type in ('title', 'subtitle', 'comment'):
|
||||
continue
|
||||
if f.in_listing:
|
||||
fields.append(f)
|
||||
return fields
|
||||
|
||||
|
||||
def listing [html] (self, url_action = None, include_form = False, items = None):
|
||||
def listing [html] (self, fields, url_action=None, include_form=False, items=None):
|
||||
get_response().add_javascript(['jquery.js',
|
||||
'tablesorter/jquery.tablesorter.min.js',
|
||||
'jquery.event.drag-1.4.js',
|
||||
'jquery.kiketable.colsizable-1.1.js'])
|
||||
'tablesorter/jquery.tablesorter.min.js'])
|
||||
get_response().add_javascript_code(
|
||||
str('''$(function() {
|
||||
$("table.sortable").tablesorter(
|
||||
).kiketable_colsizable({dragMove:false,dragProxy: 'line'}); });'''))
|
||||
str('''$(function() { $("table.sortable").tablesorter(); });'''))
|
||||
get_response().add_css_include('../js/tablesorter/themes/blue/style.css')
|
||||
get_response().add_css_include('../js/jquery.kiketable.colsizable.css')
|
||||
|
||||
if self.formdef.workflow is None or len(
|
||||
self.formdef.workflow.possible_status) > 1:
|
||||
include_status_column = True
|
||||
else:
|
||||
include_status_column = False
|
||||
|
||||
'<table id="listing" class="sortable tablesorter">'
|
||||
fields = self.get_listing_fields()
|
||||
'<colgroup>'
|
||||
'<col/>'
|
||||
'<col/>'
|
||||
for f in fields:
|
||||
'<col />'
|
||||
if include_status_column:
|
||||
'<col />'
|
||||
'</colgroup>'
|
||||
|
||||
'<thead><tr>'
|
||||
'<th></th>'
|
||||
'<th>%s</th>' % _('Creation Time')
|
||||
for f in fields:
|
||||
'<th>'
|
||||
if len(f.label) < 20:
|
||||
|
@ -76,17 +49,11 @@ class FormDefUI:
|
|||
'<span title="%s">%s</span>' % (
|
||||
f.label, misc.ellipsize(f.label, 20))
|
||||
'</th>'
|
||||
if include_status_column:
|
||||
'<th>%s</th>' % _('Status')
|
||||
'</tr></thead>'
|
||||
if include_form:
|
||||
'<thead style="display: none">' # will be displayed by javascript
|
||||
'<tr>'
|
||||
'<td></td>'
|
||||
'<td></td>' # creation time
|
||||
for f in fields:
|
||||
if f.type in ('title', 'subtitle', 'comment'):
|
||||
continue
|
||||
'<td>'
|
||||
if f.type == 'item' and f.items:
|
||||
'<select onchange="updateListing()" name="f-%s">' % f.id
|
||||
|
@ -94,32 +61,26 @@ class FormDefUI:
|
|||
for item in f.items:
|
||||
'<option value="%s">%s</option>' % (item, misc.ellipsize(item, 20))
|
||||
'</select>'
|
||||
if f.type == 'status':
|
||||
'<select name="status" onchange="updateListing()"'
|
||||
'<option value="">%s</option>' % _('All')
|
||||
if self.formdef.workflow:
|
||||
for status in self.formdef.workflow.possible_status:
|
||||
'<option value="wf-%s">%s</option>' % (status.id, status.name)
|
||||
else: # COMPAT (behaviour when no workflow)
|
||||
for label in ('new', 'accepted', 'finished', 'rejected'):
|
||||
'<option value="%s">%s</option>' % (label, _(status_labels[label]))
|
||||
'</select>'
|
||||
'</td>'
|
||||
if include_status_column:
|
||||
'<td><select name="status" onchange="updateListing()"'
|
||||
'<option value="">%s</option>' % _('All')
|
||||
for status in self.formdef.workflow.possible_status:
|
||||
'<option value="wf-%s">%s</option>' % (status.id, status.name)
|
||||
'</select></td>'
|
||||
'</tr>'
|
||||
'</thead>'
|
||||
'<script src="%sjs/listing.js"></script>' % get_publisher().get_root_url()
|
||||
|
||||
'<tbody>'
|
||||
self.tbody(fields = fields, items = items, url_action = url_action)
|
||||
'</tbody>'
|
||||
"</table>"
|
||||
|
||||
def tbody [html] (self, fields = None, items = None, url_action = None):
|
||||
if self.formdef.workflow is None or len(
|
||||
self.formdef.workflow.possible_status) > 1:
|
||||
include_status_column = True
|
||||
else:
|
||||
include_status_column = False
|
||||
|
||||
if not fields:
|
||||
fields = self.get_listing_fields()
|
||||
|
||||
def tbody [html] (self, fields=None, items=None, url_action=None):
|
||||
if items is None:
|
||||
items = self.formdef.data_class().select(order_by = '-receipt_time')
|
||||
if url_action:
|
||||
|
@ -137,19 +98,26 @@ class FormDefUI:
|
|||
style = 'odd'
|
||||
'<tr class="status-%s %s">' % (filled.status, style)
|
||||
link = str(filled.id) + '/'
|
||||
'<td><a href="%s%s">%s</a></td>' % (link, url_action, filled.id)
|
||||
'<td>%s</td>' % misc.localstrftime(filled.receipt_time)
|
||||
for i, f in enumerate(fields):
|
||||
if f.type in ('title', 'subtitle', 'comment'):
|
||||
continue
|
||||
'<td>'
|
||||
value = filled.data.get(f.id)
|
||||
if value is not None:
|
||||
s = f.get_view_short_value(value, min(120/len(fields), 30))
|
||||
s = s.replace(str('[download]'), str('%sdownload' % link))
|
||||
s
|
||||
'</td>'
|
||||
if include_status_column:
|
||||
'<td>%s</td>' % filled.get_status_label()
|
||||
if f.type == 'id':
|
||||
'<td><a href="%s%s">%s</a></td>' % (link, url_action, filled.id)
|
||||
elif f.type == 'time':
|
||||
'<td>%s</td>' % misc.localstrftime(filled.receipt_time)
|
||||
elif f.type == 'user-label':
|
||||
try:
|
||||
value = User.get(result.user_id).display_name
|
||||
'<td>%s</td>' % value
|
||||
except:
|
||||
'<td>-</td>'
|
||||
elif f.type == 'status':
|
||||
'<td>%s</td>' % filled.get_status_label()
|
||||
else:
|
||||
'<td>'
|
||||
value = filled.data.get(f.id)
|
||||
if value is not None:
|
||||
s = f.get_view_short_value(value, min(120/len(fields), 30))
|
||||
s = s.replace(str('[download]'), str('%sdownload' % link))
|
||||
s
|
||||
'</td>'
|
||||
'</tr>\n'
|
||||
|
||||
|
|
Loading…
Reference in New Issue