Refactor email profiles view to use master3
This commit is contained in:
parent
8d62960548
commit
e0650d26cf
|
@ -335,7 +335,7 @@ class Form(object):
|
|||
self.readonly_fields = set(readonly_fields or [])
|
||||
self.model_instance = model_instance
|
||||
self.model_class = model_class
|
||||
if self.model_instance and not self.model_class:
|
||||
if self.model_instance and not self.model_class and not isinstance(self.model_instance, dict):
|
||||
self.model_class = type(self.model_instance)
|
||||
if self.model_class and self.fields is None:
|
||||
self.set_fields(self.make_fields())
|
||||
|
@ -647,7 +647,10 @@ class Form(object):
|
|||
# get initial form values from model instance
|
||||
kwargs = {}
|
||||
if self.model_instance:
|
||||
kwargs['appstruct'] = schema.dictify(self.model_instance)
|
||||
if self.model_class:
|
||||
kwargs['appstruct'] = schema.dictify(self.model_instance)
|
||||
else:
|
||||
kwargs['appstruct'] = self.model_instance
|
||||
|
||||
# create form
|
||||
form = deform.Form(schema, **kwargs)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2017 Lance Edgar
|
||||
# Copyright © 2010-2018 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -26,27 +26,18 @@ Email Views
|
|||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from rattail import mail
|
||||
from rattail.db import api
|
||||
from rattail.config import parse_list
|
||||
|
||||
import formalchemy
|
||||
from formalchemy.helpers import text_area
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
import colander
|
||||
from deform import widget as dfwidget
|
||||
from webhelpers2.html import HTML
|
||||
|
||||
from tailbone import forms
|
||||
from tailbone.db import Session
|
||||
from tailbone.views import View, MasterView2 as MasterView
|
||||
|
||||
|
||||
class EmailListFieldRenderer(formalchemy.TextAreaFieldRenderer):
|
||||
|
||||
def render(self, **kwargs):
|
||||
if isinstance(kwargs.get('size'), tuple):
|
||||
kwargs['size'] = 'x'.join([str(i) for i in kwargs['size']])
|
||||
value = '\n'.join(parse_list(self.value))
|
||||
return text_area(self.name, content=value, **kwargs)
|
||||
from tailbone.views import View, MasterView3 as MasterView
|
||||
|
||||
|
||||
class ProfilesView(MasterView):
|
||||
|
@ -61,6 +52,7 @@ class ProfilesView(MasterView):
|
|||
pageable = False
|
||||
creatable = False
|
||||
deletable = False
|
||||
|
||||
grid_columns = [
|
||||
'key',
|
||||
'prefix',
|
||||
|
@ -69,6 +61,20 @@ class ProfilesView(MasterView):
|
|||
'enabled',
|
||||
]
|
||||
|
||||
form_fields = [
|
||||
'key',
|
||||
'fallback_key',
|
||||
'description',
|
||||
'prefix',
|
||||
'subject',
|
||||
'sender',
|
||||
'replyto',
|
||||
'to',
|
||||
'cc',
|
||||
'bcc',
|
||||
'enabled',
|
||||
]
|
||||
|
||||
def get_data(self, session=None):
|
||||
data = []
|
||||
for email in mail.iter_emails(self.rattail_config):
|
||||
|
@ -113,13 +119,13 @@ class ProfilesView(MasterView):
|
|||
'key': email.key,
|
||||
'fallback_key': email.fallback_key,
|
||||
'description': email.__doc__,
|
||||
'prefix': email.get_prefix(data, magic=False),
|
||||
'subject': email.get_subject(data, render=False),
|
||||
'sender': email.get_sender(),
|
||||
'replyto': email.get_replyto(),
|
||||
'to': get_recips('to'),
|
||||
'cc': get_recips('cc'),
|
||||
'bcc': get_recips('bcc'),
|
||||
'prefix': email.get_prefix(data, magic=False) or '',
|
||||
'subject': email.get_subject(data, render=False) or '',
|
||||
'sender': email.get_sender() or '',
|
||||
'replyto': email.get_replyto() or '',
|
||||
'to': get_recips('to') or '',
|
||||
'cc': get_recips('cc') or '',
|
||||
'bcc': get_recips('bcc') or '',
|
||||
'enabled': email.get_enabled(),
|
||||
}
|
||||
|
||||
|
@ -140,45 +146,58 @@ class ProfilesView(MasterView):
|
|||
return profile['key'] != 'user_feedback'
|
||||
return True
|
||||
|
||||
def make_form(self, email, **kwargs):
|
||||
"""
|
||||
Make a simple form for use with CRUD views.
|
||||
"""
|
||||
fs = forms.GenericFieldSet(email)
|
||||
fs.append(formalchemy.Field('key', value=email['key'], readonly=True))
|
||||
fs.append(formalchemy.Field('fallback_key', value=email['fallback_key'], readonly=True))
|
||||
fs.append(formalchemy.Field('description', value=email['description'], readonly=True))
|
||||
fs.append(formalchemy.Field('prefix', value=email['prefix'], label="Subject Prefix"))
|
||||
fs.append(formalchemy.Field('subject', value=email['subject'], label="Subject Text"))
|
||||
fs.append(formalchemy.Field('sender', value=email['sender'], label="From"))
|
||||
fs.append(formalchemy.Field('replyto', value=email['replyto'], label="Reply-To"))
|
||||
fs.append(formalchemy.Field('to', value=email['to'], renderer=EmailListFieldRenderer, size='60x6'))
|
||||
fs.append(formalchemy.Field('cc', value=email['cc'], renderer=EmailListFieldRenderer, size='60x2'))
|
||||
fs.append(formalchemy.Field('bcc', value=email['bcc'], renderer=EmailListFieldRenderer, size='60x2'))
|
||||
fs.append(formalchemy.Field('enabled', type=formalchemy.types.Boolean, value=email['enabled']))
|
||||
def configure_form(self, f):
|
||||
super(ProfilesView, self).configure_form(f)
|
||||
|
||||
form = forms.AlchemyForm(self.request, fs,
|
||||
creating=self.creating,
|
||||
editing=self.editing,
|
||||
action_url=self.request.current_route_url(_query=None),
|
||||
cancel_url=self.get_action_url('view', email))
|
||||
form.readonly = self.viewing
|
||||
return form
|
||||
# key
|
||||
f.set_readonly('key')
|
||||
|
||||
def save_form(self, form):
|
||||
fs = form.fieldset
|
||||
fs.sync()
|
||||
key = fs.key._value
|
||||
# fallback_key
|
||||
f.set_readonly('fallback_key')
|
||||
|
||||
session = Session()
|
||||
api.save_setting(session, 'rattail.mail.{}.prefix'.format(key), fs.prefix._value)
|
||||
api.save_setting(session, 'rattail.mail.{}.subject'.format(key), fs.subject._value)
|
||||
api.save_setting(session, 'rattail.mail.{}.from'.format(key), fs.sender._value)
|
||||
api.save_setting(session, 'rattail.mail.{}.replyto'.format(key), fs.replyto._value)
|
||||
api.save_setting(session, 'rattail.mail.{}.to'.format(key), (fs.to._value or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.cc'.format(key), (fs.cc._value or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.bcc'.format(key), (fs.bcc._value or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.enabled'.format(key), unicode(fs.enabled._value).lower())
|
||||
# description
|
||||
f.set_readonly('description')
|
||||
|
||||
# prefix
|
||||
f.set_label('prefix', "Subject Prefix")
|
||||
|
||||
# subject
|
||||
f.set_label('subject', "Subject Text")
|
||||
|
||||
# sender
|
||||
f.set_label('sender', "From")
|
||||
|
||||
# replyto
|
||||
f.set_label('replyto', "Reply-To")
|
||||
|
||||
# to
|
||||
f.set_widget('to', dfwidget.TextAreaWidget(cols=60, rows=6))
|
||||
|
||||
# cc
|
||||
f.set_widget('cc', dfwidget.TextAreaWidget(cols=60, rows=2))
|
||||
|
||||
# bcc
|
||||
f.set_widget('bcc', dfwidget.TextAreaWidget(cols=60, rows=2))
|
||||
|
||||
# enabled
|
||||
f.set_type('enabled', 'boolean')
|
||||
|
||||
def make_form_schema(self):
|
||||
return EmailProfileSchema()
|
||||
|
||||
def save_edit_form(self, form):
|
||||
key = self.request.matchdict['key']
|
||||
data = self.form_deserialized
|
||||
session = self.Session()
|
||||
api.save_setting(session, 'rattail.mail.{}.prefix'.format(key), data['prefix'])
|
||||
api.save_setting(session, 'rattail.mail.{}.subject'.format(key), data['subject'])
|
||||
api.save_setting(session, 'rattail.mail.{}.from'.format(key), data['sender'])
|
||||
api.save_setting(session, 'rattail.mail.{}.replyto'.format(key), data['replyto'])
|
||||
api.save_setting(session, 'rattail.mail.{}.to'.format(key), (data['to'] or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.cc'.format(key), (data['cc'] or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.bcc'.format(key), (data['bcc'] or '').replace('\n', ', '))
|
||||
api.save_setting(session, 'rattail.mail.{}.enabled'.format(key), six.text_type(data['enabled']).lower())
|
||||
return data
|
||||
|
||||
def template_kwargs_view(self, **kwargs):
|
||||
key = self.request.matchdict['key']
|
||||
|
@ -186,6 +205,25 @@ class ProfilesView(MasterView):
|
|||
return kwargs
|
||||
|
||||
|
||||
class EmailProfileSchema(colander.MappingSchema):
|
||||
|
||||
prefix = colander.SchemaNode(colander.String())
|
||||
|
||||
subject = colander.SchemaNode(colander.String())
|
||||
|
||||
sender = colander.SchemaNode(colander.String())
|
||||
|
||||
replyto = colander.SchemaNode(colander.String(), missing='')
|
||||
|
||||
to = colander.SchemaNode(colander.String())
|
||||
|
||||
cc = colander.SchemaNode(colander.String(), missing='')
|
||||
|
||||
bcc = colander.SchemaNode(colander.String(), missing='')
|
||||
|
||||
enabled = colander.SchemaNode(colander.Boolean())
|
||||
|
||||
|
||||
class EmailPreview(View):
|
||||
"""
|
||||
Lists available email templates, and can show previews of each.
|
||||
|
@ -196,8 +234,8 @@ class EmailPreview(View):
|
|||
# Forms submitted via POST are only used for sending emails.
|
||||
if self.request.method == 'POST':
|
||||
self.email_template()
|
||||
return HTTPFound(location=self.request.get_referrer(
|
||||
default=self.request.route_url('emailprofiles')))
|
||||
url = self.request.get_referrer(default=self.request.route_url('emailprofiles'))
|
||||
return self.redirect(url)
|
||||
|
||||
# Maybe render a preview?
|
||||
key = self.request.GET.get('key')
|
||||
|
|
|
@ -61,6 +61,9 @@ class MasterView3(MasterView2):
|
|||
if schema is None:
|
||||
schema = self.make_form_schema()
|
||||
|
||||
# TODO: SQLAlchemy class instance is assumed *unless* we get a dict
|
||||
# (seems like we should be smarter about this somehow)
|
||||
# if not self.creating and not isinstance(instance, dict):
|
||||
if not self.creating:
|
||||
kwargs['model_instance'] = instance
|
||||
kwargs = self.make_form_kwargs(**kwargs)
|
||||
|
@ -103,14 +106,15 @@ class MasterView3(MasterView2):
|
|||
Configure the primary form. By default this just sets any primary key
|
||||
fields to be readonly (if we have a :attr:`model_class`).
|
||||
"""
|
||||
|
||||
if self.editing and self.model_class:
|
||||
mapper = orm.class_mapper(self.model_class)
|
||||
for key in mapper.primary_key:
|
||||
for field in form.fields:
|
||||
if field == key.name:
|
||||
form.set_readonly(field)
|
||||
break
|
||||
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')
|
||||
|
||||
|
|
Loading…
Reference in a new issue