aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--perllib/FixMyStreet/App.pm30
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Develop.pm136
-rw-r--r--t/app/controller/develop.t33
-rwxr-xr-xtemplates/web/base/develop/email_list.html11
5 files changed, 201 insertions, 11 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 20594f363..3304f5860 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@
- Don't delete hidden field values when inspecting reports. #1999
- Admin improvements:
- Inspectors can set non_public status of reports. #1992
+ - Development improvements:
+ - Add HTML email previewer.
* v2.3.1 (12th February 2018)
- Front end improvements:
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index 008aea595..e23bc7622 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -344,6 +344,24 @@ sub send_email {
my $extra_stash_values = shift || {};
my $sender = $c->config->{DO_NOT_REPLY_EMAIL};
+ my $email = $c->construct_email($template, $extra_stash_values) or return;
+
+ my $result = 0;
+ try {
+ FixMyStreet::Email::Sender->send($email, { from => $sender });
+ $result = $email;
+ } catch {
+ my $error = $_ || 'unknown error';
+ $c->log->error("$error");
+ };
+ return $result;
+}
+
+sub construct_email {
+ my ($c, $template, $extra_stash_values) = @_;
+ $extra_stash_values //= {};
+
+ my $sender = $c->config->{DO_NOT_REPLY_EMAIL};
my $sender_name = $c->cobrand->contact_name;
# create the vars to pass to the email template
@@ -378,17 +396,7 @@ sub send_email {
$data->{_html_} = $html_compiled if $html_compiled;
$data->{_html_images_} = \@inline_images if @inline_images;
- my $email = mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email($data) };
-
- my $result = 0;
- try {
- FixMyStreet::Email::Sender->send($email, { from => $sender });
- $result = $email;
- } catch {
- my $error = $_ || 'unknown error';
- $c->log->error("$error");
- };
- return $result;
+ return mySociety::Locale::in_gb_locale { FixMyStreet::Email::construct_email($data) };
}
=head2 uri_with
diff --git a/perllib/FixMyStreet/App/Controller/Develop.pm b/perllib/FixMyStreet/App/Controller/Develop.pm
new file mode 100755
index 000000000..0bc52883f
--- /dev/null
+++ b/perllib/FixMyStreet/App/Controller/Develop.pm
@@ -0,0 +1,136 @@
+package FixMyStreet::App::Controller::Develop;
+use Moose;
+use namespace::autoclean;
+
+use File::Basename;
+
+BEGIN { extends 'Catalyst::Controller'; }
+
+=head1 NAME
+
+FixMyStreet::App::Controller::Develop - Catalyst Controller
+
+=head1 DESCRIPTION
+
+Developer-helping Catalyst Controller.
+
+=head1 METHODS
+
+=over 4
+
+=item auto
+
+Makes sure this controller is only available when run in development.
+
+=cut
+
+sub auto : Private {
+ my ($self, $c) = @_;
+ $c->detach( '/page_error_404_not_found' ) unless $c->config->{STAGING_SITE};
+ return 1;
+}
+
+=item email_list
+
+Shows a list of links to preview HTML emails.
+
+=cut
+
+sub email_list : Path('/_dev/email') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ my @include_path = @{ $c->cobrand->path_to_email_templates($c->stash->{lang_code}) };
+ push @include_path, $c->view('Email')->config->{INCLUDE_PATH}->[0];
+ my %templates;
+ foreach (@include_path) {
+ $templates{$_} = 1 for grep { /^[^_]/ } map { s/\.html$//; basename $_ } glob "$_/*.html";
+ }
+
+ my %with_update = ('update-confirm' => 1, 'other-updated' => 1);
+ my %with_problem = ('alert-update' => 1, 'other-reported' => 1,
+ 'problem-confirm' => 1, 'problem-confirm-not-sending' => 1,
+ 'problem-moderated' => 1, 'questionnaire' => 1, 'submit' => 1);
+
+ my $update = $c->model('DB::Comment')->first;
+ my $problem = $c->model('DB::Problem')->first;
+
+ $c->stash->{templates} = [];
+ foreach (sort keys %templates) {
+ my $url = $c->uri_for('/_dev/email', $_);
+ $url .= "?problem=" . $problem->id if $problem && $with_problem{$_};
+ $url .= "?update=" . $update->id if $update && $with_update{$_};
+ push @{$c->stash->{templates}}, { name => $_, url => $url };
+ }
+}
+
+=item email_previewer
+
+Previews an HTML email template. A problem or update ID can be provided as a
+query parameter, and other data is taken from the database.
+
+=back
+
+=cut
+
+sub email_previewer : Path('/_dev/email') : Args(1) {
+ my ( $self, $c, $template ) = @_;
+
+ my $vars = {};
+ if (my $id = $c->get_param('update')) {
+ $vars->{update} = $c->model('DB::Comment')->find($id);
+ $vars->{problem} = $vars->{report} = $vars->{update}->problem;
+ } elsif ($id = $c->get_param('problem')) {
+ $vars->{problem} = $vars->{report} = $c->model('DB::Problem')->find($id);
+ }
+
+ # Special case needed variables
+ if ($template =~ /^alert-problem/) {
+ $vars->{area_name} = 'Area Name';
+ $vars->{ward_name} = 'Ward Name';
+ $vars->{data} = [ $c->model('DB::Problem')->search({}, { rows => 5 })->all ];
+ } elsif ($template eq 'alert-update') {
+ $vars->{data} = [];
+ my $q = $c->model('DB::Comment')->search({}, { rows => 5 });
+ while (my $u = $q->next) {
+ my $fn = sub {
+ return FixMyStreet::App::Model::PhotoSet->new({
+ db_data => $u->photo,
+ })->get_image_data( num => 0, size => 'fp' );
+ };
+ push @{$vars->{data}}, {
+ item_photo => $u->photo, get_first_image_fp => $fn, item_text => $u->text,
+ item_name => $u->name, item_anonymous => $u->anonymous, confirmed => $u->confirmed };
+ }
+ } elsif ($template eq 'questionnaire') {
+ $vars->{created} = 'N weeks';
+ }
+
+ my $email = $c->construct_email("$template.txt", $vars);
+
+ # Look through the Email::MIME email for the text/html part, and any inline
+ # images. Turn the images into data: URIs.
+ my $html = '';
+ my %images;
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ return if $part->subparts;
+ if ($part->content_type =~ m[^image/]i) {
+ (my $cid = $part->header('Content-ID')) =~ s/[<>]//g;
+ (my $ct = $part->content_type) =~ s/;.*//;
+ $images{$cid} = "$ct;base64," . $part->body_raw;
+ } elsif ($part->content_type =~ m[text/html]i) {
+ $html = $part->body_str;
+ }
+ });
+
+ foreach (keys %images) {
+ $html =~ s/cid:([^"]*)/data:$images{$1}/g;
+ }
+
+ $c->response->body($html);
+}
+
+__PACKAGE__->meta->make_immutable;
+
+1;
+
diff --git a/t/app/controller/develop.t b/t/app/controller/develop.t
new file mode 100644
index 000000000..92aa86721
--- /dev/null
+++ b/t/app/controller/develop.t
@@ -0,0 +1,33 @@
+use FixMyStreet::TestMech;
+
+ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
+
+my ($problem) = $mech->create_problems_for_body(1, 2504, 'title');
+my $update = $mech->create_comment_for_problem($problem, $problem->user, 'Name', 'Text', 'f', 'confirmed', 'confirmed');
+
+subtest 'not visible on live site' => sub {
+ FixMyStreet::override_config {
+ STAGING_SITE => 0
+ }, sub {
+ $mech->get('/_dev/email/');
+ is $mech->res->code, 404;
+ $mech->get('/_dev/email/login');
+ is $mech->res->code, 404;
+ };
+};
+
+subtest 'dev email index page' => sub {
+ $mech->get_ok('/_dev/email/');
+ $mech->content_contains('login">login</a></li>');
+ $mech->content_contains('questionnaire?problem=' . $problem->id . '">questionnaire</a></li>');
+ $mech->content_contains('update-confirm?update=' . $update->id . '">update-confirm</a></li>');
+};
+
+subtest 'individual email previews' => sub {
+ $mech->get_ok('/_dev/email/alert-problem-area');
+ $mech->get_ok('/_dev/email/alert-update?problem=' . $problem->id);
+ $mech->get_ok('/_dev/email/questionnaire?problem=' . $problem->id);
+ $mech->get_ok('/_dev/email/update-confirm?update=' . $update->id);
+};
+
+done_testing();
diff --git a/templates/web/base/develop/email_list.html b/templates/web/base/develop/email_list.html
new file mode 100755
index 000000000..5b4298522
--- /dev/null
+++ b/templates/web/base/develop/email_list.html
@@ -0,0 +1,11 @@
+[% INCLUDE 'header.html' %]
+
+<h1>[% loc('Templates') %]</h1>
+
+<ul>
+[% FOR template IN templates %]
+<li><a href="[% template.url %]">[% template.name %]</a></li>
+[% END %]
+</ul>
+
+[% INCLUDE 'footer.html' %]