wagtail-birdsong/birdsong/options.py

178 lines
6.5 KiB
Python

from django.conf import settings
from django.forms import modelform_factory
from django.http.response import HttpResponseRedirect
from django.urls import re_path
from django.utils.module_loading import import_string
from wagtail.contrib.modeladmin.helpers import AdminURLHelper, ButtonHelper
from wagtail.contrib.modeladmin.options import ModelAdmin
from birdsong.backends.smtp import SMTPEmailBackend
from .models import CampaignStatus, Contact
from .views import actions
from .views import editor as editor_views
BIRDSONG_DEFAULT_BACKEND = 'birdsong.backends.smtp.SMTPEmailBackend'
class EmailCampaignButtonHelper(ButtonHelper):
def get_buttons_for_obj(self, campaign, **kwargs):
url_helper = AdminURLHelper(self.model)
def button(action_url, label, classnames):
return {
'url': url_helper.get_action_url(action_url, instance_pk=campaign.id),
'label': label,
'title': label,
'classname': 'button button-small ' + classnames
}
if campaign.status == CampaignStatus.SENDING:
return [
button('preview', 'Preview', 'button-secondary icon icon-view'),
]
sent = campaign.status != CampaignStatus.UNSENT
delete_btn = button('delete', 'Delete', 'no button-secondary')
copy_btn = button('copy', 'Copy', 'button-secondary')
if not sent:
buttons = [
button('edit', 'Edit', 'bicolor icon icon-edit'),
copy_btn,
button('confirm_send', 'Send', 'bicolor icon icon-mail'),
button('send_test', 'Send test', 'button-secondary icon icon-cog'),
button('preview', 'Preview', 'button-secondary icon icon-view'),
delete_btn
]
else:
buttons = [
button('inspect', 'View', 'button-secondary icon icon-view'),
copy_btn,
delete_btn,
]
return buttons
class CampaignAdmin(ModelAdmin):
campaign = None
list_display = ('name', 'status', 'sent_date')
button_helper_class = EmailCampaignButtonHelper
inspect_view_enabled = True
inspect_view_class = editor_views.InspectCampaign
inspect_template_name = 'birdsong/editor/inspect_campaign.html'
edit_template_name = 'birdsong/editor/edit_campaign.html'
edit_view_class = editor_views.EditCampaignView
create_view_class = editor_views.CreateCampaignView
create_template_name = 'birdsong/editor/create_campaign.html'
backend_class = import_string(
getattr(settings, 'BIRDSONG_BACKEND', BIRDSONG_DEFAULT_BACKEND)
)
contact_class = Contact
contact_filter_class = None
# FIXME needs to be overwritable
form_view_extra_js = ['birdsong/js/preview_campaign.js']
form_view_extra_css = ['birdsong/css/campaign-editor.css']
def __init__(self, parent=None):
if not self.model and self.campaign:
self.model = self.campaign
super().__init__(parent=parent)
self.backend = self.backend_class()
def get_admin_urls_for_registration(self):
urls = super().get_admin_urls_for_registration()
def gen_url(pattern, view, name=None):
if not name:
name = pattern
return re_path(
self.url_helper.get_action_url_pattern(pattern),
view,
name=self.url_helper.get_action_url_name(name)
)
urls = (
gen_url('preview', self.preview),
gen_url('confirm_send', self.confirm_send),
gen_url('send_campaign', self.send_campaign),
gen_url('confirm_test', self.confirm_test),
gen_url('send_test', self.send_test),
gen_url('copy', self.copy)
) + urls
return urls
def preview(self, request, instance_pk):
campaign = self.model.objects.get(pk=instance_pk)
contact = self.contact_class.objects.first()
return editor_views.preview(request, campaign, contact)
def confirm_send(self, request, instance_pk):
campaign = self.model.objects.get(pk=instance_pk)
form = self.build_sending_form()
return editor_views.confirm_send(
request,
campaign,
form,
self.url_helper.get_action_url('send_campaign', instance_pk=instance_pk),
self.url_helper.get_action_url('index')
)
def build_sending_form(self):
if not self.contact_filter_class:
return None
contact_filter = self.contact_filter_class()
return contact_filter.form
def get_contacts_send_to(self, request):
if self.contact_filter_class:
Filter = self.contact_filter_class
contact_filter = Filter(request.POST)
return contact_filter.qs
return self.contact_class.objects.all()
def send_campaign(self, request, instance_pk):
campaign = self.model.objects.get(pk=instance_pk)
contacts = self.get_contacts_send_to(request)
return actions.send_campaign(self.backend, request, campaign, contacts)
def create_contact_form(self, data=None):
ContactForm = modelform_factory(self.contact_class, exclude=['id'])
if data:
return ContactForm(data)
return ContactForm()
def confirm_test(self, request, campaign, form):
return editor_views.confirm_test(
request,
campaign,
form,
self.url_helper.get_action_url('send_test', campaign.id),
self.url_helper.get_action_url('index')
)
def send_test(self, request, instance_pk):
campaign = self.model.objects.get(pk=instance_pk)
if request.method == 'GET':
form = self.create_contact_form()
return self.confirm_test(request, campaign, form)
form = self.create_contact_form(request.POST)
if not form.is_valid():
return self.confirm_test(request, campaign, form)
# Create fake contact, send test email
contact = form.save(commit=False)
return actions.send_test(self.backend, request, campaign, contact)
def copy(self, request, instance_pk):
instance = self.model.objects.get(pk=instance_pk)
instance.name = instance.name + ' (Copy)'
instance.pk = None
instance.id = None
instance.sent_date = None
instance.status = CampaignStatus.UNSENT
instance.save()
return HttpResponseRedirect(self.url_helper.get_action_url('index'))