Add basic paging grid/index support for mobile

still lots to do for this yet..but readonly basics are here..
This commit is contained in:
Lance Edgar 2017-03-30 20:11:17 -05:00
parent e313e1bc8c
commit 0ad29c5283
7 changed files with 132 additions and 57 deletions

View file

@ -133,6 +133,13 @@ class CustomersView(MasterView):
fs.email_preference,
])
def configure_mobile_fieldset(self, fs):
fs.configure(
include=[
fs.email,
fs.phone,
])
class CustomerNameAutocomplete(AutocompleteView):
"""

View file

@ -26,6 +26,7 @@ Model Master View
from __future__ import unicode_literals, absolute_import
import six
import sqlalchemy as sa
from sqlalchemy import orm
@ -102,7 +103,7 @@ class MasterView(View):
View to list/filter/sort the model data.
If this view receives a non-empty 'partial' parameter in the query
string, then the view will return the renderered grid only. Otherwise
string, then the view will return the rendered grid only. Otherwise
returns the full page.
"""
self.listing = True
@ -135,16 +136,15 @@ class MasterView(View):
def make_mobile_grid(self, **kwargs):
factory = self.get_mobile_grid_factory()
key = self.get_mobile_grid_key()
data = self.get_mobile_data(session=kwargs.get('session'))
kwargs = self.make_mobile_grid_kwargs(**kwargs)
kwargs.setdefault('key', key)
kwargs.setdefault('key', self.get_mobile_grid_key())
kwargs.setdefault('request', self.request)
kwargs.setdefault('data', data)
kwargs.setdefault('data', self.get_mobile_data(session=kwargs.get('session')))
kwargs.setdefault('model_class', self.get_model_class(error=False))
grid = factory(**kwargs)
self.preconfigure_mobile_grid(grid)
self.configure_mobile_grid(grid)
grid.load_settings()
return grid
@classmethod
@ -166,7 +166,7 @@ class MasterView(View):
"""
if hasattr(cls, 'mobile_grid_key'):
return cls.mobile_grid_key
return cls.get_route_prefix()
return 'mobile.{}'.format(cls.get_route_prefix())
def get_mobile_data(self, session=None):
"""
@ -184,6 +184,8 @@ class MasterView(View):
"""
defaults = {
'route_prefix': self.get_route_prefix(),
'pageable': self.pageable,
'sortable': True,
}
defaults.update(kwargs)
return defaults
@ -200,7 +202,39 @@ class MasterView(View):
which columns to show and in which order etc. Along the way you're
free to customize any column(s) you like, as needed.
"""
grid.configure()
listitem = self.mobile_listitem_field()
if listitem:
grid.append(listitem)
grid.configure(include=[grid.listitem])
else:
grid.configure()
def mobile_listitem_field(self):
"""
Must return a FormAlchemy field to be appended to grid, or ``None`` if
none is desired.
"""
return fa.Field('listitem', value=lambda obj: obj,
renderer=self.mobile_listitem_renderer())
def mobile_listitem_renderer(self):
"""
Must return a FormAlchemy field renderer callable for the mobile grid's
list item field.
"""
master = self
class ListItemRenderer(fa.FieldRenderer):
def render_readonly(self, **kwargs):
obj = self.raw_value
if obj is None:
return ''
title = master.get_instance_title(obj)
url = master.get_action_url('view', obj, mobile=True)
return tags.link_to(title, url)
return ListItemRenderer
def create(self):
"""
@ -271,17 +305,39 @@ class MasterView(View):
"""
self.viewing = True
instance = self.get_instance()
# form = self.make_form(instance)
form = self.make_mobile_form(instance)
context = {
'instance': instance,
'instance_title': self.get_instance_title(instance),
# 'instance_editable': self.editable_instance(instance),
# 'instance_deletable': self.deletable_instance(instance),
# 'form': form,
'form': form,
}
return self.render_to_response('view', context, mobile=True)
def make_mobile_form(self, instance, **kwargs):
"""
Make a FormAlchemy-based form for use with mobile CRUD views
"""
fieldset = self.make_fieldset(instance)
self.preconfigure_mobile_fieldset(fieldset)
self.configure_mobile_fieldset(fieldset)
factory = kwargs.pop('factory', forms.AlchemyForm)
kwargs.setdefault('session', self.Session())
form = factory(self.request, fieldset, **kwargs)
form.readonly = self.viewing
return form
def preconfigure_mobile_fieldset(self, fieldset):
self._preconfigure_fieldset(fieldset)
def configure_mobile_fieldset(self, fieldset):
"""
Configure the given mobile fieldset.
"""
self.configure_fieldset(fieldset)
def make_default_row_grid_tools(self, obj):
if self.rows_creatable:
link = tags.link_to("Create a new {}".format(self.get_row_model_title()),
@ -547,7 +603,7 @@ class MasterView(View):
object_to_keep = self.Session.query(self.get_model_class()).get(uuids[1])
if object_to_remove and object_to_keep and self.request.POST.get('commit-merge') == 'yes':
msg = unicode(object_to_remove)
msg = six.text_type(object_to_remove)
try:
self.validate_merge(object_to_remove, object_to_keep)
except Exception as error:
@ -691,11 +747,14 @@ class MasterView(View):
"""
return getattr(cls, 'permission_prefix', cls.get_route_prefix())
def get_index_url(self):
def get_index_url(self, mobile=False):
"""
Returns the master view's index URL.
"""
return self.request.route_url(self.get_route_prefix())
route = self.get_route_prefix()
if mobile:
route = 'mobile.{}'.format(route)
return self.request.route_url(route)
@classmethod
def get_index_title(cls):
@ -704,13 +763,15 @@ class MasterView(View):
"""
return getattr(cls, 'index_title', cls.get_model_title_plural())
def get_action_url(self, action, instance, **kwargs):
def get_action_url(self, action, instance, mobile=False, **kwargs):
"""
Generate a URL for the given action on the given instance
"""
kw = self.get_action_route_kwargs(instance)
kw.update(kwargs)
route_prefix = self.get_route_prefix()
if mobile:
route_prefix = 'mobile.{}'.format(route_prefix)
return self.request.route_url('{}.{}'.format(route_prefix, action), **kw)
def render_to_response(self, template, data, mobile=False):
@ -728,7 +789,7 @@ class MasterView(View):
'route_prefix': self.get_route_prefix(),
'permission_prefix': self.get_permission_prefix(),
'index_title': self.get_index_title(),
'index_url': self.get_index_url(),
'index_url': self.get_index_url(mobile=mobile),
'action_url': self.get_action_url,
'grid_index': self.grid_index,
}
@ -1066,7 +1127,7 @@ class MasterView(View):
"""
Return a "pretty" title for the instance, to be used in the page title etc.
"""
return unicode(instance)
return six.text_type(instance)
def make_form(self, instance, **kwargs):
"""

View file

@ -93,6 +93,7 @@ class ProductsView(MasterView):
Master view for the Product class.
"""
model_class = model.Product
supports_mobile = True
# child_version_classes = [
# (model.ProductCode, 'product_uuid'),