Add master4, refactor customers view to use it
This commit is contained in:
parent
ab16ffc823
commit
63290154eb
|
@ -1,4 +1,6 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/mobile/master/create.mako" />
|
<%inherit file="/mobile/master/create.mako" />
|
||||||
|
|
||||||
|
<%def name="title()">New ${model_title} Row</%def>
|
||||||
|
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
|
@ -8,5 +8,5 @@
|
||||||
${parent.body()}
|
${parent.body()}
|
||||||
|
|
||||||
% if master.mobile_rows_editable and instance_editable and request.has_perm('{}.edit_row'.format(permission_prefix)):
|
% if master.mobile_rows_editable and instance_editable and request.has_perm('{}.edit_row'.format(permission_prefix)):
|
||||||
${h.link_to("Edit", url('mobile.{}.edit_row'.format(route_prefix), uuid=instance.uuid), class_='ui-btn')}
|
${h.link_to("Edit", url('mobile.{}.edit_row'.format(route_prefix), uuid=instance.batch_uuid, row_uuid=instance.uuid), class_='ui-btn')}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8; -*-
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2017 Lance Edgar
|
# Copyright © 2010-2018 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -30,6 +30,7 @@ from .core import View
|
||||||
from .master import MasterView
|
from .master import MasterView
|
||||||
from .master2 import MasterView2
|
from .master2 import MasterView2
|
||||||
from .master3 import MasterView3
|
from .master3 import MasterView3
|
||||||
|
from .master4 import MasterView4
|
||||||
|
|
||||||
# TODO: deprecate / remove some of this
|
# TODO: deprecate / remove some of this
|
||||||
from .autocomplete import AutocompleteView
|
from .autocomplete import AutocompleteView
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2017 Lance Edgar
|
# Copyright © 2010-2018 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -39,7 +39,7 @@ from webhelpers2.html import HTML, tags
|
||||||
|
|
||||||
from tailbone import grids
|
from tailbone import grids
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.views import MasterView3 as MasterView, AutocompleteView
|
from tailbone.views import MasterView4 as MasterView, AutocompleteView
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
|
@ -83,6 +83,19 @@ class CustomersView(MasterView):
|
||||||
'groups',
|
'groups',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
mobile_form_fields = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'default_phone',
|
||||||
|
'default_email',
|
||||||
|
'default_address',
|
||||||
|
'email_preference',
|
||||||
|
'active_in_pos',
|
||||||
|
'active_in_pos_sticky',
|
||||||
|
'people',
|
||||||
|
'groups',
|
||||||
|
]
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(CustomersView, self).configure_grid(g)
|
super(CustomersView, self).configure_grid(g)
|
||||||
|
|
||||||
|
@ -286,13 +299,6 @@ class CustomersView(MasterView):
|
||||||
items.append(HTML.tag('li', tags.link_to(text, url)))
|
items.append(HTML.tag('li', tags.link_to(text, url)))
|
||||||
return HTML.tag('ul', HTML.literal('').join(items))
|
return HTML.tag('ul', HTML.literal('').join(items))
|
||||||
|
|
||||||
# def configure_mobile_fieldset(self, fs):
|
|
||||||
# fs.configure(
|
|
||||||
# include=[
|
|
||||||
# fs.email,
|
|
||||||
# fs.phone,
|
|
||||||
# ])
|
|
||||||
|
|
||||||
def get_version_child_classes(self):
|
def get_version_child_classes(self):
|
||||||
return [
|
return [
|
||||||
(model.CustomerPhoneNumber, 'parent_uuid'),
|
(model.CustomerPhoneNumber, 'parent_uuid'),
|
||||||
|
|
|
@ -824,6 +824,9 @@ class MasterView(View):
|
||||||
def validate_mobile_form(self, form):
|
def validate_mobile_form(self, form):
|
||||||
return form.validate()
|
return form.validate()
|
||||||
|
|
||||||
|
def validate_row_form(self, form):
|
||||||
|
return form.validate()
|
||||||
|
|
||||||
def save_edit_form(self, form):
|
def save_edit_form(self, form):
|
||||||
self.save_form(form)
|
self.save_form(form)
|
||||||
self.after_edit(form.fieldset.model)
|
self.after_edit(form.fieldset.model)
|
||||||
|
@ -1741,10 +1744,9 @@ class MasterView(View):
|
||||||
index_url = self.get_action_url('view', parent)
|
index_url = self.get_action_url('view', parent)
|
||||||
form = self.make_row_form(self.model_row_class, cancel_url=index_url)
|
form = self.make_row_form(self.model_row_class, cancel_url=index_url)
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if form.validate():
|
if self.validate_row_form(form):
|
||||||
self.before_create_row(form)
|
self.before_create_row(form)
|
||||||
self.save_create_row_form(form)
|
obj = self.save_create_row_form(form) or form.fieldset.model
|
||||||
obj = form.fieldset.model
|
|
||||||
self.after_create_row(obj)
|
self.after_create_row(obj)
|
||||||
return self.redirect_after_create_row(obj)
|
return self.redirect_after_create_row(obj)
|
||||||
return self.render_to_response('create_row', {
|
return self.render_to_response('create_row', {
|
||||||
|
@ -1775,7 +1777,7 @@ class MasterView(View):
|
||||||
instance_url = self.get_action_url('view', parent, mobile=True)
|
instance_url = self.get_action_url('view', parent, mobile=True)
|
||||||
form = self.make_mobile_row_form(self.model_row_class, cancel_url=instance_url)
|
form = self.make_mobile_row_form(self.model_row_class, cancel_url=instance_url)
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if form.validate():
|
if self.validate_mobile_row_form(form):
|
||||||
self.before_create_row(form)
|
self.before_create_row(form)
|
||||||
# let save() return alternate object if necessary
|
# let save() return alternate object if necessary
|
||||||
obj = self.save_create_row_form(form) or form.fieldset.model
|
obj = self.save_create_row_form(form) or form.fieldset.model
|
||||||
|
@ -1835,7 +1837,7 @@ class MasterView(View):
|
||||||
form = self.make_row_form(row)
|
form = self.make_row_form(row)
|
||||||
|
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if form.validate():
|
if self.validate_row_form(form):
|
||||||
self.save_edit_row_form(form)
|
self.save_edit_row_form(form)
|
||||||
return self.redirect_after_edit_row(row)
|
return self.redirect_after_edit_row(row)
|
||||||
|
|
||||||
|
@ -1860,7 +1862,7 @@ class MasterView(View):
|
||||||
form = self.make_mobile_row_form(row)
|
form = self.make_mobile_row_form(row)
|
||||||
|
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if form.validate():
|
if self.validate_mobile_row_form(form):
|
||||||
self.save_edit_row_form(form)
|
self.save_edit_row_form(form)
|
||||||
return self.redirect_after_edit_row(row, mobile=True)
|
return self.redirect_after_edit_row(row, mobile=True)
|
||||||
|
|
||||||
|
|
319
tailbone/views/master4.py
Normal file
319
tailbone/views/master4.py
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
# -*- coding: utf-8; -*-
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Rattail -- Retail Software Framework
|
||||||
|
# Copyright © 2010-2018 Lance Edgar
|
||||||
|
#
|
||||||
|
# This file is part of Rattail.
|
||||||
|
#
|
||||||
|
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||||
|
# terms of the GNU General Public License as published by the Free Software
|
||||||
|
# Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
# version.
|
||||||
|
#
|
||||||
|
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
"""
|
||||||
|
Master View (v4)
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
import deform
|
||||||
|
|
||||||
|
from tailbone import forms2 as forms
|
||||||
|
from tailbone.views import MasterView3
|
||||||
|
|
||||||
|
|
||||||
|
class MasterView4(MasterView3):
|
||||||
|
"""
|
||||||
|
Base "master" view class. All model master views should derive from this.
|
||||||
|
"""
|
||||||
|
row_labels = {}
|
||||||
|
|
||||||
|
def make_mobile_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Creates a new mobile form for the given model class/instance.
|
||||||
|
"""
|
||||||
|
if factory is None:
|
||||||
|
factory = self.get_mobile_form_factory()
|
||||||
|
if fields is None:
|
||||||
|
fields = self.get_mobile_form_fields()
|
||||||
|
if schema is None:
|
||||||
|
schema = self.make_mobile_form_schema()
|
||||||
|
|
||||||
|
if not self.creating:
|
||||||
|
kwargs['model_instance'] = instance
|
||||||
|
kwargs = self.make_mobile_form_kwargs(**kwargs)
|
||||||
|
form = factory(fields, schema, **kwargs)
|
||||||
|
self.configure_mobile_form(form)
|
||||||
|
return form
|
||||||
|
|
||||||
|
def make_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Creates a new row form for the given model class/instance.
|
||||||
|
"""
|
||||||
|
if factory is None:
|
||||||
|
factory = self.get_row_form_factory()
|
||||||
|
if fields is None:
|
||||||
|
fields = self.get_row_form_fields()
|
||||||
|
if schema is None:
|
||||||
|
schema = self.make_row_form_schema()
|
||||||
|
|
||||||
|
if not self.creating:
|
||||||
|
kwargs['model_instance'] = instance
|
||||||
|
kwargs = self.make_row_form_kwargs(**kwargs)
|
||||||
|
form = factory(fields, schema, **kwargs)
|
||||||
|
self.configure_row_form(form)
|
||||||
|
return form
|
||||||
|
|
||||||
|
def make_mobile_row_form(self, instance=None, factory=None, fields=None, schema=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Creates a new mobile form for the given model class/instance.
|
||||||
|
"""
|
||||||
|
if factory is None:
|
||||||
|
factory = self.get_mobile_row_form_factory()
|
||||||
|
if fields is None:
|
||||||
|
fields = self.get_mobile_row_form_fields()
|
||||||
|
if schema is None:
|
||||||
|
schema = self.make_mobile_row_form_schema()
|
||||||
|
|
||||||
|
if not self.creating:
|
||||||
|
kwargs['model_instance'] = instance
|
||||||
|
kwargs = self.make_mobile_row_form_kwargs(**kwargs)
|
||||||
|
form = factory(fields, schema, **kwargs)
|
||||||
|
self.configure_mobile_row_form(form)
|
||||||
|
return form
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_mobile_form_factory(cls):
|
||||||
|
"""
|
||||||
|
Returns the factory or class which is to be used when creating new
|
||||||
|
mobile forms.
|
||||||
|
"""
|
||||||
|
return getattr(cls, 'mobile_form_factory', forms.Form)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_row_form_factory(cls):
|
||||||
|
"""
|
||||||
|
Returns the factory or class which is to be used when creating new row
|
||||||
|
forms.
|
||||||
|
"""
|
||||||
|
return getattr(cls, 'row_form_factory', forms.Form)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_mobile_row_form_factory(cls):
|
||||||
|
"""
|
||||||
|
Returns the factory or class which is to be used when creating new
|
||||||
|
mobile row forms.
|
||||||
|
"""
|
||||||
|
return getattr(cls, 'mobile_row_form_factory', forms.Form)
|
||||||
|
|
||||||
|
def make_mobile_form_schema(self):
|
||||||
|
if not self.model_class:
|
||||||
|
# TODO
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def make_row_form_schema(self):
|
||||||
|
if not self.model_row_class:
|
||||||
|
# TODO
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def make_mobile_row_form_schema(self):
|
||||||
|
if not self.model_row_class:
|
||||||
|
# TODO
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_mobile_form_fields(self):
|
||||||
|
if hasattr(self, 'mobile_form_fields'):
|
||||||
|
return self.mobile_form_fields
|
||||||
|
# TODO
|
||||||
|
# raise NotImplementedError
|
||||||
|
|
||||||
|
def get_row_form_fields(self):
|
||||||
|
if hasattr(self, 'row_form_fields'):
|
||||||
|
return self.row_form_fields
|
||||||
|
# TODO
|
||||||
|
# raise NotImplementedError
|
||||||
|
|
||||||
|
def get_mobile_row_form_fields(self):
|
||||||
|
if hasattr(self, 'mobile_row_form_fields'):
|
||||||
|
return self.mobile_row_form_fields
|
||||||
|
# TODO
|
||||||
|
# raise NotImplementedError
|
||||||
|
|
||||||
|
def make_mobile_form_kwargs(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Return a dictionary of kwargs to be passed to the factory when creating
|
||||||
|
new mobile forms.
|
||||||
|
"""
|
||||||
|
defaults = {
|
||||||
|
'request': self.request,
|
||||||
|
'readonly': self.viewing,
|
||||||
|
'model_class': getattr(self, 'model_class', None),
|
||||||
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
|
}
|
||||||
|
if self.creating:
|
||||||
|
defaults['cancel_url'] = self.get_index_url(mobile=True)
|
||||||
|
else:
|
||||||
|
instance = kwargs['model_instance']
|
||||||
|
defaults['cancel_url'] = self.get_action_url('view', instance, mobile=True)
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
def make_row_form_kwargs(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Return a dictionary of kwargs to be passed to the factory when creating
|
||||||
|
new row forms.
|
||||||
|
"""
|
||||||
|
defaults = {
|
||||||
|
'request': self.request,
|
||||||
|
'readonly': self.viewing,
|
||||||
|
'model_class': getattr(self, 'model_row_class', None),
|
||||||
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
|
}
|
||||||
|
if self.creating:
|
||||||
|
kwargs.setdefault('cancel_url', self.request.get_referrer())
|
||||||
|
else:
|
||||||
|
instance = kwargs['model_instance']
|
||||||
|
kwargs.setdefault('cancel_url', self.get_row_action_url('view', instance))
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
def make_mobile_row_form_kwargs(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Return a dictionary of kwargs to be passed to the factory when creating
|
||||||
|
new mobile row forms.
|
||||||
|
"""
|
||||||
|
defaults = {
|
||||||
|
'request': self.request,
|
||||||
|
'readonly': self.viewing,
|
||||||
|
'model_class': getattr(self, 'model_row_class', None),
|
||||||
|
'action_url': self.request.current_route_url(_query=None),
|
||||||
|
}
|
||||||
|
if self.creating:
|
||||||
|
defaults['cancel_url'] = self.request.get_referrer()
|
||||||
|
else:
|
||||||
|
instance = kwargs['model_instance']
|
||||||
|
defaults['cancel_url'] = self.get_row_action_url('view', instance, mobile=True)
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return defaults
|
||||||
|
|
||||||
|
def configure_mobile_form(self, form):
|
||||||
|
"""
|
||||||
|
Configure the primary mobile form.
|
||||||
|
"""
|
||||||
|
# TODO: is any of this stuff from configure_form() needed?
|
||||||
|
# if self.editing:
|
||||||
|
# model_class = self.get_model_class(error=False)
|
||||||
|
# if model_class:
|
||||||
|
# mapper = orm.class_mapper(model_class)
|
||||||
|
# for key in mapper.primary_key:
|
||||||
|
# for field in form.fields:
|
||||||
|
# if field == key.name:
|
||||||
|
# form.set_readonly(field)
|
||||||
|
# break
|
||||||
|
# form.remove_field('uuid')
|
||||||
|
|
||||||
|
self.set_labels(form)
|
||||||
|
|
||||||
|
def configure_row_grid(self, grid):
|
||||||
|
super(MasterView4, self).configure_row_grid(grid)
|
||||||
|
self.set_row_labels(grid)
|
||||||
|
|
||||||
|
def configure_row_form(self, form):
|
||||||
|
"""
|
||||||
|
Configure a row form.
|
||||||
|
"""
|
||||||
|
# TODO: is any of this stuff from configure_form() needed?
|
||||||
|
# if self.editing:
|
||||||
|
# model_class = self.get_model_class(error=False)
|
||||||
|
# if model_class:
|
||||||
|
# mapper = orm.class_mapper(model_class)
|
||||||
|
# for key in mapper.primary_key:
|
||||||
|
# for field in form.fields:
|
||||||
|
# if field == key.name:
|
||||||
|
# form.set_readonly(field)
|
||||||
|
# break
|
||||||
|
# form.remove_field('uuid')
|
||||||
|
|
||||||
|
self.set_row_labels(form)
|
||||||
|
|
||||||
|
def configure_mobile_row_form(self, form):
|
||||||
|
"""
|
||||||
|
Configure the mobile row form.
|
||||||
|
"""
|
||||||
|
# TODO: is any of this stuff from configure_form() needed?
|
||||||
|
# if self.editing:
|
||||||
|
# model_class = self.get_model_class(error=False)
|
||||||
|
# if model_class:
|
||||||
|
# mapper = orm.class_mapper(model_class)
|
||||||
|
# for key in mapper.primary_key:
|
||||||
|
# for field in form.fields:
|
||||||
|
# if field == key.name:
|
||||||
|
# form.set_readonly(field)
|
||||||
|
# break
|
||||||
|
# form.remove_field('uuid')
|
||||||
|
|
||||||
|
self.set_row_labels(form)
|
||||||
|
|
||||||
|
def set_row_labels(self, obj):
|
||||||
|
for key, label in self.row_labels.items():
|
||||||
|
obj.set_label(key, label)
|
||||||
|
|
||||||
|
def validate_mobile_form(self, form):
|
||||||
|
controls = self.request.POST.items()
|
||||||
|
try:
|
||||||
|
self.form_deserialized = form.validate(controls)
|
||||||
|
except deform.ValidationFailure:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def validate_row_form(self, form):
|
||||||
|
controls = self.request.POST.items()
|
||||||
|
try:
|
||||||
|
self.form_deserialized = form.validate(controls)
|
||||||
|
except deform.ValidationFailure:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def validate_mobile_row_form(self, form):
|
||||||
|
controls = self.request.POST.items()
|
||||||
|
try:
|
||||||
|
self.form_deserialized = form.validate(controls)
|
||||||
|
except deform.ValidationFailure:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def save_mobile_create_form(self, form):
|
||||||
|
self.before_create(form)
|
||||||
|
with self.Session.no_autoflush:
|
||||||
|
obj = self.objectify(form, self.form_deserialized)
|
||||||
|
self.before_create_flush(obj, form)
|
||||||
|
self.Session.add(obj)
|
||||||
|
self.Session.flush()
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# TODO: still need to verify this logic
|
||||||
|
def save_create_row_form(self, form):
|
||||||
|
# self.before_create(form)
|
||||||
|
# with self.Session().no_autoflush:
|
||||||
|
# obj = self.objectify(form, self.form_deserialized)
|
||||||
|
# self.before_create_flush(obj, form)
|
||||||
|
obj = self.objectify(form, self.form_deserialized)
|
||||||
|
self.Session.add(obj)
|
||||||
|
self.Session.flush()
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def save_edit_row_form(self, form):
|
||||||
|
obj = self.objectify(form, self.form_deserialized)
|
||||||
|
self.after_edit_row(obj)
|
||||||
|
self.Session.flush()
|
||||||
|
return obj
|
Loading…
Reference in a new issue