diff --git a/MANIFEST.in b/MANIFEST.in index d688a50c6..b0f3135c7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -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 diff --git a/tests/test_workflows.py b/tests/test_workflows.py index de9391d6c..8768653d5 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -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] == '

Hello world

' item.comment = '
Hello world
' item.perform(formdata) + formdata.evolution[-1]._display_parts = None assert formdata.evolution[-1].display_parts()[-1] == '
Hello world
' item.comment = '[test]' item.perform(formdata) + formdata.evolution[-1]._display_parts = None assert formdata.evolution[-1].display_parts()[-1] == '

[test]

' 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] == '

Foobar

' item.comment = '[foo]' item.perform(formdata) + formdata.evolution[-1]._display_parts = None assert formdata.evolution[-1].display_parts()[-1] == '

1 < 3

' item.comment = '
[foo]
' item.perform(formdata) + formdata.evolution[-1]._display_parts = None assert formdata.evolution[-1].display_parts()[-1] == '
1 < 3
' 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')): diff --git a/wcs/formdata.py b/wcs/formdata.py index b6b0fab0e..03697f891 100644 --- a/wcs/formdata.py +++ b/wcs/formdata.py @@ -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: diff --git a/wcs/forms/common.py b/wcs/forms/common.py index 6397c721b..cebae12cd 100644 --- a/wcs/forms/common.py +++ b/wcs/forms/common.py @@ -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('
') - r += htmltext('

%s

') % _('Log') - r += htmltext('') - r += htmltext('
') # .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() diff --git a/wcs/forms/root.py b/wcs/forms/root.py index ab9dbf034..c0471d26f 100644 --- a/wcs/forms/root.py +++ b/wcs/forms/root.py @@ -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) diff --git a/wcs/qommon/template.py b/wcs/qommon/template.py index cd02358ec..e6eab9998 100644 --- a/wcs/qommon/template.py +++ b/wcs/qommon/template.py @@ -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')) diff --git a/wcs/templates/wcs/formdata_history.html b/wcs/templates/wcs/formdata_history.html new file mode 100644 index 000000000..e85f4d3eb --- /dev/null +++ b/wcs/templates/wcs/formdata_history.html @@ -0,0 +1,39 @@ +{% load i18n %} +
+

{% trans "Log" %}

+ +
diff --git a/wcs/workflows.py b/wcs/workflows.py index 67fe86f11..dff5ce50c 100644 --- a/wcs/workflows.py +++ b/wcs/workflows.py @@ -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'):