0003-workflows-add-target-roles-in-commenter-workflow-ite.patch
tests/test_formdata.py | ||
---|---|---|
419 | 419 |
d.user_id = local_user.id |
420 | 420 |
d.receipt_time = time.localtime() |
421 | 421 |
evo = Evolution() |
422 | 422 |
evo.time = time.localtime() |
423 | 423 |
evo.status = 'wf-%s' % st_new.id |
424 | 424 |
evo.who = '_submitter' |
425 | 425 |
d.evolution = [evo] |
426 | 426 |
d.store() |
427 |
evo.add_part(JournalEvolutionPart(d, "ok")) |
|
427 |
evo.add_part(JournalEvolutionPart(d, "ok", None))
|
|
428 | 428 |
evo.add_part(JournalWsCallErrorPart("summary", "label", "data")) |
429 | 429 |
evo = Evolution() |
430 | 430 |
evo.time = time.localtime() |
431 | 431 |
evo.status = 'wf-%s' % st_finished.id |
432 | 432 |
evo.who = '_submitter' |
433 | 433 |
d.evolution.append(evo) |
434 | 434 |
d.store() |
435 | 435 | |
... | ... | |
459 | 459 |
export = d.get_json_export_dict(anonymise=True) |
460 | 460 |
assert 'evolution' in export |
461 | 461 |
assert len(export['evolution']) == 2 |
462 | 462 |
assert export['evolution'][0]['status'] == st_new.id |
463 | 463 |
assert 'time' in export['evolution'][0] |
464 | 464 |
assert 'who' not in export['evolution'][0] |
465 | 465 |
assert 'parts' in export['evolution'][0] |
466 | 466 |
assert len(export['evolution'][0]['parts']) == 2 |
467 |
assert len(export['evolution'][0]['parts'][0]) == 1
|
|
467 |
assert len(export['evolution'][0]['parts'][0]) == 2
|
|
468 | 468 |
assert export['evolution'][0]['parts'][0]['type'] == 'workflow-comment' |
469 | 469 |
assert len(export['evolution'][0]['parts'][1]) == 1 |
470 | 470 |
assert export['evolution'][0]['parts'][1]['type'] == 'wscall-error' |
471 | 471 |
assert export['evolution'][1]['status'] == st_finished.id |
472 | 472 |
assert 'time' in export['evolution'][1] |
473 | 473 |
assert 'who' not in export['evolution'][0] |
474 | 474 |
assert 'parts' not in export['evolution'][1] |
475 | 475 |
tests/test_workflow_import.py | ||
---|---|---|
462 | 462 |
trigger.roles = [role.id] |
463 | 463 | |
464 | 464 |
wf2 = assert_import_export_works(wf) |
465 | 465 |
assert wf2.global_actions[0].triggers[0].roles == [role.id] |
466 | 466 | |
467 | 467 |
wf2 = assert_import_export_works(wf, True) |
468 | 468 | |
469 | 469 | |
470 |
def test_register_comment_to(pub): |
|
471 |
role = Role() |
|
472 |
role.id = '5' |
|
473 |
role.name = 'Test Role' |
|
474 |
role.store() |
|
475 | ||
476 |
wf = Workflow(name='global actions') |
|
477 |
st1 = wf.add_status('Status1', 'st1') |
|
478 | ||
479 |
add_to_journal1 = RegisterCommenterWorkflowStatusItem() |
|
480 |
add_to_journal1.id = '_add_to_journal1' |
|
481 |
add_to_journal1.comment = 'HELLO WORLD' |
|
482 |
st1.items.append(add_to_journal1) |
|
483 |
add_to_journal1.parent = st1 |
|
484 | ||
485 |
add_to_journal2 = RegisterCommenterWorkflowStatusItem() |
|
486 |
add_to_journal2.id = '_add_to_journal2' |
|
487 |
add_to_journal2.comment = 'OLA MUNDO' |
|
488 |
add_to_journal2.to = [role.id] |
|
489 |
st1.items.append(add_to_journal2) |
|
490 |
add_to_journal2.parent = st1 |
|
491 |
assert wf.possible_status[0].items[0].to == [] |
|
492 |
assert wf.possible_status[0].items[1].to == [role.id] |
|
493 | ||
494 |
xml_root = wf.export_to_xml() |
|
495 |
assert 'to' not in [x.tag for x in xml_root.findall('possible_status/status/items/item[1]/')] |
|
496 |
assert 'to' in [x.tag for x in xml_root.findall('possible_status/status/items/item[2]/')] |
|
497 | ||
498 |
wf2 = assert_import_export_works(wf) |
|
499 |
assert wf2.possible_status[0].items[0].to == [] |
|
500 |
assert wf2.possible_status[0].items[1].to == [role.id] |
|
501 | ||
502 | ||
470 | 503 |
def test_backoffice_fields(pub): |
471 | 504 |
wf = Workflow(name='bo fields') |
472 | 505 |
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf) |
473 | 506 |
wf.backoffice_fields_formdef.fields = [ |
474 | 507 |
StringField(id='bo1', label='1st backoffice field', |
475 | 508 |
type='string', varname='backoffice_blah'), |
476 | 509 |
] |
477 | 510 |
wf2 = assert_import_export_works(wf, True) |
tests/test_workflows.py | ||
---|---|---|
1104 | 1104 |
assert formdata.evolution[-1].parts[0].orig_filename == 'hello.txt' |
1105 | 1105 | |
1106 | 1106 |
assert isinstance(formdata.evolution[-1].parts[1], JournalEvolutionPart) |
1107 | 1107 |
assert len(formdata.evolution[-1].parts[1].content) > 0 |
1108 | 1108 |
comment_view = str(formdata.evolution[-1].parts[1].view()) |
1109 | 1109 |
assert comment_view == '<p>%s</p>' % comment_text |
1110 | 1110 | |
1111 | 1111 | |
1112 |
def test_register_comment_to(pub): |
|
1113 |
workflow = Workflow(name='register comment to') |
|
1114 |
st1 = workflow.add_status('Status1', 'st1') |
|
1115 | ||
1116 |
role = Role(name='foorole') |
|
1117 |
role.store() |
|
1118 |
role2 = Role(name='no-one-role') |
|
1119 |
role2.store() |
|
1120 |
user = pub.user_class(name='baruser') |
|
1121 |
user.roles = [] |
|
1122 |
user.store() |
|
1123 | ||
1124 |
FormDef.wipe() |
|
1125 |
formdef = FormDef() |
|
1126 |
formdef.url_name = 'foobar' |
|
1127 |
formdef._workflow = workflow |
|
1128 | ||
1129 |
formdata = formdef.data_class()() |
|
1130 |
formdata.just_created() |
|
1131 |
assert formdata.status == 'wf-st1' |
|
1132 |
formdata.store() |
|
1133 | ||
1134 |
register_commenter = RegisterCommenterWorkflowStatusItem() |
|
1135 |
register_commenter.parent = st1 |
|
1136 |
st1.items.append(register_commenter) |
|
1137 | ||
1138 |
def display_parts(): |
|
1139 |
formdata.evolution[-1]._display_parts = None # invalidate cache |
|
1140 |
return [str(x) for x in formdata.evolution[-1].display_parts()] |
|
1141 | ||
1142 |
register_commenter.comment = 'all' |
|
1143 |
register_commenter.to = None |
|
1144 |
register_commenter.perform(formdata) |
|
1145 |
assert len(formdata.evolution[-1].parts) == 1 |
|
1146 |
assert display_parts() == ['<p>all</p>'] |
|
1147 | ||
1148 |
register_commenter.comment = 'to-role' |
|
1149 |
register_commenter.to = [role.id] |
|
1150 |
register_commenter.perform(formdata) |
|
1151 |
assert len(formdata.evolution[-1].parts) == 2 |
|
1152 |
assert len(display_parts()) == 1 |
|
1153 |
pub._request._user = user |
|
1154 |
assert display_parts() == ['<p>all</p>'] |
|
1155 |
user.roles = [role.id] |
|
1156 |
assert display_parts() == ['<p>all</p>', '<p>to-role</p>'] |
|
1157 | ||
1158 |
user.roles = [] |
|
1159 |
register_commenter.comment = 'to-submitter' |
|
1160 |
register_commenter.to = ['_submitter'] |
|
1161 |
register_commenter.perform(formdata) |
|
1162 |
assert len(formdata.evolution[-1].parts) == 3 |
|
1163 |
assert display_parts() == ['<p>all</p>'] |
|
1164 |
formdata.user_id = user.id |
|
1165 |
assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>'] |
|
1166 | ||
1167 |
register_commenter.comment = 'to-role-or-submitter' |
|
1168 |
register_commenter.to = [role.id, '_submitter'] |
|
1169 |
register_commenter.perform(formdata) |
|
1170 |
assert len(formdata.evolution[-1].parts) == 4 |
|
1171 |
assert display_parts() == ['<p>all</p>', '<p>to-submitter</p>', '<p>to-role-or-submitter</p>'] |
|
1172 |
formdata.user_id = None |
|
1173 |
assert display_parts() == ['<p>all</p>'] |
|
1174 |
user.roles = [role.id] |
|
1175 |
assert display_parts() == ['<p>all</p>', '<p>to-role</p>', '<p>to-role-or-submitter</p>'] |
|
1176 |
formdata.user_id = user.id |
|
1177 |
assert display_parts() == [ |
|
1178 |
'<p>all</p>', '<p>to-role</p>', '<p>to-submitter</p>', '<p>to-role-or-submitter</p>'] |
|
1179 | ||
1180 |
register_commenter.comment = 'd1' |
|
1181 |
register_commenter.to = [role2.id] |
|
1182 |
register_commenter.perform(formdata) |
|
1183 |
assert len(formdata.evolution[-1].parts) == 5 |
|
1184 |
assert display_parts() == [ |
|
1185 |
'<p>all</p>', '<p>to-role</p>', '<p>to-submitter</p>', '<p>to-role-or-submitter</p>'] |
|
1186 |
register_commenter2 = RegisterCommenterWorkflowStatusItem() |
|
1187 |
register_commenter2.parent = st1 |
|
1188 |
st1.items.append(register_commenter2) |
|
1189 |
register_commenter2.comment = 'd2' |
|
1190 |
register_commenter2.to = [role.id, '_submitter'] |
|
1191 |
user.roles = [role.id, role2.id] |
|
1192 |
register_commenter2.perform(formdata) |
|
1193 |
assert len(formdata.evolution[-1].parts) == 6 |
|
1194 |
assert '<p>d1</p>' in [str(x) for x in display_parts()] |
|
1195 |
assert '<p>d2</p>' in [str(x) for x in display_parts()] |
|
1196 | ||
1197 | ||
1112 | 1198 |
def test_email(pub, emails): |
1113 | 1199 |
pub.substitutions.feed(MockSubstitutionVariables()) |
1114 | 1200 | |
1115 | 1201 |
formdef = FormDef() |
1116 | 1202 |
formdef.name = 'baz' |
1117 | 1203 |
formdef.fields = [] |
1118 | 1204 |
formdef.store() |
1119 | 1205 |
wcs/formdata.py | ||
---|---|---|
149 | 149 | |
150 | 150 |
if not self.parts: |
151 | 151 |
return [] |
152 | 152 | |
153 | 153 |
l = [] |
154 | 154 |
for p in self.parts: |
155 | 155 |
if not hasattr(p, 'view'): |
156 | 156 |
continue |
157 |
if hasattr(p, 'to') and not self.formdata.is_for_current_user(p.to): |
|
158 |
continue |
|
157 | 159 |
text = p.view() |
158 | 160 |
if text: |
159 | 161 |
l.append(text) |
160 | 162 |
self._display_parts = l |
161 | 163 |
return self._display_parts |
162 | 164 | |
163 | 165 |
def get_json_export_dict(self, user, anonymise=False): |
164 | 166 |
data = { |
wcs/sql.py | ||
---|---|---|
1802 | 1802 |
elif type(value) in (tuple, list): |
1803 | 1803 |
fts_strings.extend(value) |
1804 | 1804 |
if self._evolution: |
1805 | 1805 |
for evo in self._evolution: |
1806 | 1806 |
if evo.comment: |
1807 | 1807 |
fts_strings.append(evo.comment) |
1808 | 1808 |
for part in evo.parts or []: |
1809 | 1809 |
if hasattr(part, 'view'): |
1810 |
if hasattr(part, 'to') and not self.is_for_current_user(part.to): |
|
1811 |
continue |
|
1810 | 1812 |
html_part = part.view() |
1811 | 1813 |
if html_part: |
1812 | 1814 |
fts_strings.append(qommon.misc.html2text(html_part)) |
1813 | 1815 |
user = self.get_user() |
1814 | 1816 |
if user: |
1815 | 1817 |
fts_strings.append(user.get_display_name()) |
1816 | 1818 | |
1817 | 1819 |
sql_statement = '''UPDATE %s SET fts = to_tsvector( %%(fts)s) |
wcs/wf/register_comment.py | ||
---|---|---|
22 | 22 |
from wcs.workflows import (WorkflowStatusItem, register_item_class, template_on_formdata, |
23 | 23 |
AttachmentEvolutionPart) |
24 | 24 | |
25 | 25 |
import sys |
26 | 26 | |
27 | 27 | |
28 | 28 |
class JournalEvolutionPart: #pylint: disable=C1001 |
29 | 29 |
content = None |
30 |
to = [] |
|
30 | 31 | |
31 |
def __init__(self, formdata, message): |
|
32 |
def __init__(self, formdata, message, to):
|
|
32 | 33 |
if not message: |
33 | 34 |
return |
35 |
self.to = to |
|
34 | 36 |
if '{{' in message or '{%' in message: |
35 | 37 |
# django template |
36 | 38 |
content = template_on_formdata(formdata, message) |
37 | 39 |
if content and not content.startswith('<'): |
38 | 40 |
# add <div> to mark the string as processed as HTML |
39 | 41 |
content = '<div>%s</div>' % content |
40 | 42 |
self.content = content |
41 | 43 |
return |
... | ... | |
59 | 61 |
return htmltext('<p>') + \ |
60 | 62 |
htmltext('\n').join( |
61 | 63 |
[(x or htmltext('</p><p>')) for x in self.content.splitlines()]) + \ |
62 | 64 |
htmltext('</p>') |
63 | 65 | |
64 | 66 |
def get_json_export_dict(self, anonymise=False): |
65 | 67 |
d = { |
66 | 68 |
'type': 'workflow-comment', |
69 |
'to': self.to, |
|
67 | 70 |
} |
68 | 71 |
if not anonymise: |
69 | 72 |
d['content'] = self.content |
70 | 73 |
return d |
71 | 74 | |
72 | 75 | |
73 | 76 |
class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem): |
74 | 77 |
description = N_('History Message') |
75 | 78 |
key = 'register-comment' |
76 | 79 |
category = 'interaction' |
77 | 80 | |
78 | 81 |
comment = None |
82 |
to = [] |
|
79 | 83 |
attachments = None |
80 | 84 | |
81 | 85 |
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None): |
82 | 86 |
super(RegisterCommenterWorkflowStatusItem, self).add_parameters_widgets( |
83 | 87 |
form, parameters, prefix=prefix, formdef=formdef) |
84 | 88 |
if 'comment' in parameters: |
85 | 89 |
form.add(TextWidget, '%scomment' % prefix, title=_('Message'), |
86 | 90 |
value=self.comment, cols=80, rows=10) |
91 |
if 'to' in parameters: |
|
92 |
form.add(WidgetList, '%sto' % prefix, title=_('To'), |
|
93 |
element_type=SingleSelectWidget, |
|
94 |
value=self.to or [], |
|
95 |
add_element_label=self.get_add_role_label(), |
|
96 |
element_kwargs={'render_br': False, |
|
97 |
'options': [(None, '---', None)] + |
|
98 |
self.get_list_of_roles(include_logged_in_users=False)}) |
|
87 | 99 | |
88 | 100 |
def get_parameters(self): |
89 |
return ('comment', 'attachments', 'condition') |
|
101 |
return ('comment', 'to', 'attachments', 'condition')
|
|
90 | 102 | |
91 | 103 |
def attach_uploads_to_formdata(self, formdata, uploads): |
92 | 104 |
if not formdata.evolution[-1].parts: |
93 | 105 |
formdata.evolution[-1].parts = [] |
94 | 106 |
for upload in uploads: |
95 | 107 |
try: |
96 | 108 |
# useless but required to restore upload.fp from serialized state, |
97 | 109 |
# needed by AttachmentEvolutionPart.from_upload() |
... | ... | |
110 | 122 |
# (with substitution vars) |
111 | 123 |
if self.attachments: |
112 | 124 |
uploads = self.convert_attachments_to_uploads() |
113 | 125 |
self.attach_uploads_to_formdata(formdata, uploads) |
114 | 126 |
formdata.store() # store and invalidate cache, so references can be used in the comment message. |
115 | 127 | |
116 | 128 |
# the comment can use attachments done above |
117 | 129 |
try: |
118 |
formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment)) |
|
130 |
formdata.evolution[-1].add_part(JournalEvolutionPart(formdata, self.comment, self.to))
|
|
119 | 131 |
formdata.store() |
120 | 132 |
except TemplateError as e: |
121 | 133 |
url = formdata.get_url() |
122 | 134 |
get_logger().error('error in template for comment [%s], ' |
123 | 135 |
'comment could not be generated: %s' % (url, str(e))) |
124 | 136 | |
125 | 137 | |
126 | 138 |
register_item_class(RegisterCommenterWorkflowStatusItem) |
127 |
- |