settings: configure user search result template (#51343)

This commit is contained in:
Lauréline Guérin 2021-03-30 10:16:20 +02:00
parent 1b215ec7fd
commit 824dce61dc
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
6 changed files with 121 additions and 33 deletions

View File

@ -354,8 +354,8 @@ def test_settings_user(pub):
resp = app.get('/backoffice/settings/users').follow().follow()
# add a field
resp.forms[2]['label'] = 'foobar'
resp = resp.forms[2].submit()
resp.forms[3]['label'] = 'foobar'
resp = resp.forms[3].submit()
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
resp = resp.follow()
assert b'foobar' in pub.cfg['users']['formdef']
@ -376,9 +376,9 @@ def test_settings_user(pub):
assert pub.cfg['users']['field_email'] is None
# add a comment field
resp.forms[2]['label'] = 'barfoo'
resp.forms[2]['type'] = 'comment'
resp = resp.forms[2].submit()
resp.forms[3]['label'] = 'barfoo'
resp.forms[3]['type'] = 'comment'
resp = resp.forms[3].submit()
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
resp = resp.follow()
assert b'barfoo' in pub.cfg['users']['formdef']
@ -409,6 +409,22 @@ def test_settings_user(pub):
assert pub.cfg['users']['sidebar_template'] == 'hello {{ form_user_display_name }}'
assert 'syntax error in Django template' in resp
# set a search result template
resp = app.get('/backoffice/settings/users/fields/')
assert 'search_result_template' not in pub.cfg['users']
assert resp.forms['search_result_template']['search_result_template'].value.replace('\n', '') == (
'{{ user_email|default:"" }}'
'{% if user_var_phone %} 📞 {{ user_var_phone }}{% endif %}'
'{% if user_var_mobile %} 📱 {{ user_var_mobile }}{% endif %}'
'{% if user_var_address or user_var_zipcode or user_var_city %} 📨{% endif %}'
'{% if user_var_address %} {{ user_var_address }}{% endif %}'
'{% if user_var_zipcode %} {{ user_var_zipcode }}{% endif %}'
'{% if user_var_city %} {{ user_var_city }}{% endif %}'
)
resp.forms['search_result_template']['search_result_template'] = '{{ user_email|default:"" }} Foo Bar'
resp = resp.forms['search_result_template'].submit().follow()
assert pub.cfg['users']['search_result_template'] == '{{ user_email|default:"" }} Foo Bar'
# disable users screen
if not pub.site_options.has_section('options'):
pub.site_options.add_section('options')

View File

@ -8,6 +8,7 @@ from quixote import get_publisher
from utilities import clean_temporary_pub, create_temporary_pub, get_app
from wcs import fields
from wcs.admin.settings import UserFieldsFormDef
from wcs.formdef import FormDef
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.ident.password_accounts import PasswordAccount
@ -121,8 +122,6 @@ def test_users(pub, local_user):
resp = get_app(pub).get(sign_uri('/api/users/?q=foobar'))
assert len(resp.json['data']) == 0
from wcs.admin.settings import UserFieldsFormDef
formdef = UserFieldsFormDef(pub)
formdef.fields.append(fields.StringField(id='3', label='test', type='string'))
formdef.store()
@ -157,6 +156,48 @@ def test_users_unaccent(pub, local_user):
assert len(resp.json['data']) == 0
def test_users_description(pub, local_user):
assert 'users' not in pub.cfg
formdef = UserFieldsFormDef(pub)
formdef.fields = [
fields.StringField(id='1', label='phone', type='string', varname='phone'),
fields.StringField(id='2', label='mobile', type='string', varname='mobile'),
fields.StringField(id='3', label='address', type='string', varname='address'),
fields.StringField(id='4', label='zipcode', type='string', varname='zipcode'),
fields.StringField(id='5', label='city', type='string', varname='city'),
]
formdef.store()
local_user.form_data = {
'1': '0505050505',
'2': '0606060606',
'3': 'rue du Chateau',
'4': '75014',
'5': 'PARIS',
}
local_user.set_attributes_from_formdata(local_user.form_data)
local_user.store()
resp = get_app(pub).get(sign_uri('/api/users/'))
assert resp.json['data'][0]['user_id'] == local_user.id
assert (
resp.json['data'][0]['description'].replace('\n', '')
== 'jean.darmette@triffouilis.fr 📞 0505050505 📱 0606060606 📨 rue du Chateau 75014 PARIS'
)
pub.cfg['users'][
'search_result_template'
] = """{{ user_email|default:"" }}{% if user_var_phone %} 📞 {{ user_var_phone }}{% endif %} foo bar"""
pub.write_cfg()
resp = get_app(pub).get(sign_uri('/api/users/'))
assert resp.json['data'][0]['user_id'] == local_user.id
assert (
resp.json['data'][0]['description'].replace('\n', '')
== 'jean.darmette@triffouilis.fr 📞 0505050505 foo bar'
)
def test_user_by_nameid(pub, local_user):
resp = get_app(pub).get(sign_uri('/api/users/xyz/', user=local_user), status=404)
local_user.name_identifiers = ['xyz']

View File

@ -136,7 +136,7 @@ class UserFieldDefPage(FieldDefPage):
class UserFieldsDirectory(FieldsDirectory):
_q_exports = ['', 'update_order', 'new', 'mapping', 'template']
_q_exports = ['', 'update_order', 'new', 'mapping', 'template', 'search_result_template']
section = 'settings'
field_def_page_class = UserFieldDefPage
@ -158,6 +158,10 @@ class UserFieldsDirectory(FieldsDirectory):
r += htmltext('<h2>%s</h2>') % _('Sidebar Template')
r += self.sidebar_template_form().render()
r += htmltext('</div>')
r += htmltext('<div class="bo-block">')
r += htmltext('<h2>%s</h2>') % _('User search result template')
r += self.search_result_template_form().render()
r += htmltext('</div>')
return r.getvalue()
def mapping_form(self):
@ -214,6 +218,30 @@ class UserFieldsDirectory(FieldsDirectory):
cfg_submit(form, 'users', ['sidebar_template'])
return redirect('.')
@classmethod
def search_result_template_form(cls, action='search_result_template'):
users_cfg = get_cfg('users', {})
form = Form(action=action, id='search_result_template')
form.add(
TextWidget,
'search_result_template',
value=users_cfg.get('search_result_template')
or get_publisher().user_class.default_search_result_template,
required=False,
validation_function=ComputedExpressionWidget.validate_template,
rows=7,
)
form.add_submit('submit', _('Submit'))
return form
def search_result_template(self):
form = self.search_result_template_form()
if form.has_errors():
get_session().message = ('error', form.get_widget('search_result_template').get_error())
return redirect('.')
cfg_submit(form, 'users', ['search_result_template'])
return redirect('.')
class UserFieldsFormDef(FormDef):
"""Class to handle custom user fields, it loads and saves from/to

View File

@ -37,6 +37,7 @@ from wcs.data_sources import NamedDataSource
from wcs.data_sources import get_object as get_data_source_object
from wcs.formdef import FormDef
from wcs.forms.common import FormStatusPage
from wcs.qommon import get_cfg
from wcs.qommon.afterjobs import AfterJob
from wcs.roles import logged_users_role
@ -53,6 +54,7 @@ from .qommon.errors import (
)
from .qommon.form import ComputedExpressionWidget
from .qommon.storage import Equal, NotEqual
from .qommon.template import Template, TemplateError
def posted_json_data_to_formdata_data(formdef, data):
@ -970,6 +972,12 @@ class ApiUsersDirectory(Directory):
criterias.append(st.Or(criteria_fields))
def as_dict(user):
users_cfg = get_cfg('users', {})
template = (
users_cfg.get('search_result_template')
or get_publisher().user_class.default_search_result_template
)
user_info = user.get_substitution_variables(prefix='')
del user_info['user']
user_info['user_id'] = user.id
@ -978,6 +986,11 @@ class ApiUsersDirectory(Directory):
# add attributes to be usable as datasource
user_info['id'] = user.id
user_info['text'] = user_info['user_display_name']
if Template.is_template_string(template):
try:
user_info['description'] = Template(template).render(user_info)
except TemplateError:
pass
return user_info
limit = misc.get_int_or_400(get_request().form.get('limit'))

View File

@ -159,33 +159,15 @@ $(function() {
},
placeholder: '-',
templateResult: function (state) {
console.log(state);
if (!state.id) {
if (!state.description) {
return state.text;
}
var details = '';
if (state.user_email) {
details += ' ' + state.user_email;
}
if (state.user_var_phone) {
details += ' 📞 ' + state.user_var_phone;
}
if (state.user_var_mobile) {
details += ' 📱 ' + state.user_var_mobile;
}
if (state.user_var_address || state.user_var_zipcode || state.user_var_city) {
details += ' 📨';
}
if (state.user_var_address) {
details += ' ' + state.user_var_address;
}
if (state.user_var_zipcode) {
details += ' ' + state.user_var_zipcode;
}
if (state.user_var_city) {
details += ' ' + state.user_var_city;
}
return $('<span>' + state.text + '</span><br /><span>' + details + '</span>');
var $template_string = $('<span>');
$template_string.append(
$('<span>', {text: state.text})).append(
$('<br>')).append(
$('<span>' + state.description + '</span>'));
return $template_string;
}
}
if ($('div.submit-user-selection').length) {

View File

@ -44,6 +44,14 @@ class User(StorableObject):
last_seen = None
default_search_result_template = """{{ user_email|default:"" }}
{% if user_var_phone %} 📞 {{ user_var_phone }}{% endif %}
{% if user_var_mobile %} 📱 {{ user_var_mobile }}{% endif %}
{% if user_var_address or user_var_zipcode or user_var_city %} 📨{% endif %}
{% if user_var_address %} {{ user_var_address }}{% endif %}
{% if user_var_zipcode %} {{ user_var_zipcode }}{% endif %}
{% if user_var_city %} {{ user_var_city }}{% endif %}"""
def __init__(self, name=None):
StorableObject.__init__(self)
self.name = name