backoffice: use a customisable template to render user info in sidebar (#40034)
This commit is contained in:
parent
7134680e7c
commit
e34366d5b5
|
@ -4727,31 +4727,31 @@ def test_settings_user(pub):
|
||||||
resp = app.get('/backoffice/settings/users').follow().follow()
|
resp = app.get('/backoffice/settings/users').follow().follow()
|
||||||
|
|
||||||
# add a field
|
# add a field
|
||||||
resp.forms[1]['label'] = 'foobar'
|
resp.forms[2]['label'] = 'foobar'
|
||||||
resp = resp.forms[1].submit()
|
resp = resp.forms[2].submit()
|
||||||
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
||||||
resp = resp.follow()
|
resp = resp.follow()
|
||||||
assert b'foobar' in pub.cfg['users']['formdef']
|
assert b'foobar' in pub.cfg['users']['formdef']
|
||||||
assert 'foobar' in resp.text
|
assert 'foobar' in resp.text
|
||||||
|
|
||||||
# set field as email
|
# set field as email
|
||||||
resp.forms[0]['field_email'] = '1'
|
resp.forms['mapping']['field_email'] = '1'
|
||||||
resp = resp.forms[0].submit()
|
resp = resp.forms['mapping'].submit()
|
||||||
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
||||||
resp = resp.follow()
|
resp = resp.follow()
|
||||||
assert pub.cfg['users']['field_email'] == '1'
|
assert pub.cfg['users']['field_email'] == '1'
|
||||||
|
|
||||||
# and unset it
|
# and unset it
|
||||||
resp.forms[0]['field_email'] = ''
|
resp.forms['mapping']['field_email'] = ''
|
||||||
resp = resp.forms[0].submit()
|
resp = resp.forms['mapping'].submit()
|
||||||
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
||||||
resp = resp.follow()
|
resp = resp.follow()
|
||||||
assert pub.cfg['users']['field_email'] == None
|
assert pub.cfg['users']['field_email'] == None
|
||||||
|
|
||||||
# add a comment field
|
# add a comment field
|
||||||
resp.forms[1]['label'] = 'barfoo'
|
resp.forms[2]['label'] = 'barfoo'
|
||||||
resp.forms[1]['type'] = 'Comment'
|
resp.forms[2]['type'] = 'Comment'
|
||||||
resp = resp.forms[1].submit()
|
resp = resp.forms[2].submit()
|
||||||
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
assert resp.location == 'http://example.net/backoffice/settings/users/fields/'
|
||||||
resp = resp.follow()
|
resp = resp.follow()
|
||||||
assert b'barfoo' in pub.cfg['users']['formdef']
|
assert b'barfoo' in pub.cfg['users']['formdef']
|
||||||
|
@ -4760,16 +4760,43 @@ def test_settings_user(pub):
|
||||||
# check fields are present in edit form
|
# check fields are present in edit form
|
||||||
resp = app.get('/backoffice/users/%s/edit' % user.id)
|
resp = app.get('/backoffice/users/%s/edit' % user.id)
|
||||||
assert 'barfoo' in resp.text
|
assert 'barfoo' in resp.text
|
||||||
assert 'f1' in resp.forms[0].fields
|
assert 'f1' in resp.form.fields
|
||||||
assert 'email' in resp.forms[0].fields
|
assert 'email' in resp.form.fields
|
||||||
|
|
||||||
# check the email field is not displayed if it's overridden by a custom
|
# check the email field is not displayed if it's overridden by a custom
|
||||||
# field.
|
# field.
|
||||||
pub.cfg['users']['field_email'] = '1'
|
pub.cfg['users']['field_email'] = '1'
|
||||||
pub.write_cfg()
|
pub.write_cfg()
|
||||||
resp = app.get('/backoffice/users/%s/edit' % user.id)
|
resp = app.get('/backoffice/users/%s/edit' % user.id)
|
||||||
assert 'f1' in resp.forms[0].fields
|
assert 'f1' in resp.form.fields
|
||||||
assert 'email' not in resp.forms[0].fields
|
assert 'email' not in resp.form.fields
|
||||||
|
|
||||||
|
# set a sidebar template
|
||||||
|
app = login(get_app(pub))
|
||||||
|
resp = app.get('/backoffice/settings/users').follow().follow()
|
||||||
|
resp.forms['template']['sidebar_template'] = 'hello {{ form_user_display_name }}'
|
||||||
|
resp = resp.forms['template'].submit().follow()
|
||||||
|
assert pub.cfg['users']['sidebar_template'] == 'hello {{ form_user_display_name }}'
|
||||||
|
resp.forms['template']['sidebar_template'] = '{% if True %}'
|
||||||
|
resp = resp.forms['template'].submit().follow()
|
||||||
|
assert pub.cfg['users']['sidebar_template'] == 'hello {{ form_user_display_name }}'
|
||||||
|
assert 'syntax error in Django template' in resp
|
||||||
|
|
||||||
|
# disable users screen
|
||||||
|
if not pub.site_options.has_section('options'):
|
||||||
|
pub.site_options.add_section('options')
|
||||||
|
pub.site_options.set('options', 'settings-disabled-screens', 'users')
|
||||||
|
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
|
||||||
|
pub.site_options.write(fd)
|
||||||
|
|
||||||
|
resp = app.get('/backoffice/settings/')
|
||||||
|
resp = resp.click('Users', href='user-template')
|
||||||
|
resp.forms['template']['sidebar_template'] = '{% if True %}'
|
||||||
|
resp = resp.forms['template'].submit()
|
||||||
|
assert 'syntax error in Django template' in resp
|
||||||
|
resp.forms['template']['sidebar_template'] = 'hello {{ form_user_display_name }}'
|
||||||
|
resp = resp.forms['template'].submit()
|
||||||
|
assert pub.cfg['users']['sidebar_template'] == 'hello {{ form_user_display_name }}'
|
||||||
|
|
||||||
# restore config
|
# restore config
|
||||||
pub.cfg['users']['field_email'] = None
|
pub.cfg['users']['field_email'] = None
|
||||||
|
|
|
@ -1913,6 +1913,32 @@ def test_backoffice_submission_context(pub):
|
||||||
assert 'by %s' % user.get_display_name() in resp.text
|
assert 'by %s' % user.get_display_name() in resp.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_backoffice_sidebar_user_template(pub):
|
||||||
|
user = create_user(pub)
|
||||||
|
create_environment(pub)
|
||||||
|
form_class = FormDef.get_by_urlname('form-title').data_class()
|
||||||
|
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0]
|
||||||
|
number31.user_id = user.id
|
||||||
|
number31.store()
|
||||||
|
app = login(get_app(pub))
|
||||||
|
resp = app.get('/backoffice/management/form-title/')
|
||||||
|
resp = resp.click(href='%s/' % number31.id)
|
||||||
|
assert 'Associated User' in resp.text
|
||||||
|
assert '<p>admin</p>' in resp.text
|
||||||
|
pub.cfg['users'] = {'sidebar_template': 'XXX{{ form_user_display_name }}YYY'}
|
||||||
|
pub.write_cfg()
|
||||||
|
resp = app.get(resp.request.url)
|
||||||
|
assert '<p>XXXadminYYY</p>' in resp.text
|
||||||
|
pub.cfg['users'] = {'sidebar_template': 'XXX<b>{{ form_user_display_name }}</b>YYY'}
|
||||||
|
pub.write_cfg()
|
||||||
|
resp = app.get(resp.request.url)
|
||||||
|
assert '<p>XXX<b>admin</b>YYY</p>' in resp.text
|
||||||
|
user.name = 'adm<i>n'
|
||||||
|
user.store()
|
||||||
|
resp = app.get(resp.request.url)
|
||||||
|
assert '<p>XXX<b>adm<i>n</b>YYY</p>' in resp.text
|
||||||
|
|
||||||
|
|
||||||
def test_backoffice_geolocation_info(pub):
|
def test_backoffice_geolocation_info(pub):
|
||||||
user = create_user(pub)
|
user = create_user(pub)
|
||||||
create_environment(pub)
|
create_environment(pub)
|
||||||
|
|
|
@ -118,7 +118,7 @@ class UserFieldDefPage(FieldDefPage):
|
||||||
|
|
||||||
|
|
||||||
class UserFieldsDirectory(FieldsDirectory):
|
class UserFieldsDirectory(FieldsDirectory):
|
||||||
_q_exports = ['', 'update_order', 'new', 'mapping']
|
_q_exports = ['', 'update_order', 'new', 'mapping', 'template']
|
||||||
|
|
||||||
section = 'settings'
|
section = 'settings'
|
||||||
field_def_page_class = UserFieldDefPage
|
field_def_page_class = UserFieldDefPage
|
||||||
|
@ -128,11 +128,15 @@ class UserFieldsDirectory(FieldsDirectory):
|
||||||
|
|
||||||
def index_bottom(self):
|
def index_bottom(self):
|
||||||
r = TemplateIO(html=True)
|
r = TemplateIO(html=True)
|
||||||
|
r += get_session().display_message()
|
||||||
r += htmltext('<div class="bo-block">')
|
r += htmltext('<div class="bo-block">')
|
||||||
r += htmltext('<h2>%s</h2>') % _('Fields Mapping')
|
r += htmltext('<h2>%s</h2>') % _('Fields Mapping')
|
||||||
r += htmltext('<p>%s</p>') % _('These settings make it possible to assign custom user fields to standard user fields.')
|
r += htmltext('<p>%s</p>') % _('These settings make it possible to assign custom user fields to standard user fields.')
|
||||||
form = self.mapping_form()
|
r += self.mapping_form().render()
|
||||||
r += form.render()
|
r += htmltext('</div>')
|
||||||
|
r += htmltext('<div class="bo-block">')
|
||||||
|
r += htmltext('<h2>%s</h2>') % _('Sidebar Template')
|
||||||
|
r += self.sidebar_template_form().render()
|
||||||
r += htmltext('</div>')
|
r += htmltext('</div>')
|
||||||
return r.getvalue()
|
return r.getvalue()
|
||||||
|
|
||||||
|
@ -141,7 +145,7 @@ class UserFieldsDirectory(FieldsDirectory):
|
||||||
options = [(None, _('None'), '')] + [
|
options = [(None, _('None'), '')] + [
|
||||||
(x.id, x.label, x.id) for x in self.objectdef.fields]
|
(x.id, x.label, x.id) for x in self.objectdef.fields]
|
||||||
|
|
||||||
form = Form(action = 'mapping', enctype='multipart/form-data')
|
form = Form(action='mapping', id='mapping')
|
||||||
field_name_value = users_cfg.get('field_name')
|
field_name_value = users_cfg.get('field_name')
|
||||||
if type(field_name_value) is str:
|
if type(field_name_value) is str:
|
||||||
field_name_value = [field_name_value]
|
field_name_value = [field_name_value]
|
||||||
|
@ -161,6 +165,26 @@ class UserFieldsDirectory(FieldsDirectory):
|
||||||
cfg_submit(form, 'users', ['field_name', 'field_email'])
|
cfg_submit(form, 'users', ['field_name', 'field_email'])
|
||||||
return redirect('.')
|
return redirect('.')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sidebar_template_form(cls, action='template'):
|
||||||
|
users_cfg = get_cfg('users', {})
|
||||||
|
form = Form(action=action, id='template')
|
||||||
|
form.add(TextWidget, 'sidebar_template',
|
||||||
|
value=users_cfg.get('sidebar_template') or '{{ form_user_display_name }}',
|
||||||
|
required=False,
|
||||||
|
validation_function=ComputedExpressionWidget.validate_template,
|
||||||
|
rows=4)
|
||||||
|
form.add_submit('submit', _('Submit'))
|
||||||
|
return form
|
||||||
|
|
||||||
|
def template(self):
|
||||||
|
form = self.sidebar_template_form()
|
||||||
|
if form.has_errors():
|
||||||
|
get_session().message = ('error', form.get_widget('sidebar_template').get_error())
|
||||||
|
return redirect('.')
|
||||||
|
cfg_submit(form, 'users', ['sidebar_template'])
|
||||||
|
return redirect('.')
|
||||||
|
|
||||||
|
|
||||||
class UserFieldsFormDef(FormDef):
|
class UserFieldsFormDef(FormDef):
|
||||||
'''Class to handle custom user fields, it loads and saves from/to
|
'''Class to handle custom user fields, it loads and saves from/to
|
||||||
|
@ -405,6 +429,7 @@ class SettingsDirectory(QommonSettingsDirectory):
|
||||||
'session', 'download_theme', 'smstest', 'postgresql',
|
'session', 'download_theme', 'smstest', 'postgresql',
|
||||||
('admin-permissions', 'admin_permissions'), 'geolocation',
|
('admin-permissions', 'admin_permissions'), 'geolocation',
|
||||||
'theme_preview', 'filetypes',
|
'theme_preview', 'filetypes',
|
||||||
|
('user-template', 'user_template'),
|
||||||
('data-sources', 'data_sources'), 'wscalls', 'logs']
|
('data-sources', 'data_sources'), 'wscalls', 'logs']
|
||||||
|
|
||||||
emails = EmailsDirectory()
|
emails = EmailsDirectory()
|
||||||
|
@ -517,6 +542,10 @@ class SettingsDirectory(QommonSettingsDirectory):
|
||||||
if enabled('users'):
|
if enabled('users'):
|
||||||
r += htmltext('<dt><a href="users/">%s</a></dt> <dd>%s</dd>') % (
|
r += htmltext('<dt><a href="users/">%s</a></dt> <dd>%s</dd>') % (
|
||||||
_('Users'), _('Configure users'))
|
_('Users'), _('Configure users'))
|
||||||
|
else:
|
||||||
|
# minimal options
|
||||||
|
r += htmltext('<dt><a href="user-template">%s</a></dt> <dd>%s</dd>') % (
|
||||||
|
_('Users'), _('Configure sidebar template for users'))
|
||||||
if enabled('emails'):
|
if enabled('emails'):
|
||||||
r += htmltext('<dt><a href="emails/">%s</a></dt> <dd>%s</dd>') % (
|
r += htmltext('<dt><a href="emails/">%s</a></dt> <dd>%s</dd>') % (
|
||||||
_('Emails'), _('Configure email settings'))
|
_('Emails'), _('Configure email settings'))
|
||||||
|
@ -1223,3 +1252,23 @@ class SettingsDirectory(QommonSettingsDirectory):
|
||||||
r += htmltext('<h2>%s</h2>') % _('Geolocation Settings')
|
r += htmltext('<h2>%s</h2>') % _('Geolocation Settings')
|
||||||
r += form.render()
|
r += form.render()
|
||||||
return r.getvalue()
|
return r.getvalue()
|
||||||
|
|
||||||
|
def user_template(self):
|
||||||
|
users_cfg = get_cfg('users', {})
|
||||||
|
form = UserFieldsDirectory.sidebar_template_form(action='user-template')
|
||||||
|
form.get_widget('sidebar_template').set_title(_('Sidebar Template'))
|
||||||
|
form.add_submit('cancel', _('Cancel'))
|
||||||
|
|
||||||
|
if form.get_widget('cancel').parse():
|
||||||
|
return redirect('.')
|
||||||
|
|
||||||
|
if form.is_submitted() and not form.has_errors():
|
||||||
|
cfg_submit(form, 'users', ['sidebar_template'])
|
||||||
|
return redirect('.')
|
||||||
|
|
||||||
|
get_response().breadcrumb.append(('user-template', _('Users')))
|
||||||
|
html_top('settings', title=_('Users'))
|
||||||
|
r = TemplateIO(html=True)
|
||||||
|
r += htmltext('<h2>%s</h2>') % _('Users')
|
||||||
|
r += form.render()
|
||||||
|
return r.getvalue()
|
||||||
|
|
|
@ -53,6 +53,7 @@ from ..qommon import ods
|
||||||
from ..qommon.form import *
|
from ..qommon.form import *
|
||||||
from ..qommon.storage import (Equal, NotEqual, LessOrEqual, GreaterOrEqual, Or,
|
from ..qommon.storage import (Equal, NotEqual, LessOrEqual, GreaterOrEqual, Or,
|
||||||
Intersects, ILike, FtsMatch, Contains, Null, NotNull)
|
Intersects, ILike, FtsMatch, Contains, Null, NotNull)
|
||||||
|
from ..qommon.template import Template
|
||||||
|
|
||||||
from wcs.api_utils import get_user_from_api_query_string
|
from wcs.api_utils import get_user_from_api_query_string
|
||||||
from wcs.carddef import CardDef
|
from wcs.carddef import CardDef
|
||||||
|
@ -2661,7 +2662,16 @@ class FormBackOfficeStatusPage(FormStatusPage):
|
||||||
if formdata.user_id and formdata.get_user():
|
if formdata.user_id and formdata.get_user():
|
||||||
r += htmltext('<div class="extra-context">')
|
r += htmltext('<div class="extra-context">')
|
||||||
r += htmltext('<h3>%s</h3>') % _('Associated User')
|
r += htmltext('<h3>%s</h3>') % _('Associated User')
|
||||||
r += htmltext('<p>%s</p>') % formdata.get_user().display_name
|
users_cfg = get_cfg('users', {})
|
||||||
|
sidebar_user_template = users_cfg.get('sidebar_template')
|
||||||
|
if sidebar_user_template:
|
||||||
|
variables = get_publisher().substitutions.get_context_variables(mode='lazy')
|
||||||
|
sidebar_user = Template(sidebar_user_template).render(variables)
|
||||||
|
if not sidebar_user.startswith('<'):
|
||||||
|
sidebar_user = htmltext('<p>%s</p>' % sidebar_user)
|
||||||
|
r += sidebar_user
|
||||||
|
else:
|
||||||
|
r += htmltext('<p>%s</p>') % formdata.get_user().display_name
|
||||||
r += htmltext('</div>')
|
r += htmltext('</div>')
|
||||||
|
|
||||||
if formdata.formdef.geolocations and formdata.geolocations:
|
if formdata.formdef.geolocations and formdata.geolocations:
|
||||||
|
|
Loading…
Reference in New Issue