backoffice: create/display user label from data fields (#33812)

This commit is contained in:
Frédéric Péters 2019-06-08 14:36:35 +02:00
parent b35f425223
commit f14115483d
5 changed files with 138 additions and 13 deletions

View File

@ -2818,6 +2818,44 @@ def test_global_listing(pub):
assert resp.body[resp.body.index('<tbody'):].count('<tr') == 0
assert not 'form-title' in resp.body
def test_global_listing_user_label(pub):
if not pub.is_using_postgresql():
pytest.skip('this requires SQL')
return
create_user(pub)
FormDef.wipe()
from wcs.admin.settings import UserFieldsFormDef
user_formdef = UserFieldsFormDef(pub)
user_formdef.fields.append(fields.StringField(id='3', label='first_name', type='string'))
user_formdef.fields.append(fields.StringField(id='4', label='last_name', type='string'))
user_formdef.store()
pub.cfg['users']['field_name'] = ['3', '4']
pub.write_cfg()
formdef = FormDef()
formdef.name = 'foobar'
formdef.url_name = 'foobar'
formdef.workflow_roles = {'_receiver': 1}
formdef.fields = [
fields.StringField(id='1', label='first_name',
prefill={'type': 'user', 'value': '3'}),
fields.StringField(id='2', label='last_name',
prefill={'type': 'user', 'value': '4'}),
]
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'1': 'blah', '2': 'xxx'}
formdata.just_created()
formdata.store()
formdata.jump_status('new')
app = login(get_app(pub))
resp = app.get('/backoffice/management/').follow()
resp = resp.click('Global View')
assert '<td class="cell-user">blah xxx</td>' in resp.body
def test_management_views_with_no_formdefs(pub):
if not pub.is_using_postgresql():

View File

@ -1618,3 +1618,60 @@ def test_string_filters(pub, variable_test_data):
for mode in (None, 'lazy'):
context = pub.substitutions.get_context_variables(mode=mode)
assert tmpl.render(context) == ''
def test_user_label(pub):
from wcs.admin.settings import UserFieldsFormDef
user_formdef = UserFieldsFormDef(pub)
user_formdef.fields.append(fields.StringField(id='3', label='first_name', type='string'))
user_formdef.fields.append(fields.StringField(id='4', label='last_name', type='string'))
user_formdef.store()
pub.cfg['users']['field_name'] = ['3', '4']
pub.write_cfg()
formdef = FormDef()
formdef.name = 'foobar'
formdef.url_name = 'foobar'
formdef.fields = [
fields.StringField(id='1', label='first_name',
prefill={'type': 'user', 'value': '3'}),
fields.StringField(id='2', label='last_name',
prefill={'type': 'user', 'value': '4'}),
]
formdef.store()
user = pub.user_class()
user.email = 'bar@localhost'
user.store()
formdata = formdef.data_class()()
formdata.data = {}
formdata.user_id = user.id
formdata.store()
assert str(formdef.data_class().get(formdata.id).user_id) == str(user.id)
assert formdef.data_class().get(formdata.id).user_label is None
assert formdef.data_class().get(formdata.id).get_user_label() == 'bar@localhost'
formdata = formdef.data_class()()
formdata.data = {}
formdata.store()
assert formdef.data_class().get(formdata.id).user_id is None
assert formdef.data_class().get(formdata.id).user_label == ''
assert formdef.data_class().get(formdata.id).get_user_label() == ''
formdata = formdef.data_class()()
formdata.data = {'1': 'blah'}
formdata.store()
assert formdef.data_class().get(formdata.id).user_id is None
assert formdef.data_class().get(formdata.id).user_label == 'blah'
assert formdef.data_class().get(formdata.id).get_user_label() == 'blah'
formdata = formdef.data_class()()
formdata.data = {'1': 'blah', '2': 'xxx'}
formdata.store()
assert formdef.data_class().get(formdata.id).user_id is None
assert formdef.data_class().get(formdata.id).user_label == 'blah xxx'
assert formdef.data_class().get(formdata.id).get_user_label() == 'blah xxx'

View File

@ -899,10 +899,10 @@ class ManagementDirectory(Directory):
formdata.receipt_time)
r += htmltext('<td class="cell-time">%s</td>') % misc.localstrftime(
formdata.last_update_time)
try:
value = get_publisher().user_class.get(formdata.user_id).display_name
value = formdata.get_user_label()
if value:
r += htmltext('<td class="cell-user">%s</td>') % value
except:
else:
r += htmltext('<td class="cell-user cell-no-user">-</td>')
r += htmltext('<td class="cell-status">%s</td>') % formdata.get_status_label()
r += htmltext('</tr>\n')

View File

