Add edit mode for email "profile" settings.
Plus some related tweaks, needed to make that happen.
This commit is contained in:
parent
73d14cb1d9
commit
1956c4c9cf
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue