templates: use a template to render formdata history (#17601)
This commit is contained in:
parent
98b74edd3f
commit
db4d477898
|
@ -8,3 +8,4 @@ recursive-include data/themes/default/ *.html *.css *.png *.gif *.jpg *.js *.ezt
|
|||
recursive-include data/themes/alto/ *.html *.css *.png *.gif *.jpg *.js *.ezt *.xml
|
||||
recursive-include data/vendor/ *.dat
|
||||
recursive-include wcs/qommon/static/ *.css *.png *.gif *.jpg *.js *.eot *.svg *.ttf *.woff
|
||||
recursive-include wcs/templates *.html
|
||||
|
|
|
@ -521,30 +521,38 @@ def test_register_comment(pub):
|
|||
|
||||
item = RegisterCommenterWorkflowStatusItem()
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == ''
|
||||
|
||||
item.comment = 'Hello world'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<p>Hello world</p>'
|
||||
|
||||
item.comment = '<div>Hello world</div>'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<div>Hello world</div>'
|
||||
|
||||
item.comment = '[test]'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<p>[test]</p>'
|
||||
|
||||
item.comment = '[bar]'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<p>Foobar</p>'
|
||||
|
||||
item.comment = '[foo]'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<p>1 < 3</p>'
|
||||
|
||||
item.comment = '<div>[foo]</div>'
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == '<div>1 < 3</div>'
|
||||
|
||||
def test_register_comment_attachment(pub):
|
||||
|
@ -561,6 +569,7 @@ def test_register_comment_attachment(pub):
|
|||
|
||||
item = RegisterCommenterWorkflowStatusItem()
|
||||
item.perform(formdata)
|
||||
formdata.evolution[-1]._display_parts = None
|
||||
assert formdata.evolution[-1].display_parts()[-1] == ''
|
||||
|
||||
if os.path.exists(os.path.join(get_publisher().app_dir, 'attachments')):
|
||||
|
|
|
@ -143,17 +143,29 @@ class Evolution(object):
|
|||
return self._formdata
|
||||
|
||||
def get_author_name(self):
|
||||
user_id = self.who
|
||||
if self.who == '_submitter':
|
||||
user_id = self.formdata.user_id
|
||||
try:
|
||||
return get_publisher().user_class.get(user_id).display_name
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def get_author_qualification(self):
|
||||
if self.who == '_submitter' and not self.formdata.is_submitter(get_request().user):
|
||||
return _('Original Submitter')
|
||||
else:
|
||||
return get_publisher().user_class.get(self.who).display_name
|
||||
return None
|
||||
|
||||
def add_part(self, part):
|
||||
if not self.parts:
|
||||
self.parts = []
|
||||
self.parts.append(part)
|
||||
|
||||
_display_parts = None # cache
|
||||
def display_parts(self):
|
||||
if self._display_parts is not None:
|
||||
return self._display_parts
|
||||
|
||||
if not self.parts:
|
||||
return []
|
||||
|
||||
|
@ -162,7 +174,8 @@ class Evolution(object):
|
|||
if not hasattr(p, 'view'):
|
||||
continue
|
||||
l.append(p.view())
|
||||
return l
|
||||
self._display_parts = l
|
||||
return self._display_parts
|
||||
|
||||
def get_json_export_dict(self, user, anonymise=False):
|
||||
data = {
|
||||
|
@ -194,8 +207,27 @@ class Evolution(object):
|
|||
odict = self.__dict__.copy()
|
||||
if odict.has_key('_formdata'):
|
||||
del odict['_formdata']
|
||||
if odict.has_key('_display_parts'):
|
||||
del odict['_display_parts']
|
||||
return odict
|
||||
|
||||
@property
|
||||
def datetime(self):
|
||||
return datetime.datetime(*self.time[:6])
|
||||
|
||||
def is_hidden(self):
|
||||
if self.status:
|
||||
wf_status = self.formdata.get_status(self.status)
|
||||
if wf_status and not wf_status.is_visible(self.formdata, get_request().user):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_status(self):
|
||||
return self.formdata.get_status(status=self.status)
|
||||
|
||||
def get_status_label(self):
|
||||
return self.formdata.get_status_label(status=self.status)
|
||||
|
||||
|
||||
class FormData(StorableObject):
|
||||
_names = 'XX'
|
||||
|
@ -451,6 +483,22 @@ class FormData(StorableObject):
|
|||
return wf_status
|
||||
return None
|
||||
|
||||
def get_visible_evolution_parts(self):
|
||||
last_seen_status = None
|
||||
last_seen_author = None
|
||||
for evolution_part in self.evolution or []:
|
||||
if evolution_part.is_hidden():
|
||||
continue
|
||||
if (evolution_part.status is None or last_seen_status == evolution_part.status) and (
|
||||
evolution_part.who is None or last_seen_author == evolution_part.who):
|
||||
# don't include empty evolution parts if status and author
|
||||
# didn't change.
|
||||
if not evolution_part.comment and not evolution_part.display_parts():
|
||||
continue
|
||||
last_seen_status = evolution_part.status or last_seen_status
|
||||
last_seen_author = evolution_part.who or last_seen_author
|
||||
yield evolution_part
|
||||
|
||||
def get_workflow_form(self, user):
|
||||
wf_status = self.get_status()
|
||||
if not wf_status:
|
||||
|
|
|
@ -25,6 +25,8 @@ from wcs.api_utils import get_user_from_api_query_string, is_url_signed
|
|||
from wcs.fields import WidgetField, FileField
|
||||
from wcs.workflows import EditableWorkflowStatusItem
|
||||
|
||||
from django.template import RequestContext
|
||||
|
||||
from qommon import _
|
||||
from qommon import template
|
||||
from qommon import get_logger
|
||||
|
@ -94,6 +96,8 @@ class FormStatusPage(Directory):
|
|||
_q_extra_exports = []
|
||||
form_page_class = None
|
||||
|
||||
history_templates = ['wcs/formdata_history.html']
|
||||
|
||||
def html_top(self, title = None):
|
||||
template.html_top(title = title, default_org = _('Forms'))
|
||||
|
||||
|
@ -251,108 +255,9 @@ class FormStatusPage(Directory):
|
|||
return
|
||||
if not self.formdef.is_user_allowed_read_status_and_history(get_request().user, self.filled):
|
||||
return
|
||||
r = TemplateIO(html=True)
|
||||
r += htmltext('<div class="bo-block" id="evolution-log">')
|
||||
r += htmltext('<h2 class="foldable">%s</h2>') % _('Log')
|
||||
r += htmltext('<ul id="evolutions">')
|
||||
hidden = False
|
||||
previous_status = None
|
||||
for evo in self.filled.evolution:
|
||||
status_css_class = ''
|
||||
if evo.status:
|
||||
wf_status = self.filled.get_status(evo.status)
|
||||
if wf_status:
|
||||
status_css_class = wf_status.extra_css_class
|
||||
if wf_status and not wf_status.is_visible(self.filled, get_request().user):
|
||||
hidden = True
|
||||
else:
|
||||
hidden = False
|
||||
if hidden:
|
||||
continue
|
||||
|
||||
evo_author = None
|
||||
evo_author_more = None
|
||||
klass = 'msg-system'
|
||||
if evo.who:
|
||||
if evo.who == '_submitter':
|
||||
klass = 'msg-in'
|
||||
evo_author = _('Original Submitter')
|
||||
if get_request().user and self.filled.is_submitter(get_request().user):
|
||||
evo_author = get_request().user.display_name
|
||||
elif self.filled.user_id:
|
||||
try:
|
||||
evo_author = get_publisher().user_class.get(self.filled.user_id).display_name
|
||||
evo_author_more = _('(Original Submitter)')
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
klass = 'msg-out'
|
||||
try:
|
||||
evo_author = evo.get_author_name()
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
status_block = TemplateIO(html=True)
|
||||
if evo.status:
|
||||
status_block += htmltext('<div class="evolution-metadata">')
|
||||
status_block += htmltext('<span class="status">%s</span> '
|
||||
) % self.filled.get_status_label(evo.status)
|
||||
status_block += htmltext('<span class="time">%s</span> '
|
||||
) % misc.localstrftime(evo.time)
|
||||
status_block += htmltext('</div>') # <-- .evolution-metadata -->
|
||||
|
||||
parts = TemplateIO(html=True)
|
||||
if evo_author:
|
||||
parts += htmltext('<span class="user">%s') % evo_author
|
||||
if evo_author_more:
|
||||
parts += htmltext(' <span>%s</span>') % evo_author_more
|
||||
parts += htmltext('</span>')
|
||||
if not evo.status:
|
||||
parts += htmltext('<span class="time">%s</span> ') % misc.localstrftime(evo.time)
|
||||
|
||||
if evo.comment:
|
||||
if evo.comment.startswith(str('#pre')):
|
||||
parts += htmltext('<div class="comment"><pre>%s</pre></div>') % evo.comment[4:]
|
||||
else:
|
||||
parts += htmltext('<div class="comment">')
|
||||
parts += htmltext('<p>')
|
||||
parts += htmltext('\n').join(
|
||||
[(x or htmltext('</p><p>')) for x in evo.comment.splitlines()])
|
||||
parts += htmltext('</p>')
|
||||
parts += htmltext('</div>')
|
||||
for t in evo.display_parts():
|
||||
parts += t
|
||||
|
||||
parts_value = parts.getvalue()
|
||||
|
||||
if not (parts_value or evo.status != previous_status):
|
||||
continue
|
||||
|
||||
if evo.status:
|
||||
previous_status = evo.status
|
||||
|
||||
try:
|
||||
status_colour = self.filled.get_status(previous_status).colour
|
||||
except AttributeError:
|
||||
status_colour = 'ffffff'
|
||||
fg_colour = misc.get_foreground_colour(status_colour)
|
||||
|
||||
r += htmltext('<li class="%s %s">' % (klass, status_css_class))
|
||||
r += htmltext('<span class="item" style="background: #%s; color: %s;"></span>' %
|
||||
(status_colour, fg_colour))
|
||||
r += htmltext('<div>')
|
||||
r += status_block.getvalue()
|
||||
|
||||
if parts_value:
|
||||
r += htmltext('<div class="msg">')
|
||||
r += htmltext(parts_value)
|
||||
r += htmltext('</div>')
|
||||
|
||||
r += htmltext('</div>')
|
||||
r += htmltext('</li>')
|
||||
r += htmltext('</ul>')
|
||||
r += htmltext('</div>') # .bo-block #evolution-log
|
||||
return r.getvalue()
|
||||
context = RequestContext(get_request(), {'formdata': self.filled})
|
||||
return template.render(self.history_templates, context)
|
||||
|
||||
def check_receiver(self):
|
||||
session = get_session()
|
||||
|
|
|
@ -1577,6 +1577,7 @@ class RootDirectory(AccessControlled, Directory):
|
|||
class PublicFormStatusPage(FormStatusPage):
|
||||
_q_exports_orig = ['', 'download', 'status']
|
||||
form_page_class = FormPage
|
||||
history_templates = ['wcs/front/formdata_history.html', 'wcs/formdata_history.html']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
FormStatusPage.__init__(self, *args, **kwargs)
|
||||
|
|
|
@ -19,6 +19,8 @@ import os
|
|||
import glob
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from quixote import get_session, get_request, get_response, get_publisher
|
||||
from quixote.directory import Directory
|
||||
from quixote.util import StaticDirectory, StaticFile
|
||||
|
@ -405,3 +407,7 @@ def decorate(body, response):
|
|||
|
||||
template.generate(fd, vars)
|
||||
return fd.getvalue()
|
||||
|
||||
|
||||
def render(template_name, context):
|
||||
return htmltext(render_to_string(template_name, context).encode('utf-8'))
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
{% load i18n %}
|
||||
<div class="bo-block" id="evolution-log">
|
||||
<h2 class="foldable">{% trans "Log" %}</h2>
|
||||
<ul id="evolutions">
|
||||
{% for evolution in formdata.get_visible_evolution_parts %}
|
||||
{% with status=evolution.get_status display_parts=evolution.display_parts %}
|
||||
<li class="{% if evolution.who == '_submitter' %}msg-in{% elif evolution.who %}msg-out{% else %}msg-system{% endif %} {{ status.extra_css_class }}">
|
||||
<span class="item" style="background: #{{ status.colour }}; color: {{ status.get_contrast_color}}"></span>
|
||||
<div>
|
||||
{% if evolution.status %}
|
||||
<div class="evolution-metadata">
|
||||
<span class="status">{{evolution.get_status_label}}</span>
|
||||
<span class="time">{{evolution.datetime}}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="msg">
|
||||
{% if evolution.who %}
|
||||
<span class="user">{{evolution.get_author_name}}
|
||||
<span>{% if evolution.get_author_qualification %}({{evolution.get_author_qualification}}){% endif %}</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% if not evolution.status %}
|
||||
<span class="time">{{evolution.datetime}}</span>
|
||||
{% endif %}
|
||||
{% if evolution.comment %}
|
||||
<div class="comment">
|
||||
{{evolution.comment|linebreaks}}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% for part in display_parts %}
|
||||
{{part|safe}}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
|
@ -29,7 +29,7 @@ import uuid
|
|||
from quixote import get_request, redirect
|
||||
|
||||
from qommon import _
|
||||
from qommon.misc import C_, get_as_datetime, file_digest
|
||||
from qommon.misc import C_, get_as_datetime, file_digest, get_foreground_colour
|
||||
from qommon.storage import StorableObject, atomic_write
|
||||
from qommon.form import *
|
||||
from qommon.humantime import seconds2humanduration
|
||||
|
@ -1411,6 +1411,10 @@ class WorkflowStatus(object):
|
|||
waitpoint = item.waitpoint or waitpoint
|
||||
return bool(endpoint or waitpoint)
|
||||
|
||||
def get_contrast_color(self):
|
||||
colour = self.colour or 'ffffff'
|
||||
return misc.get_foreground_colour(colour)
|
||||
|
||||
def __getstate__(self):
|
||||
odict = self.__dict__.copy()
|
||||
if odict.has_key('parent'):
|
||||
|
|
Loading…
Reference in New Issue