From e3de40bdfe9b90dd51ee00817d0aaa91cc1e6613 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 17 Aug 2017 20:13:42 -0500 Subject: [PATCH] Convert bouncer view to master3 also move common file field logic from upgrades into master3 --- tailbone/views/bouncer.py | 98 +++++++++++++++++++++----------------- tailbone/views/master3.py | 31 ++++++++++++ tailbone/views/upgrades.py | 20 +------- 3 files changed, 86 insertions(+), 63 deletions(-) diff --git a/tailbone/views/bouncer.py b/tailbone/views/bouncer.py index 72674890..bcbd7131 100644 --- a/tailbone/views/bouncer.py +++ b/tailbone/views/bouncer.py @@ -33,14 +33,11 @@ from rattail.db import model from rattail.bouncer import get_handler from rattail.bouncer.config import get_profile_keys -import formalchemy from pyramid.response import FileResponse -from webhelpers2.html import literal +from webhelpers2.html import HTML, tags from tailbone import grids -from tailbone.db import Session -from tailbone.views import MasterView2 as MasterView -from tailbone.forms.renderers.bouncer import BounceMessageFieldRenderer +from tailbone.views import MasterView3 as MasterView class EmailBouncesView(MasterView): @@ -53,6 +50,12 @@ class EmailBouncesView(MasterView): creatable = False editable = False + labels = { + 'config_key': "Source", + 'bounce_recipient_address': "Bounced To", + 'intended_recipient_address': "Intended For", + } + grid_columns = [ 'config_key', 'bounced', @@ -90,38 +93,59 @@ class EmailBouncesView(MasterView): g.set_link('bounced') g.set_link('intended_recipient_address') - def configure_fieldset(self, fs): - bounce = fs.model - handler = self.get_handler(bounce) - fs.append(formalchemy.Field('message', - value=handler.msgpath(bounce), - renderer=BounceMessageFieldRenderer.new(self.request, handler))) - fs.append(formalchemy.Field('links', - value=list(handler.make_links(Session(), bounce.intended_recipient_address)), - renderer=LinksFieldRenderer)) - fs.configure( - include=[ - fs.config_key.label("Source"), - fs.message, - fs.bounced, - fs.bounce_recipient_address.label("Bounced To"), - fs.intended_recipient_address.label("Intended For"), - fs.links, - fs.processed, - fs.processed_by, - ], - readonly=True) + def configure_form(self, f): + super(EmailBouncesView, self).configure_form(f) + bounce = f.model_instance + f.set_renderer('message', self.render_message_file) + f.set_renderer('links', self.render_links) + f.fields = [ + 'config_key', + 'message', + 'bounced', + 'bounce_recipient_address', + 'intended_recipient_address', + 'links', + 'processed', + 'processed_by', + ] if not bounce.processed: - del fs.processed - del fs.processed_by + f.remove_field('processed') + f.remove_field('processed_by') + + def render_links(self, bounce, field): + handler = self.get_handler(bounce) + value = list(handler.make_links(self.Session(), bounce.intended_recipient_address)) + if not value: + return "n/a" + + links = [] + for link in value: + label = HTML.literal("{}:  ".format(link.type)) + anchor = tags.link_to(link.title, link.url, target='_blank') + links.append(HTML.tag('li', label + anchor)) + + return HTML.tag('ul', HTML.literal('').join(links)) + + def render_message_file(self, bounce, field): + handler = self.get_handler(bounce) + path = handler.msgpath(bounce) + if not path: + return "" + + url = self.get_action_url('download', bounce) + return self.render_file_field(path, url) def template_kwargs_view(self, **kwargs): bounce = kwargs['instance'] kwargs['bounce'] = bounce handler = self.get_handler(bounce) kwargs['handler'] = handler - with open(handler.msgpath(bounce), 'rb') as f: - kwargs['message'] = f.read() + path = handler.msgpath(bounce) + if os.path.exists(path): + with open(path, 'rb') as f: + kwargs['message'] = f.read() + else: + kwargs['message'] = "(file not found)" return kwargs def process(self): @@ -185,19 +209,5 @@ class EmailBouncesView(MasterView): cls._defaults(config) -class LinksFieldRenderer(formalchemy.FieldRenderer): - - def render_readonly(self, **kwargs): - value = self.raw_value - if not value: - return 'n/a' - html = literal('') - return html - - def includeme(config): EmailBouncesView.defaults(config) diff --git a/tailbone/views/master3.py b/tailbone/views/master3.py index 459ebfe0..c25e60a6 100644 --- a/tailbone/views/master3.py +++ b/tailbone/views/master3.py @@ -26,9 +26,12 @@ Master View from __future__ import unicode_literals, absolute_import +import os + from sqlalchemy import orm import deform +from webhelpers2.html import tags from tailbone import forms2 as forms from tailbone.views import MasterView2 @@ -113,6 +116,34 @@ class MasterView3(MasterView2): self.set_labels(form) + def render_file_field(self, path, url=None, filename=None): + """ + Convenience for rendering a file with optional download link + """ + if not filename: + filename = os.path.basename(path) + content = "{} ({})".format(filename, self.readable_size(path)) + if url: + return tags.link_to(content, url) + return content + + def readable_size(self, path): + # TODO: this was shamelessly copied from FormAlchemy ... + length = self.get_size(path) + if length == 0: + return '0 KB' + if length <= 1024: + return '1 KB' + if length > 1048576: + return '%0.02f MB' % (length / 1048576.0) + return '%0.02f KB' % (length / 1024.0) + + def get_size(self, path): + try: + return os.path.getsize(path) + except os.error: + return 0 + def validate_form(self, form): controls = self.request.POST.items() try: diff --git a/tailbone/views/upgrades.py b/tailbone/views/upgrades.py index 8bacec4b..b28c2639 100644 --- a/tailbone/views/upgrades.py +++ b/tailbone/views/upgrades.py @@ -206,9 +206,8 @@ class UpgradeView(MasterView): filename = 'stdout.log' path = self.rattail_config.upgrade_filepath(upgrade.uuid, filename=filename) if path: - content = "{} ({})".format(filename, self.readable_size(path)) url = '{}?filename={}'.format(self.get_action_url('download', upgrade), filename) - return tags.link_to(content, url) + return self.render_file_field(path, url, filename=filename) return filename def render_package_diff(self, upgrade, fieldname): @@ -291,23 +290,6 @@ class UpgradeView(MasterView): return six.text_type(req.link) return "" - def get_size(self, path): - try: - return os.path.getsize(path) - except os.error: - return 0 - - def readable_size(self, path): - # TODO: this was shamelessly copied from FormAlchemy ... - length = self.get_size(path) - if length == 0: - return '0 KB' - if length <= 1024: - return '1 KB' - if length > 1048576: - return '%0.02f MB' % (length / 1048576.0) - return '%0.02f KB' % (length / 1024.0) - def download_path(self, upgrade, filename): return self.rattail_config.upgrade_filepath(upgrade.uuid, filename=filename)