@ -29,6 +29,7 @@ from qommon import _
from qommon.storage import StorableObject, Intersects, Contains
import qommon.misc
from qommon.evalutils import make_datetime
from qommon.publisher import get_cfg
from qommon.substitution import Substitutions, invalidate_substitution_cache
from qommon.template import Template
@ -245,6 +246,7 @@ class FormData(StorableObject):
id_display = None
user_id = None
user_label = None # taken from data, for anonymous users
receipt_time = None
status = None
anonymised = None
@ -323,6 +325,12 @@ class FormData(StorableObject):
self.user_id = None
user = property(get_user, set_user)
def get_user_label(self):
user = self.user
if user:
return user.get_display_name()
return self.user_label
def has_empty_data(self):
empty = True
for key in self.data or {}:
@ -386,7 +394,23 @@ class FormData(StorableObject):
# only set id_display once as it may have been set automatically
# by interpreting a webservice response.
fields['id_display'] = self.formdef.get_display_id_format().strip()
changed = False
users_cfg = get_cfg('users', {})
if not self.user_id and users_cfg and users_cfg.get('field_name'):
field_name_values = users_cfg.get('field_name')
form_user_data = {}
for field in self.formdef.fields:
if not hasattr(field, 'prefill'):
continue
if field.prefill and field.prefill.get('type') == 'user':
form_user_data[field.prefill['value']] = self.data.get(field.id)
user_label = ' '.join([form_user_data.get(x) for x in field_name_values if form_user_data.get(x)])
if user_label != self.user_label:
self.user_label = user_label
changed = True
if any(fields.values()):
context = self.get_substitution_variables()
context['formdef_id'] = self.formdef.id
@ -610,10 +634,7 @@ class FormData(StorableObject):
if field.type == 'last_update_time':
return qommon.misc.localstrftime(self.last_update_time)
if field.type == 'user-label':
try:
return get_publisher().user_class.get(self.user_id).display_name
except KeyError:
return '-'
return self.get_user_label() or '-'
if field.type == 'status':
return self.get_status_label()
if field.type == 'submission_channel':
@ -935,6 +956,7 @@ class FormData(StorableObject):
self.anonymised = datetime.datetime.now()
self.user_id = None
self.user_label = None
self.editable_by = None
self.workflow_data = None
self.workflow_roles = None

View File

@ -403,7 +403,7 @@ def do_formdef_tables(formdef, conn=None, cur=None, rebuild_views=False, rebuild
'actions_roles_array', 'backoffice_submission',
'submission_context', 'submission_channel',
'criticality_level', 'last_update_time',
'digest'])
'digest', 'user_label'])
# migrations
if not 'fts' in existing_fields:
@ -447,6 +447,9 @@ def do_formdef_tables(formdef, conn=None, cur=None, rebuild_views=False, rebuild
if not 'digest' in existing_fields:
cur.execute('''ALTER TABLE %s ADD COLUMN digest varchar''' % table_name)
if not 'user_label' in existing_fields:
cur.execute('''ALTER TABLE %s ADD COLUMN user_label varchar''' % table_name)
# add new fields
for field in formdef.get_all_fields():
assert field.id is not None
@ -733,7 +736,7 @@ def get_view_fields(formdef):
view_fields.append(("int '%s'" % (formdef.id or 0), 'formdef_id'))
for field in ('id', 'user_id', 'receipt_time', 'status',
'id_display', 'submission_channel', 'backoffice_submission',
'last_update_time', 'digest'):
'last_update_time', 'digest', 'user_label'):
view_fields.append((field, field))
return view_fields
@ -1207,6 +1210,7 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
('criticality_level', 'int'),
('last_update_time', 'timestamp'),
('digest', 'varchar'),
('user_label', 'varchar'),
]
def __init__(self, id=None):
@ -1363,12 +1367,14 @@ class SqlFormData(SqlMixin, wcs.formdata.FormData):
if self.set_auto_fields():
sql_statement = '''UPDATE %s
SET id_display = %%(id_display)s,
digest = %%(digest)s
digest = %%(digest)s,
user_label = %%(user_label)s
WHERE id = %%(id)s''' % self._table_name
cur.execute(sql_statement, {
'id': self.id,
'id_display': self.id_display,
'digest': self.digest,
'user_label': self.user_label,
})
if self._evolution:
@ -2168,7 +2174,7 @@ def get_yearly_totals(period_start=None, period_end=None, criterias=None):
return result
SQL_LEVEL = 30
SQL_LEVEL = 31
def migrate_global_views(conn, cur):
cur.execute('''SELECT COUNT(*) FROM information_schema.tables
@ -2235,7 +2241,7 @@ def migrate():
raise RuntimeError()
if sql_level < 1: # 1: introduction of tracking_code table
do_tracking_code_table()
if sql_level < 27:
if sql_level < 31:
# 2: introduction of formdef_id in views
# 5: add concerned_roles_array, is_at_endpoint and fts to views
# 7: add backoffice_submission to tables
@ -2251,6 +2257,7 @@ def migrate():
# 22: rebuild views
# 26: add digest to formdata
# 27: add last_jump_datetime in evolutions tables
# 31: add user_label to formdata
migrate_views(conn, cur)
if sql_level < 21:
# 3: introduction of _structured for user fields
@ -2270,13 +2277,14 @@ def migrate():
# 21: (second part), store ascii_name of users
# 23: (first part), use misc.simplify() over full text queries
set_reindex('user', 'needed', conn=conn, cur=cur)
if sql_level < 28:
if sql_level < 31:
# 17: store last_update_time in tables
# 18: add user name to full-text search index
# 21: (third part), add user ascii_names to full-text index
# 23: (second part) use misc.simplify() over full text queries
# 28: add display id and formdef name to full-text index
# 29: add evolution parts to full-text index
# 31: add user_label to formdata
set_reindex('formdata', 'needed', conn=conn, cur=cur)
if sql_level < 24:
from wcs.formdef import FormDef