0001-backoffice-create-display-user-label-from-data-field.patch
tests/test_backoffice_pages.py | ||
---|---|---|
2826 | 2826 |
assert resp.body[resp.body.index('<tbody'):].count('<tr') == 0 |
2827 | 2827 |
assert not 'form-title' in resp.body |
2828 | 2828 | |
2829 |
def test_global_listing_user_label(pub): |
|
2830 |
if not pub.is_using_postgresql(): |
|
2831 |
pytest.skip('this requires SQL') |
|
2832 |
return |
|
2833 | ||
2834 |
create_user(pub) |
|
2835 |
FormDef.wipe() |
|
2836 | ||
2837 |
from wcs.admin.settings import UserFieldsFormDef |
|
2838 |
user_formdef = UserFieldsFormDef(pub) |
|
2839 |
user_formdef.fields.append(fields.StringField(id='3', label='first_name', type='string')) |
|
2840 |
user_formdef.fields.append(fields.StringField(id='4', label='last_name', type='string')) |
|
2841 |
user_formdef.store() |
|
2842 |
pub.cfg['users']['field_name'] = ['3', '4'] |
|
2843 |
pub.write_cfg() |
|
2844 | ||
2845 |
formdef = FormDef() |
|
2846 |
formdef.name = 'foobar' |
|
2847 |
formdef.url_name = 'foobar' |
|
2848 |
formdef.workflow_roles = {'_receiver': 1} |
|
2849 |
formdef.fields = [ |
|
2850 |
fields.StringField(id='1', label='first_name', |
|
2851 |
prefill={'type': 'user', 'value': '3'}), |
|
2852 |
fields.StringField(id='2', label='last_name', |
|
2853 |
prefill={'type': 'user', 'value': '4'}), |
|
2854 |
] |
|
2855 |
formdef.store() |
|
2856 | ||
2857 |
formdata = formdef.data_class()() |
|
2858 |
formdata.data = {'1': 'blah', '2': 'xxx'} |
|
2859 |
formdata.just_created() |
|
2860 |
formdata.store() |
|
2861 |
formdata.jump_status('new') |
|
2862 | ||
2863 |
app = login(get_app(pub)) |
|
2864 |
resp = app.get('/backoffice/management/').follow() |
|
2865 |
resp = resp.click('Global View') |
|
2866 |
assert '<td class="cell-user">blah xxx</td>' in resp.body |
|
2829 | 2867 | |
2830 | 2868 |
def test_management_views_with_no_formdefs(pub): |
2831 | 2869 |
if not pub.is_using_postgresql(): |
tests/test_formdata.py | ||
---|---|---|
1618 | 1618 |
for mode in (None, 'lazy'): |
1619 | 1619 |
context = pub.substitutions.get_context_variables(mode=mode) |
1620 | 1620 |
assert tmpl.render(context) == '' |
1621 | ||
1622 |
def test_user_label(pub): |
|
1623 |
from wcs.admin.settings import UserFieldsFormDef |
|
1624 |
user_formdef = UserFieldsFormDef(pub) |
|
1625 |
user_formdef.fields.append(fields.StringField(id='3', label='first_name', type='string')) |
|
1626 |
user_formdef.fields.append(fields.StringField(id='4', label='last_name', type='string')) |
|
1627 |
user_formdef.store() |
|
1628 |
pub.cfg['users']['field_name'] = ['3', '4'] |
|
1629 |
pub.write_cfg() |
|
1630 | ||
1631 |
formdef = FormDef() |
|
1632 |
formdef.name = 'foobar' |
|
1633 |
formdef.url_name = 'foobar' |
|
1634 |
formdef.fields = [ |
|
1635 |
fields.StringField(id='1', label='first_name', |
|
1636 |
prefill={'type': 'user', 'value': '3'}), |
|
1637 |
fields.StringField(id='2', label='last_name', |
|
1638 |
prefill={'type': 'user', 'value': '4'}), |
|
1639 |
] |
|
1640 |
formdef.store() |
|
1641 | ||
1642 |
user = pub.user_class() |
|
1643 |
user.email = 'bar@localhost' |
|
1644 |
user.store() |
|
1645 | ||
1646 |
formdata = formdef.data_class()() |
|
1647 |
formdata.data = {} |
|
1648 |
formdata.user_id = user.id |
|
1649 |
formdata.store() |
|
1650 | ||
1651 |
assert str(formdef.data_class().get(formdata.id).user_id) == str(user.id) |
|
1652 |
assert formdef.data_class().get(formdata.id).user_label is None |
|
1653 |
assert formdef.data_class().get(formdata.id).get_user_label() == 'bar@localhost' |
|
1654 | ||
1655 |
formdata = formdef.data_class()() |
|
1656 |
formdata.data = {} |
|
1657 |
formdata.store() |
|
1658 | ||
1659 |
assert formdef.data_class().get(formdata.id).user_id is None |
|
1660 |
assert formdef.data_class().get(formdata.id).user_label == '' |
|
1661 |
assert formdef.data_class().get(formdata.id).get_user_label() == '' |
|
1662 | ||
1663 |
formdata = formdef.data_class()() |
|
1664 |
formdata.data = {'1': 'blah'} |
|
1665 |
formdata.store() |
|
1666 | ||
1667 |
assert formdef.data_class().get(formdata.id).user_id is None |
|
1668 |
assert formdef.data_class().get(formdata.id).user_label == 'blah' |
|
1669 |
assert formdef.data_class().get(formdata.id).get_user_label() == 'blah' |
|
1670 | ||
1671 |
formdata = formdef.data_class()() |
|
1672 |
formdata.data = {'1': 'blah', '2': 'xxx'} |
|
1673 |
formdata.store() |
|
1674 | ||
1675 |
assert formdef.data_class().get(formdata.id).user_id is None |
|
1676 |
assert formdef.data_class().get(formdata.id).user_label == 'blah xxx' |
|
1677 |
assert formdef.data_class().get(formdata.id).get_user_label() == 'blah xxx' |
wcs/backoffice/management.py | ||
---|---|---|
903 | 903 |
formdata.receipt_time) |
904 | 904 |
r += htmltext('<td class="cell-time">%s</td>') % misc.localstrftime( |
905 | 905 |
formdata.last_update_time) |
906 |
try:
|
|
907 |
value = get_publisher().user_class.get(formdata.user_id).display_name
|
|
906 |
value = formdata.get_user_label()
|
|
907 |
if value:
|
|
908 | 908 |
r += htmltext('<td class="cell-user">%s</td>') % value |
909 |
except:
|
|
909 |
else:
|
|
910 | 910 |
r += htmltext('<td class="cell-user cell-no-user">-</td>') |
911 | 911 |
r += htmltext('<td class="cell-status">%s</td>') % formdata.get_status_label() |
912 | 912 |
r += htmltext('</tr>\n') |
wcs/formdata.py | ||
---|---|---|
29 | 29 |
from qommon.storage import StorableObject, Intersects, Contains |
30 | 30 |
import qommon.misc |
31 | 31 |
from qommon.evalutils import make_datetime |
32 |
from qommon.publisher import get_cfg |
|
32 | 33 |
from qommon.substitution import Substitutions, invalidate_substitution_cache |
33 | 34 |
from qommon.template import Template |
34 | 35 | |
... | ... | |
245 | 246 |
id_display = None |
246 | 247 | |
247 | 248 |
user_id = None |
249 |
user_label = None # taken from data, for anonymous users |
|
248 | 250 |
receipt_time = None |
249 | 251 |
status = None |
250 | 252 |
anonymised = None |
... | ... | |
323 | 325 |
self.user_id = None |
324 | 326 |
user = property(get_user, set_user) |
325 | 327 | |
328 |
def get_user_label(self): |
|
329 |
user = self.user |
|
330 |
if user: |
|
331 |
return user.get_display_name() |
|
332 |
return self.user_label |
|
333 | ||
326 | 334 |
def has_empty_data(self): |
327 | 335 |
empty = True |
328 | 336 |
for key in self.data or {}: |
... | ... | |
386 | 394 |
# only set id_display once as it may have been set automatically |
387 | 395 |
# by interpreting a webservice response. |
388 | 396 |
fields['id_display'] = self.formdef.get_display_id_format().strip() |
397 | ||
389 | 398 |
changed = False |
399 | ||
400 |
users_cfg = get_cfg('users', {}) |
|
401 |
if not self.user_id and users_cfg and users_cfg.get('field_name'): |
|
402 |
field_name_values = users_cfg.get('field_name') |
|
403 |
form_user_data = {} |
|
404 |
for field in self.formdef.fields: |
|
405 |
if not hasattr(field, 'prefill'): |
|
406 |
continue |
|
407 |
if field.prefill and field.prefill.get('type') == 'user': |
|
408 |
form_user_data[field.prefill['value']] = self.data.get(field.id) |
|
409 |
user_label = ' '.join([form_user_data.get(x) for x in field_name_values if form_user_data.get(x)]) |
|
410 |
if user_label != self.user_label: |
|
411 |
self.user_label = user_label |
|
412 |
changed = True |
|
413 | ||
390 | 414 |
if any(fields.values()): |
391 | 415 |
context = self.get_substitution_variables() |
392 | 416 |
context['formdef_id'] = self.formdef.id |
... | ... | |
610 | 634 |
if field.type == 'last_update_time': |
611 | 635 |
return qommon.misc.localstrftime(self.last_update_time) |
612 | 636 |
if field.type == 'user-label': |
613 |
try: |
|
614 |
return get_publisher().user_class.get(self.user_id).display_name |
|
615 |
except KeyError: |
|
616 |
return '-' |
|
637 |
return self.get_user_label() or '-' |
|
617 | 638 |
if field.type == 'status': |
618 | 639 |
return self.get_status_label() |
619 | 640 |
if field.type == 'submission_channel': |
... | ... | |
932 | 953 | |
933 | 954 |
self.anonymised = datetime.datetime.now() |
934 | 955 |
self.user_id = None |
956 |
self.user_label = None |
|
935 | 957 |
self.editable_by = None |
936 | 958 |
self.workflow_data = None |
937 | 959 |
self.workflow_roles = None |
wcs/sql.py | ||
---|---|---|
403 | 403 |
'actions_roles_array', 'backoffice_submission', |
404 | 404 |
'submission_context', 'submission_channel', |
405 | 405 |
'criticality_level', 'last_update_time', |
406 |
'digest']) |
|
406 |
'digest', 'user_label'])
|
|
407 | 407 | |
408 | 408 |
# migrations |
409 | 409 |
if not 'fts' in existing_fields: |
... | ... | |
447 | 447 |
if not 'digest' in existing_fields: |
448 | 448 |
cur.execute('''ALTER TABLE %s ADD COLUMN digest varchar''' % table_name) |
449 | 449 | |
450 |
if not 'user_label' in existing_fields: |
|
451 |
cur.execute('''ALTER TABLE %s ADD COLUMN user_label varchar''' % table_name) |
|
452 | ||
450 | 453 |
# add new fields |
451 | 454 |
for field in formdef.get_all_fields(): |
452 | 455 |
assert field.id is not None |
... | ... | |
733 | 736 |
view_fields.append(("int '%s'" % (formdef.id or 0), 'formdef_id')) |
734 | 737 |
for field in ('id', 'user_id', 'receipt_time', 'status', |
735 | 738 |
'id_display', 'submission_channel', 'backoffice_submission', |
736 |
'last_update_time', 'digest'): |
|
739 |
'last_update_time', 'digest', 'user_label'):
|
|
737 | 740 |
view_fields.append((field, field)) |
738 | 741 |
return view_fields |
739 | 742 | |
... | ... | |
1207 | 1210 |
('criticality_level', 'int'), |
1208 | 1211 |
('last_update_time', 'timestamp'), |
1209 | 1212 |
('digest', 'varchar'), |
1213 |
('user_label', 'varchar'), |
|
1210 | 1214 |
] |
1211 | 1215 | |
1212 | 1216 |
def __init__(self, id=None): |
... | ... | |
1363 | 1367 |
if self.set_auto_fields(): |
1364 | 1368 |
sql_statement = '''UPDATE %s |
1365 | 1369 |
SET id_display = %%(id_display)s, |
1366 |
digest = %%(digest)s |
|
1370 |
digest = %%(digest)s, |
|
1371 |
user_label = %%(user_label)s |
|
1367 | 1372 |
WHERE id = %%(id)s''' % self._table_name |
1368 | 1373 |
cur.execute(sql_statement, { |
1369 | 1374 |
'id': self.id, |
1370 | 1375 |
'id_display': self.id_display, |
1371 | 1376 |
'digest': self.digest, |
1377 |
'user_label': self.user_label, |
|
1372 | 1378 |
}) |
1373 | 1379 | |
1374 | 1380 |
if self._evolution: |
... | ... | |
2168 | 2174 |
return result |
2169 | 2175 | |
2170 | 2176 | |
2171 |
SQL_LEVEL = 30
|
|
2177 |
SQL_LEVEL = 31
|
|
2172 | 2178 | |
2173 | 2179 |
def migrate_global_views(conn, cur): |
2174 | 2180 |
cur.execute('''SELECT COUNT(*) FROM information_schema.tables |
... | ... | |
2235 | 2241 |
raise RuntimeError() |
2236 | 2242 |
if sql_level < 1: # 1: introduction of tracking_code table |
2237 | 2243 |
do_tracking_code_table() |
2238 |
if sql_level < 27:
|
|
2244 |
if sql_level < 31:
|
|
2239 | 2245 |
# 2: introduction of formdef_id in views |
2240 | 2246 |
# 5: add concerned_roles_array, is_at_endpoint and fts to views |
2241 | 2247 |
# 7: add backoffice_submission to tables |
... | ... | |
2251 | 2257 |
# 22: rebuild views |
2252 | 2258 |
# 26: add digest to formdata |
2253 | 2259 |
# 27: add last_jump_datetime in evolutions tables |
2260 |
# 31: add user_label to formdata |
|
2254 | 2261 |
migrate_views(conn, cur) |
2255 | 2262 |
if sql_level < 21: |
2256 | 2263 |
# 3: introduction of _structured for user fields |
... | ... | |
2270 | 2277 |
# 21: (second part), store ascii_name of users |
2271 | 2278 |
# 23: (first part), use misc.simplify() over full text queries |
2272 | 2279 |
set_reindex('user', 'needed', conn=conn, cur=cur) |
2273 |
if sql_level < 28:
|
|
2280 |
if sql_level < 31:
|
|
2274 | 2281 |
# 17: store last_update_time in tables |
2275 | 2282 |
# 18: add user name to full-text search index |
2276 | 2283 |
# 21: (third part), add user ascii_names to full-text index |
2277 | 2284 |
# 23: (second part) use misc.simplify() over full text queries |
2278 | 2285 |
# 28: add display id and formdef name to full-text index |
2279 | 2286 |
# 29: add evolution parts to full-text index |
2287 |
# 31: add user_label to formdata |
|
2280 | 2288 |
set_reindex('formdata', 'needed', conn=conn, cur=cur) |
2281 | 2289 |
if sql_level < 24: |
2282 | 2290 |
from wcs.formdef import FormDef |
2283 |
- |