Refactor "send new message" form, esp. recipients field, per Vue.js

This commit is contained in:
Lance Edgar 2019-11-04 17:30:00 -06:00
parent e153e530a8
commit 86695c9dc7
8 changed files with 274 additions and 20 deletions

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2018 Lance Edgar
# Copyright © 2010-2019 Lance Edgar
#
# This file is part of Rattail.
#
@ -36,6 +36,7 @@ from deform import widget as dfwidget
from pyramid import httpexceptions
from webhelpers2.html import tags, HTML
# from tailbone import forms
from tailbone.db import Session
from tailbone.views import MasterView
from tailbone.util import raw_datetime
@ -140,6 +141,8 @@ class MessagesView(MasterView):
return six.text_type(sender)
def render_subject_bold(self, message, field):
if not message.subject:
return ""
return HTML.tag('span', c=message.subject, style='font-weight: bold;')
def render_recipients(self, message, column_name):
@ -212,9 +215,12 @@ class MessagesView(MasterView):
super(MessagesView, self).configure_form(f)
use_buefy = self.get_use_buefy()
# we have custom logic to disable submit button
f.auto_disable = False
f.auto_disable_save = False
f.submit_label = "Send Message"
if not use_buefy:
# we have custom logic to disable submit button
f.auto_disable = False
f.auto_disable_save = False
# TODO: A fair amount of this still seems hacky...
@ -223,22 +229,34 @@ class MessagesView(MasterView):
f.set_type('sent', 'datetime')
# recipients
f.set_renderer('recipients', self.render_recipients_full)
f.set_label('recipients', "To")
# subject
if use_buefy:
f.set_renderer('subject', self.render_subject_bold)
if self.creating:
f.set_widget('subject', dfwidget.TextInputWidget(
placeholder="please enter a subject",
autocomplete='off'))
f.set_required('subject')
# body
f.set_widget('body', dfwidget.TextAreaWidget(cols=50, rows=15))
if self.creating:
f.remove('sender', 'sent')
f.insert_after('recipients', 'recipients_')
# recipients
f.insert_after('recipients', 'set_recipients')
f.remove('recipients')
f.set_node('recipients_', colander.SchemaNode(colander.Set()))
f.set_widget('recipients_', RecipientsWidget())
f.set_label('recipients_', "To")
f.set_node('set_recipients', colander.SchemaNode(colander.Set()))
if use_buefy:
f.set_widget('set_recipients', RecipientsWidgetBuefy())
else:
f.set_widget('set_recipients', RecipientsWidget())
f.set_label('set_recipients', "To")
if self.replying:
old_message = self.get_instance()
@ -259,11 +277,11 @@ class MessagesView(MasterView):
value = [r[0] for r in value]
if old_message.sender is not self.request.user and old_message.sender.active:
value.insert(0, old_message.sender_uuid)
f.set_default('recipients_', ','.join(value))
f.set_default('set_recipients', ','.join(value))
# Just a normal reply, to sender only.
elif self.filter_reply_recipient(old_message.sender):
f.set_default('recipients_', old_message.sender.uuid)
f.set_default('set_recipients', old_message.sender.uuid)
# TODO?
# # Set focus to message body instead of recipients, when replying.
@ -281,7 +299,7 @@ class MessagesView(MasterView):
if self.request.user:
message.sender = self.request.user
for uuid in data['recipients_']:
for uuid in data['set_recipients']:
user = self.Session.query(model.User).get(uuid)
if user:
message.add_recipient(user, status=self.enum.MESSAGE_STATUS_INBOX)
@ -322,11 +340,21 @@ class MessagesView(MasterView):
return recipient
def template_kwargs_create(self, **kwargs):
recips = list(self.get_available_recipients().items())
use_buefy = self.get_use_buefy()
recips = self.get_available_recipients()
if use_buefy:
kwargs['recipient_display_map'] = recips
recips = list(recips.items())
recips.sort(key=self.recipient_sortkey)
kwargs['available_recipients'] = recips
if self.replying:
kwargs['original_message'] = self.get_instance()
if use_buefy:
kwargs['index_url'] = None
kwargs['index_title'] = "New Message"
return kwargs
def recipient_sortkey(self, recip):
@ -355,7 +383,7 @@ class MessagesView(MasterView):
kwargs['message'] = message
kwargs['recipient'] = recipient
if recipient.status == self.enum.MESSAGE_STATUS_ARCHIVE:
if recipient and recipient.status == self.enum.MESSAGE_STATUS_ARCHIVE:
kwargs['index_url'] = self.request.route_url('messages.archive')
return kwargs
@ -514,6 +542,30 @@ class RecipientsWidget(dfwidget.TextInputWidget):
return pstruct.split(',')
class RecipientsWidgetBuefy(dfwidget.Widget):
"""
Custom "message recipients" widget, for use with Buefy / Vue.js themes.
"""
template = 'message_recipients_buefy'
def deserialize(self, field, pstruct):
if pstruct is colander.null:
return colander.null
if not isinstance(pstruct, six.string_types):
raise colander.Invalid(field.schema, "Pstruct is not a string")
if not pstruct:
return colander.null
pstruct = pstruct.split(',')
return pstruct
def serialize(self, field, cstruct, **kw):
if cstruct in (colander.null, None):
cstruct = ""
template = self.template
values = self.get_template_values(field, cstruct, kw)
return field.renderer(template, **values)
def includeme(config):
config.add_tailbone_permission('messages', 'messages.list', "List/Search Messages")