Add edit mode for email "profile" settings.

Plus some related tweaks, needed to make that happen.
This commit is contained in:
Lance Edgar 2016-01-10 17:35:34 -06:00
parent 73d14cb1d9
commit 1956c4c9cf
6 changed files with 94 additions and 43 deletions

View file

@ -26,7 +26,7 @@ Forms
from formencode import Schema
from .core import Form, Field, FieldSet
from .core import Form, Field, FieldSet, GenericFieldSet
from .simpleform import SimpleForm, FormRenderer
from .alchemy import AlchemyForm
from .fields import AssociationProxyField

View file

@ -30,8 +30,9 @@ from edbob.util import prettify
from rattail.util import OrderedDict
from pyramid.renderers import render
import formalchemy
from formalchemy.helpers import content_tag
from pyramid.renderers import render
class Form(object):
@ -108,3 +109,12 @@ class FieldSet(object):
def __init__(self):
self.fields = OrderedDict()
self.render_fields = self.fields
class GenericFieldSet(formalchemy.FieldSet):
"""
FieldSet class based on FormAlchemy, but without the SQLAlchemy magic.
"""
__sa__ = False
_bound_pk = None
data = None

View file

@ -657,7 +657,7 @@ class Grid(object):
return self.cell_attrs
def render_cell(self, row, column):
return unicode(row[column.key])
return column.render(row[column.key])
def get_pagesize_options(self):
# TODO: Make configurable or something...
@ -681,6 +681,12 @@ class GridColumn(object):
self.key = key
self.label = label or prettify(key)
def render(self, value):
"""
Render the given value, to be displayed within a grid cell.
"""
return unicode(value)
class GridAction(object):
"""

View file

@ -1,7 +1,7 @@
## -*- coding: utf-8 -*-
<%inherit file="/base.mako" />
<%def name="title()">${model_title}: ${unicode(instance)}</%def>
<%def name="title()">Edit ${model_title}: ${instance_title}</%def>
<%def name="context_menu_items()">
<li>${h.link_to("Back to {}".format(model_title_plural), url(route_prefix))}</li>

View file

@ -26,15 +26,40 @@ Email Views
from __future__ import unicode_literals, absolute_import
import formalchemy
from formalchemy.helpers import text_area
from pyramid.httpexceptions import HTTPFound
from rattail import mail
from rattail.db import api
from rattail.config import parse_list
from tailbone import forms
from tailbone.db import Session
from tailbone.views import MasterView, View
from tailbone.newgrids import Grid, GridColumn
class EmailListGridColumn(GridColumn):
def render(self, value):
if not value:
return ''
recips = parse_list(value)
if len(recips) < 3:
return value
return "{}, ...".format(', '.join(recips[:2]))
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):
"""
Master view for email admin (settings/preview).
@ -49,7 +74,6 @@ class ProfilesView(MasterView):
pageable = False
creatable = False
editable = False
deletable = False
def get_data(self, session=None):
@ -84,7 +108,7 @@ class ProfilesView(MasterView):
GridColumn('key'),
GridColumn('prefix'),
GridColumn('subject'),
GridColumn('to'),
EmailListGridColumn('to'),
]
g.sorters['key'] = g.make_sorter('key', foldcase=True)
@ -93,8 +117,8 @@ class ProfilesView(MasterView):
g.sorters['to'] = g.make_sorter('to', foldcase=True)
g.default_sortkey = 'key'
# g.main_actions = []
g.more_actions = []
# Make edit link visible by default, no "More" actions.
g.main_actions.append(g.more_actions.pop())
def get_instance(self):
key = self.request.matchdict['key']
@ -107,35 +131,39 @@ class ProfilesView(MasterView):
"""
Make a simple form for use with CRUD views.
"""
# TODO: This needs all kinds of help still...
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('prefix', value=email['prefix'], label="Subject Prefix"))
fs.append(formalchemy.Field('subject', value=email['subject'], label="Subject Text"))
fs.append(formalchemy.Field('description', value=email['description'], readonly=True))
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'))
class EmailSchema(forms.Schema):
pass
form = forms.SimpleForm(self.request, schema=EmailSchema(), obj=email)
form.creating = self.creating
form.editing = self.editing
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_index_url() if self.creating else self.get_action_url('view', email))
form.readonly = self.viewing
if self.creating:
form.cancel_url = self.get_index_url()
else:
form.cancel_url = self.get_action_url('view', email)
form.fieldset = forms.FieldSet()
form.fieldset.fields['key'] = forms.Field('key', value=email['key'])
form.fieldset.fields['fallback_key'] = forms.Field('fallback_key', value=email['fallback_key'])
form.fieldset.fields['prefix'] = forms.Field('prefix', value=email['prefix'], label="Subject Prefix")
form.fieldset.fields['subject'] = forms.Field('subject', value=email['subject'], label="Subject Text")
form.fieldset.fields['description'] = forms.Field('description', value=email['description'])
form.fieldset.fields['sender'] = forms.Field('sender', value=email['sender'], label="From")
form.fieldset.fields['replyto'] = forms.Field('replyto', value=email['replyto'], label="Reply-To")
form.fieldset.fields['to'] = forms.Field('to', value=email['to'])
form.fieldset.fields['cc'] = forms.Field('cc', value=email['cc'])
form.fieldset.fields['bcc'] = forms.Field('bcc', value=email['bcc'])
return form
def save_form(self, form):
fs = form.fieldset
fs.sync()
key = fs.key._value
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', ', '))
def template_kwargs_view(self, **kwargs):
key = self.request.matchdict['key']
kwargs['email'] = mail.get_email(self.rattail_config, key)

View file

@ -117,13 +117,9 @@ class MasterView(View):
self.viewing = True
instance = self.get_instance()
form = self.make_form(instance)
return self.render_to_response('view', {
'instance': instance,
'form': form,
'instance_title': self.get_instance_title(instance)})
def get_instance_title(self, instance):
return unicode(instance)
return self.render_to_response('view', {'instance': instance,
'instance_title': self.get_instance_title(instance),
'form': form})
def edit(self):
"""
@ -134,12 +130,14 @@ class MasterView(View):
form = self.make_form(instance)
if self.request.method == 'POST':
if form.validate():
form.save()
self.save_form(form)
self.after_edit(instance)
self.request.session.flash("{0} {1} has been updated.".format(
self.get_model_title(), instance))
self.get_model_title(), self.get_instance_title(instance)))
return HTTPFound(location=self.get_action_url('view', instance))
return self.render_to_response('edit', {'instance': instance, 'form': form})
return self.render_to_response('edit', {'instance': instance,
'instance_title': self.get_instance_title(instance),
'form': form})
def delete(self):
"""
@ -503,6 +501,12 @@ class MasterView(View):
raise HTTPNotFound()
return instance
def get_instance_title(self, instance):
"""
Return a "pretty" title for the instance, to be used in the page title etc.
"""
return unicode(instance)
def make_form(self, instance, **kwargs):
"""
Make a FormAlchemy-based form for use with CRUD views.
@ -525,6 +529,9 @@ class MasterView(View):
form.readonly = self.viewing
return form
def save_form(self, form):
form.save()
def make_fieldset(self, instance, **kwargs):
"""
Make a FormAlchemy fieldset for the given model instance.