diff options
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/App.pm | 30 | ||||
-rwxr-xr-x | perllib/FixMyStreet/App/Controller/Develop.pm | 136 | ||||
-rw-r--r-- | t/app/controller/develop.t | 33 | ||||
-rwxr-xr-x | templates/web/base/develop/email_list.html | 11 |
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' %] |