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.readonly_fields = set(readonly_fields or [])
|
||||||
self.model_instance = model_instance
|
self.model_instance = model_instance
|
||||||
self.model_class = model_class
|
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)
|
self.model_class = type(self.model_instance)
|
||||||
if self.model_class and self.fields is None:
|
if self.model_class and self.fields is None:
|
||||||
self.set_fields(self.make_fields())
|
self.set_fields(self.make_fields())
|
||||||
|
@ -647,7 +647,10 @@ class Form(object):
|
||||||
# get initial form values from model instance
|
# get initial form values from model instance
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if self.model_instance:
|
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
|
# create form
|
||||||
form = deform.Form(schema, **kwargs)
|
form = deform.Form(schema, **kwargs)
|
||||||
|
|
|
@ -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.
|
||||||
#
|
#
|
||||||
|
@ -26,27 +26,18 @@ Email Views
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
from rattail import mail
|
from rattail import mail
|
||||||
from rattail.db import api
|
from rattail.db import api
|
||||||
from rattail.config import parse_list
|
from rattail.config import parse_list
|
||||||
|
|
||||||
import formalchemy
|
import colander
|
||||||
from formalchemy.helpers import text_area
|
from deform import widget as dfwidget
|
||||||
from pyramid.httpexceptions import HTTPFound
|
|
||||||
from webhelpers2.html import HTML
|
from webhelpers2.html import HTML
|
||||||
|
|
||||||
from tailbone import forms
|
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.views import View, MasterView2 as MasterView
|
from tailbone.views import View, MasterView3 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)
|
|
||||||
|
|
||||||
|
|
||||||
class ProfilesView(MasterView):
|
class ProfilesView(MasterView):
|
||||||
|
@ -61,6 +52,7 @@ class ProfilesView(MasterView):
|
||||||
pageable = False
|
pageable = False
|
||||||
creatable = False
|
creatable = False
|
||||||
deletable = False
|
deletable = False
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'key',
|
'key',
|
||||||
'prefix',
|
'prefix',
|
||||||
|
@ -69,6 +61,20 @@ class ProfilesView(MasterView):
|
||||||
'enabled',
|
'enabled',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
form_fields = [
|
||||||
|
'key',
|
||||||
|
'fallback_key',
|
||||||
|
'description',
|
||||||
|
'prefix',
|
||||||
|
'subject',
|
||||||
|
'sender',
|
||||||
|
'replyto',
|
||||||
|
'to',
|
||||||
|
'cc',
|
||||||
|
'bcc',
|
||||||
|
'enabled',
|
||||||
|
]
|
||||||
|
|
||||||
def get_data(self, session=None):
|
def get_data(self, session=None):
|
||||||
data = []
|
data = []
|
||||||
for email in mail.iter_emails(self.rattail_config):
|
for email in mail.iter_emails(self.rattail_config):
|
||||||
|
@ -113,13 +119,13 @@ class ProfilesView(MasterView):
|
||||||
'key': email.key,
|
'key': email.key,
|
||||||
'fallback_key': email.fallback_key,
|
'fallback_key': email.fallback_key,
|
||||||
'description': email.__doc__,
|
'description': email.__doc__,
|
||||||
'prefix': email.get_prefix(data, magic=False),
|
'prefix': email.get_prefix(data, magic=False) or '',
|
||||||
'subject': email.get_subject(data, render=False),
|
'subject': email.get_subject(data, render=False) or '',
|
||||||
'sender': email.get_sender(),
|
'sender': email.get_sender() or '',
|
||||||
'replyto': email.get_replyto(),
|
'replyto': email.get_replyto() or '',
|
||||||
'to': get_recips('to'),
|
'to': get_recips('to') or '',
|
||||||
'cc': get_recips('cc'),
|
'cc': get_recips('cc') or '',
|
||||||
'bcc': get_recips('bcc'),
|
'bcc': get_recips('bcc') or '',
|
||||||
'enabled': email.get_enabled(),
|
'enabled': email.get_enabled(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,45 +146,58 @@ class ProfilesView(MasterView):
|
||||||
return profile['key'] != 'user_feedback'
|
return profile['key'] != 'user_feedback'
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def make_form(self, email, **kwargs):
|
def configure_form(self, f):
|
||||||
"""
|
super(ProfilesView, self).configure_form(f)
|
||||||
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']))
|
|
||||||
|
|
||||||
form = forms.AlchemyForm(self.request, fs,
|
# key
|
||||||
creating=self.creating,
|
f.set_readonly('key')
|
||||||
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
|
|
||||||
|
|
||||||
def save_form(self, form):
|
# fallback_key
|
||||||
fs = form.fieldset
|
f.set_readonly('fallback_key')
|
||||||
fs.sync()
|
|
||||||
key = fs.key._value
|
|
||||||
|
|
||||||
session = Session()
|
# description
|
||||||
api.save_setting(session, 'rattail.mail.{}.prefix'.format(key), fs.prefix._value)
|
f.set_readonly('description')
|
||||||
api.save_setting(session, 'rattail.mail.{}.subject'.format(key), fs.subject._value)
|
|
||||||
api.save_setting(session, 'rattail.mail.{}.from'.format(key), fs.sender._value)
|
# prefix
|
||||||
api.save_setting(session, 'rattail.mail.{}.replyto'.format(key), fs.replyto._value)
|
f.set_label('prefix', "Subject Prefix")
|
||||||
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', ', '))
|
# subject
|
||||||
api.save_setting(session, 'rattail.mail.{}.bcc'.format(key), (fs.bcc._value or '').replace('\n', ', '))
|
f.set_label('subject', "Subject Text")
|
||||||
api.save_setting(session, 'rattail.mail.{}.enabled'.format(key), unicode(fs.enabled._value).lower())
|
|
||||||
|
# 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):
|
def template_kwargs_view(self, **kwargs):
|
||||||
key = self.request.matchdict['key']
|
key = self.request.matchdict['key']
|
||||||
|
@ -186,6 +205,25 @@ class ProfilesView(MasterView):
|
||||||
return kwargs
|
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):
|
class EmailPreview(View):
|
||||||
"""
|
"""
|
||||||
Lists available email templates, and can show previews of each.
|
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.
|
# Forms submitted via POST are only used for sending emails.
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
self.email_template()
|
self.email_template()
|
||||||
return HTTPFound(location=self.request.get_referrer(
|
url = self.request.get_referrer(default=self.request.route_url('emailprofiles'))
|
||||||
default=self.request.route_url('emailprofiles')))
|
return self.redirect(url)
|
||||||
|
|
||||||
# Maybe render a preview?
|
# Maybe render a preview?
|
||||||
key = self.request.GET.get('key')
|
key = self.request.GET.get('key')
|
||||||
|
|
|
@ -61,6 +61,9 @@ class MasterView3(MasterView2):
|
||||||
if schema is None:
|
if schema is None:
|
||||||
schema = self.make_form_schema()
|
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:
|
if not self.creating:
|
||||||
kwargs['model_instance'] = instance
|
kwargs['model_instance'] = instance
|
||||||
kwargs = self.make_form_kwargs(**kwargs)
|
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
|
Configure the primary form. By default this just sets any primary key
|
||||||
fields to be readonly (if we have a :attr:`model_class`).
|
fields to be readonly (if we have a :attr:`model_class`).
|
||||||
"""
|
"""
|
||||||
|
if self.editing:
|
||||||
if self.editing and self.model_class:
|
model_class = self.get_model_class(error=False)
|
||||||
mapper = orm.class_mapper(self.model_class)
|
if model_class:
|
||||||
for key in mapper.primary_key:
|
mapper = orm.class_mapper(model_class)
|
||||||
for field in form.fields:
|
for key in mapper.primary_key:
|
||||||
if field == key.name:
|
for field in form.fields:
|
||||||
form.set_readonly(field)
|
if field == key.name:
|
||||||
break
|
form.set_readonly(field)
|
||||||
|
break
|
||||||
|
|
||||||
form.remove_field('uuid')
|
form.remove_field('uuid')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue