Add initial support for editing user preferences
by default this exposes just one setting which has only one possible value, so not very useful. but can override as needed
This commit is contained in:
parent
6093be43c9
commit
962d31c4c2
|
@ -30,14 +30,24 @@
|
||||||
</b-button>
|
</b-button>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="intro_message()">
|
||||||
|
<p class="block">
|
||||||
|
This page lets you modify the
|
||||||
|
% if config_preferences is not Undefined and config_preferences:
|
||||||
|
preferences
|
||||||
|
% else:
|
||||||
|
configuration
|
||||||
|
% endif
|
||||||
|
for ${config_title}.
|
||||||
|
</p>
|
||||||
|
</%def>
|
||||||
|
|
||||||
<%def name="buttons_row()">
|
<%def name="buttons_row()">
|
||||||
<div class="level">
|
<div class="level">
|
||||||
<div class="level-left">
|
<div class="level-left">
|
||||||
|
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
<p class="block">
|
${self.intro_message()}
|
||||||
This page lets you modify the configuration for ${config_title}.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="level-item">
|
<div class="level-item">
|
||||||
|
|
|
@ -549,6 +549,7 @@
|
||||||
${h.link_to("Messages{}".format(" ({})".format(inbox_count) if inbox_count else ''), url('messages.inbox'), class_='navbar-item')}
|
${h.link_to("Messages{}".format(" ({})".format(inbox_count) if inbox_count else ''), url('messages.inbox'), class_='navbar-item')}
|
||||||
% endif
|
% endif
|
||||||
${h.link_to("Change Password", url('change_password'), class_='navbar-item')}
|
${h.link_to("Change Password", url('change_password'), class_='navbar-item')}
|
||||||
|
${h.link_to("Edit Preferences", url('my.preferences'), class_='navbar-item')}
|
||||||
${h.link_to("Logout", url('logout'), class_='navbar-item')}
|
${h.link_to("Logout", url('logout'), class_='navbar-item')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
55
tailbone/templates/users/preferences.mako
Normal file
55
tailbone/templates/users/preferences.mako
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/configure.mako" />
|
||||||
|
|
||||||
|
<%def name="title()">
|
||||||
|
% if current_user:
|
||||||
|
Edit Preferences
|
||||||
|
% else:
|
||||||
|
${index_title} » ${instance_title} » Preferences
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="content_title()">Preferences</%def>
|
||||||
|
|
||||||
|
<%def name="intro_message()">
|
||||||
|
<p class="block">
|
||||||
|
% if current_user:
|
||||||
|
This page lets you modify your preferences.
|
||||||
|
% else:
|
||||||
|
This page lets you modify the preferences for ${config_title}.
|
||||||
|
% endif
|
||||||
|
</p>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="form_content()">
|
||||||
|
|
||||||
|
<h3 class="block is-size-3">Display</h3>
|
||||||
|
<div class="block" style="padding-left: 2rem;">
|
||||||
|
|
||||||
|
<b-field label="Theme Style">
|
||||||
|
<b-select name="tailbone.${user.uuid}.buefy_css"
|
||||||
|
v-model="simpleSettings['tailbone.${user.uuid}.buefy_css']"
|
||||||
|
@input="settingsNeedSaved = true">
|
||||||
|
<option v-for="option in buefyCSSOptions"
|
||||||
|
:key="option.value"
|
||||||
|
:value="option.value">
|
||||||
|
{{ option.label }}
|
||||||
|
</option>
|
||||||
|
</b-select>
|
||||||
|
|
||||||
|
</b-field>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="modify_this_page_vars()">
|
||||||
|
${parent.modify_this_page_vars()}
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
ThisPageData.buefyCSSOptions = ${json.dumps(buefy_css_options)|n}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -14,4 +14,12 @@
|
||||||
% endif
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="context_menu_items()">
|
||||||
|
${parent.context_menu_items()}
|
||||||
|
% if master.has_perm('preferences'):
|
||||||
|
<li>${h.link_to("Edit User Preferences", action_url('preferences', instance))}</li>
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -4290,6 +4290,7 @@ class MasterView(View):
|
||||||
'type': bool,
|
'type': bool,
|
||||||
'value': config.getbool('rattail.batch',
|
'value': config.getbool('rattail.batch',
|
||||||
'purchase.allow_cases'),
|
'purchase.allow_cases'),
|
||||||
|
'save_if_empty': False,
|
||||||
}
|
}
|
||||||
|
|
||||||
Note that some of the above is optional, in particular it
|
Note that some of the above is optional, in particular it
|
||||||
|
@ -4316,8 +4317,10 @@ class MasterView(View):
|
||||||
return '{}.{}'.format(simple['section'],
|
return '{}.{}'.format(simple['section'],
|
||||||
simple['option'])
|
simple['option'])
|
||||||
|
|
||||||
def configure_get_context(self):
|
def configure_get_context(self, simple_settings=None,
|
||||||
|
input_file_templates=True):
|
||||||
context = {}
|
context = {}
|
||||||
|
if simple_settings is None:
|
||||||
simple_settings = self.configure_get_simple_settings()
|
simple_settings = self.configure_get_simple_settings()
|
||||||
if simple_settings:
|
if simple_settings:
|
||||||
|
|
||||||
|
@ -4342,7 +4345,7 @@ class MasterView(View):
|
||||||
context['simple_settings'] = settings
|
context['simple_settings'] = settings
|
||||||
|
|
||||||
# add settings for downloadable input file templates, if any
|
# add settings for downloadable input file templates, if any
|
||||||
if self.has_input_file_templates:
|
if input_file_templates and self.has_input_file_templates:
|
||||||
settings = {}
|
settings = {}
|
||||||
file_options = {}
|
file_options = {}
|
||||||
file_option_dirs = {}
|
file_option_dirs = {}
|
||||||
|
@ -4359,10 +4362,12 @@ class MasterView(View):
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def configure_gather_settings(self, data):
|
def configure_gather_settings(self, data, simple_settings=None,
|
||||||
|
input_file_templates=True):
|
||||||
settings = []
|
settings = []
|
||||||
|
|
||||||
# maybe collect "simple" settings
|
# maybe collect "simple" settings
|
||||||
|
if simple_settings is None:
|
||||||
simple_settings = self.configure_get_simple_settings()
|
simple_settings = self.configure_get_simple_settings()
|
||||||
if simple_settings:
|
if simple_settings:
|
||||||
|
|
||||||
|
@ -4377,11 +4382,14 @@ class MasterView(View):
|
||||||
else:
|
else:
|
||||||
value = six.text_type(value)
|
value = six.text_type(value)
|
||||||
|
|
||||||
|
# only want to save this setting if we received a
|
||||||
|
# value, or if empty values are okay to save
|
||||||
|
if value or simple.get('save_if_empty'):
|
||||||
settings.append({'name': name,
|
settings.append({'name': name,
|
||||||
'value': value})
|
'value': value})
|
||||||
|
|
||||||
# maybe also collect input file template settings
|
# maybe also collect input file template settings
|
||||||
if self.has_input_file_templates:
|
if input_file_templates and self.has_input_file_templates:
|
||||||
for template in self.normalize_input_file_templates():
|
for template in self.normalize_input_file_templates():
|
||||||
|
|
||||||
# mode
|
# mode
|
||||||
|
@ -4401,16 +4409,18 @@ class MasterView(View):
|
||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
def configure_remove_settings(self):
|
def configure_remove_settings(self, simple_settings=None,
|
||||||
|
input_file_templates=True):
|
||||||
model = self.model
|
model = self.model
|
||||||
names = []
|
names = []
|
||||||
|
|
||||||
|
if simple_settings is None:
|
||||||
simple_settings = self.configure_get_simple_settings()
|
simple_settings = self.configure_get_simple_settings()
|
||||||
if simple_settings:
|
if simple_settings:
|
||||||
names.extend([self.configure_get_name_for_simple_setting(simple)
|
names.extend([self.configure_get_name_for_simple_setting(simple)
|
||||||
for simple in simple_settings])
|
for simple in simple_settings])
|
||||||
|
|
||||||
if self.has_input_file_templates:
|
if input_file_templates and self.has_input_file_templates:
|
||||||
for template in self.normalize_input_file_templates():
|
for template in self.normalize_input_file_templates():
|
||||||
names.extend([
|
names.extend([
|
||||||
template['setting_mode'],
|
template['setting_mode'],
|
||||||
|
|
|
@ -26,12 +26,10 @@ User Views
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
import copy
|
|
||||||
|
|
||||||
import six
|
import six
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db.model import User, UserEvent
|
||||||
from rattail.db.auth import (administrator_role, guest_role,
|
from rattail.db.auth import (administrator_role, guest_role,
|
||||||
authenticated_role, set_user_password)
|
authenticated_role, set_user_password)
|
||||||
|
|
||||||
|
@ -40,8 +38,7 @@ from deform import widget as dfwidget
|
||||||
from webhelpers2.html import HTML, tags
|
from webhelpers2.html import HTML, tags
|
||||||
|
|
||||||
from tailbone import forms
|
from tailbone import forms
|
||||||
from tailbone.db import Session
|
from tailbone.views import MasterView, View
|
||||||
from tailbone.views import MasterView
|
|
||||||
from tailbone.views.principal import PrincipalMasterView, PermissionsRenderer
|
from tailbone.views.principal import PrincipalMasterView, PermissionsRenderer
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,9 +46,9 @@ class UserView(PrincipalMasterView):
|
||||||
"""
|
"""
|
||||||
Master view for the User model.
|
Master view for the User model.
|
||||||
"""
|
"""
|
||||||
model_class = model.User
|
model_class = User
|
||||||
has_rows = True
|
has_rows = True
|
||||||
model_row_class = model.UserEvent
|
model_row_class = UserEvent
|
||||||
has_versions = True
|
has_versions = True
|
||||||
touchable = True
|
touchable = True
|
||||||
|
|
||||||
|
@ -99,6 +96,7 @@ class UserView(PrincipalMasterView):
|
||||||
|
|
||||||
def query(self, session):
|
def query(self, session):
|
||||||
query = super(UserView, self).query(session)
|
query = super(UserView, self).query(session)
|
||||||
|
model = self.model
|
||||||
|
|
||||||
# bring in the related Person(s)
|
# bring in the related Person(s)
|
||||||
query = query.outerjoin(model.Person)\
|
query = query.outerjoin(model.Person)\
|
||||||
|
@ -108,6 +106,7 @@ class UserView(PrincipalMasterView):
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(UserView, self).configure_grid(g)
|
super(UserView, self).configure_grid(g)
|
||||||
|
model = self.model
|
||||||
|
|
||||||
del g.filters['salt']
|
del g.filters['salt']
|
||||||
g.filters['username'].default_active = True
|
g.filters['username'].default_active = True
|
||||||
|
@ -160,6 +159,7 @@ class UserView(PrincipalMasterView):
|
||||||
return not self.user_is_protected(user)
|
return not self.user_is_protected(user)
|
||||||
|
|
||||||
def unique_username(self, node, value):
|
def unique_username(self, node, value):
|
||||||
|
model = self.model
|
||||||
query = self.Session.query(model.User)\
|
query = self.Session.query(model.User)\
|
||||||
.filter(model.User.username == value)
|
.filter(model.User.username == value)
|
||||||
if self.editing:
|
if self.editing:
|
||||||
|
@ -181,6 +181,7 @@ class UserView(PrincipalMasterView):
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(UserView, self).configure_form(f)
|
super(UserView, self).configure_form(f)
|
||||||
|
model = self.model
|
||||||
user = f.model_instance
|
user = f.model_instance
|
||||||
|
|
||||||
# username
|
# username
|
||||||
|
@ -265,6 +266,7 @@ class UserView(PrincipalMasterView):
|
||||||
f.remove('set_password')
|
f.remove('set_password')
|
||||||
|
|
||||||
def get_possible_roles(self):
|
def get_possible_roles(self):
|
||||||
|
model = self.model
|
||||||
|
|
||||||
# some roles should never have users "belong" to them
|
# some roles should never have users "belong" to them
|
||||||
excluded = [
|
excluded = [
|
||||||
|
@ -281,6 +283,7 @@ class UserView(PrincipalMasterView):
|
||||||
.order_by(model.Role.name)
|
.order_by(model.Role.name)
|
||||||
|
|
||||||
def objectify(self, form, data=None):
|
def objectify(self, form, data=None):
|
||||||
|
model = self.model
|
||||||
|
|
||||||
# create/update user as per normal
|
# create/update user as per normal
|
||||||
if data is None:
|
if data is None:
|
||||||
|
@ -328,6 +331,7 @@ class UserView(PrincipalMasterView):
|
||||||
if 'roles' not in data:
|
if 'roles' not in data:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
model = self.model
|
||||||
old_roles = set([r.uuid for r in user.roles])
|
old_roles = set([r.uuid for r in user.roles])
|
||||||
new_roles = data['roles']
|
new_roles = data['roles']
|
||||||
admin = administrator_role(self.Session())
|
admin = administrator_role(self.Session())
|
||||||
|
@ -389,6 +393,7 @@ class UserView(PrincipalMasterView):
|
||||||
return HTML.tag('ul', c=items)
|
return HTML.tag('ul', c=items)
|
||||||
|
|
||||||
def get_row_data(self, user):
|
def get_row_data(self, user):
|
||||||
|
model = self.model
|
||||||
return self.Session.query(model.UserEvent)\
|
return self.Session.query(model.UserEvent)\
|
||||||
.filter(model.UserEvent.user == user)
|
.filter(model.UserEvent.user == user)
|
||||||
|
|
||||||
|
@ -402,6 +407,7 @@ class UserView(PrincipalMasterView):
|
||||||
g.main_actions = []
|
g.main_actions = []
|
||||||
|
|
||||||
def get_version_child_classes(self):
|
def get_version_child_classes(self):
|
||||||
|
model = self.model
|
||||||
return [
|
return [
|
||||||
(model.UserRole, 'user_uuid'),
|
(model.UserRole, 'user_uuid'),
|
||||||
]
|
]
|
||||||
|
@ -409,6 +415,7 @@ class UserView(PrincipalMasterView):
|
||||||
def find_principals_with_permission(self, session, permission):
|
def find_principals_with_permission(self, session, permission):
|
||||||
app = self.get_rattail_app()
|
app = self.get_rattail_app()
|
||||||
auth = app.get_auth_handler()
|
auth = app.get_auth_handler()
|
||||||
|
model = self.model
|
||||||
|
|
||||||
# TODO: this should search Permission table instead, and work backward to User?
|
# TODO: this should search Permission table instead, and work backward to User?
|
||||||
all_users = session.query(model.User)\
|
all_users = session.query(model.User)\
|
||||||
|
@ -448,6 +455,105 @@ class UserView(PrincipalMasterView):
|
||||||
assert not removing._roles
|
assert not removing._roles
|
||||||
self.Session.delete(removing)
|
self.Session.delete(removing)
|
||||||
|
|
||||||
|
def preferences(self, user=None):
|
||||||
|
"""
|
||||||
|
View to modify preferences for a particular user.
|
||||||
|
"""
|
||||||
|
current_user = True
|
||||||
|
if not user:
|
||||||
|
current_user = False
|
||||||
|
user = self.get_instance()
|
||||||
|
|
||||||
|
# TODO: this is of course largely copy/pasted from the
|
||||||
|
# MasterView.configure() method..should refactor?
|
||||||
|
if self.request.method == 'POST':
|
||||||
|
if self.request.POST.get('remove_settings'):
|
||||||
|
self.preferences_remove_settings(user)
|
||||||
|
self.request.session.flash("Settings have been removed.")
|
||||||
|
return self.redirect(self.request.current_route_url())
|
||||||
|
else:
|
||||||
|
data = self.request.POST
|
||||||
|
|
||||||
|
# then gather/save settings
|
||||||
|
settings = self.preferences_gather_settings(data, user)
|
||||||
|
self.preferences_remove_settings(user)
|
||||||
|
self.configure_save_settings(settings)
|
||||||
|
self.request.session.flash("Settings have been saved.")
|
||||||
|
return self.redirect(self.request.current_route_url())
|
||||||
|
|
||||||
|
context = self.preferences_get_context(user, current_user)
|
||||||
|
return self.render_to_response('preferences', context)
|
||||||
|
|
||||||
|
def my_preferences(self):
|
||||||
|
"""
|
||||||
|
View to modify preferences for the current user.
|
||||||
|
"""
|
||||||
|
user = self.request.user
|
||||||
|
if not user:
|
||||||
|
raise self.forbidden()
|
||||||
|
return self.preferences(user=user)
|
||||||
|
|
||||||
|
def preferences_get_context(self, user, current_user):
|
||||||
|
simple_settings = self.preferences_get_simple_settings(user)
|
||||||
|
context = self.configure_get_context(simple_settings=simple_settings,
|
||||||
|
input_file_templates=False)
|
||||||
|
|
||||||
|
instance_title = self.get_instance_title(user)
|
||||||
|
context.update({
|
||||||
|
'user': user,
|
||||||
|
'instance': user,
|
||||||
|
'instance_title': instance_title,
|
||||||
|
'instance_url': self.get_action_url('view', user),
|
||||||
|
'config_title': instance_title,
|
||||||
|
'config_preferences': True,
|
||||||
|
'current_user': current_user,
|
||||||
|
})
|
||||||
|
|
||||||
|
if current_user:
|
||||||
|
context.update({
|
||||||
|
'index_url': None,
|
||||||
|
'index_title': instance_title,
|
||||||
|
})
|
||||||
|
|
||||||
|
# theme style options
|
||||||
|
options = [{'value': None, 'label': "default"}]
|
||||||
|
styles = self.rattail_config.getlist('tailbone', 'themes.styles',
|
||||||
|
default=[])
|
||||||
|
for name in styles:
|
||||||
|
css = self.rattail_config.get('tailbone',
|
||||||
|
'themes.style.{}'.format(name))
|
||||||
|
if css:
|
||||||
|
options.append({'value': css, 'label': name})
|
||||||
|
context['buefy_css_options'] = options
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def preferences_get_simple_settings(self, user):
|
||||||
|
"""
|
||||||
|
This method is conceptually the same as for
|
||||||
|
:meth:`~tailbone.views.master.MasterView.configure_get_simple_settings()`.
|
||||||
|
See its docs for more info.
|
||||||
|
|
||||||
|
The only difference here is that we are given a user account,
|
||||||
|
so the settings involved should only pertain to that user.
|
||||||
|
"""
|
||||||
|
return [
|
||||||
|
|
||||||
|
# display
|
||||||
|
{'section': 'tailbone.{}'.format(user.uuid),
|
||||||
|
'option': 'buefy_css'},
|
||||||
|
]
|
||||||
|
|
||||||
|
def preferences_gather_settings(self, data, user):
|
||||||
|
simple_settings = self.preferences_get_simple_settings(user)
|
||||||
|
return self.configure_gather_settings(
|
||||||
|
data, simple_settings=simple_settings, input_file_templates=False)
|
||||||
|
|
||||||
|
def preferences_remove_settings(self, user):
|
||||||
|
simple_settings = self.preferences_get_simple_settings(user)
|
||||||
|
self.configure_remove_settings(simple_settings=simple_settings,
|
||||||
|
input_file_templates=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
cls._user_defaults(config)
|
cls._user_defaults(config)
|
||||||
|
@ -459,7 +565,9 @@ class UserView(PrincipalMasterView):
|
||||||
"""
|
"""
|
||||||
Provide extra default configuration for the User master view.
|
Provide extra default configuration for the User master view.
|
||||||
"""
|
"""
|
||||||
|
route_prefix = cls.get_route_prefix()
|
||||||
permission_prefix = cls.get_permission_prefix()
|
permission_prefix = cls.get_permission_prefix()
|
||||||
|
instance_url_prefix = cls.get_instance_url_prefix()
|
||||||
model_title = cls.get_model_title()
|
model_title = cls.get_model_title()
|
||||||
|
|
||||||
# view/edit roles
|
# view/edit roles
|
||||||
|
@ -468,6 +576,23 @@ class UserView(PrincipalMasterView):
|
||||||
config.add_tailbone_permission(permission_prefix, '{}.edit_roles'.format(permission_prefix),
|
config.add_tailbone_permission(permission_prefix, '{}.edit_roles'.format(permission_prefix),
|
||||||
"Edit the Roles to which a {} belongs".format(model_title))
|
"Edit the Roles to which a {} belongs".format(model_title))
|
||||||
|
|
||||||
|
# edit preferences for any user
|
||||||
|
config.add_tailbone_permission(permission_prefix,
|
||||||
|
'{}.preferences'.format(permission_prefix),
|
||||||
|
"Edit preferences for any {}".format(model_title))
|
||||||
|
config.add_route('{}.preferences'.format(route_prefix),
|
||||||
|
'{}/preferences'.format(instance_url_prefix))
|
||||||
|
config.add_view(cls, attr='preferences',
|
||||||
|
route_name='{}.preferences'.format(route_prefix),
|
||||||
|
permission='{}.preferences'.format(permission_prefix))
|
||||||
|
|
||||||
|
# edit "my" preferences (for current user)
|
||||||
|
config.add_route('my.preferences',
|
||||||
|
'/my/preferences')
|
||||||
|
config.add_view(cls, attr='my_preferences',
|
||||||
|
route_name='my.preferences')
|
||||||
|
|
||||||
|
|
||||||
# TODO: deprecate / remove this
|
# TODO: deprecate / remove this
|
||||||
UsersView = UserView
|
UsersView = UserView
|
||||||
|
|
||||||
|
@ -476,7 +601,7 @@ class UserEventView(MasterView):
|
||||||
"""
|
"""
|
||||||
Master view for all user events
|
Master view for all user events
|
||||||
"""
|
"""
|
||||||
model_class = model.UserEvent
|
model_class = UserEvent
|
||||||
url_prefix = '/user-events'
|
url_prefix = '/user-events'
|
||||||
viewable = False
|
viewable = False
|
||||||
creatable = False
|
creatable = False
|
||||||
|
@ -492,10 +617,12 @@ class UserEventView(MasterView):
|
||||||
|
|
||||||
def get_data(self, session=None):
|
def get_data(self, session=None):
|
||||||
query = super(UserEventView, self).get_data(session=session)
|
query = super(UserEventView, self).get_data(session=session)
|
||||||
|
model = self.model
|
||||||
return query.join(model.User)
|
return query.join(model.User)
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(UserEventView, self).configure_grid(g)
|
super(UserEventView, self).configure_grid(g)
|
||||||
|
model = self.model
|
||||||
g.set_joiner('person', lambda q: q.outerjoin(model.Person))
|
g.set_joiner('person', lambda q: q.outerjoin(model.Person))
|
||||||
g.set_sorter('user', model.User.username)
|
g.set_sorter('user', model.User.username)
|
||||||
g.set_sorter('person', model.Person.display_name)
|
g.set_sorter('person', model.Person.display_name)
|
||||||
|
@ -522,8 +649,12 @@ UserEventsView = UserEventView
|
||||||
|
|
||||||
def defaults(config, **kwargs):
|
def defaults(config, **kwargs):
|
||||||
base = globals()
|
base = globals()
|
||||||
kwargs.get('UserView', base['UserView']).defaults(config)
|
|
||||||
kwargs.get('UserEventView', base['UserEventView']).defaults(config)
|
UserView = kwargs.get('UserView', base['UserView'])
|
||||||
|
UserView.defaults(config)
|
||||||
|
|
||||||
|
UserEventView = kwargs.get('UserEventView', base['UserEventView'])
|
||||||
|
UserEventView.defaults(config)
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
|
|
Loading…
Reference in a new issue