diff options
-rwxr-xr-x | bin/send-alerts | 25 | ||||
-rwxr-xr-x | bin/send-reports | 9 | ||||
-rw-r--r-- | conf/general-example | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Alert.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/ResultSet/AlertType.pm (renamed from perllib/FixMyStreet/Alert.pm) | 173 | ||||
-rw-r--r-- | perllib/FixMyStreet/TestMech.pm | 5 | ||||
-rw-r--r-- | t/app/controller/alert_new.t | 141 | ||||
-rw-r--r-- | templates/web/default/alert/list.html | 4 | ||||
-rw-r--r-- | templates/web/default/report/display.html | 2 |
9 files changed, 231 insertions, 134 deletions
diff --git a/bin/send-alerts b/bin/send-alerts index c52af4059..89dc18ee7 100755 --- a/bin/send-alerts +++ b/bin/send-alerts @@ -5,37 +5,18 @@ # # Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. # Email: matthew@mysociety.org. WWW: http://www.mysociety.org -# -# $Id: send-alerts,v 1.5 2010-01-06 16:50:25 louise Exp $ use strict; require 5.8.0; use CGI; # XXX - -# Horrible boilerplate to set up appropriate library paths. -use FindBin; -use lib "$FindBin::Bin/../perllib"; -use lib "$FindBin::Bin/../commonlib/perllib"; use CronFns; use mySociety::Config; -use mySociety::DBHandle qw(dbh); -use FixMyStreet::Alert; - -BEGIN { - mySociety::Config::set_file("$FindBin::Bin/../conf/general"); - mySociety::DBHandle::configure( - Name => mySociety::Config::get('BCI_DB_NAME'), - User => mySociety::Config::get('BCI_DB_USER'), - Password => mySociety::Config::get('BCI_DB_PASS'), - Host => mySociety::Config::get('BCI_DB_HOST', undef), - Port => mySociety::Config::get('BCI_DB_PORT', undef) - ); -} +use FixMyStreet::App; my $site = CronFns::site(mySociety::Config::get('BASE_URL')); CronFns::language($site); -my $testing_email = mySociety::Config::get('TESTING_EMAIL'); -FixMyStreet::Alert::email_alerts($testing_email); + +FixMyStreet::App->model('DB::AlertType')->email_alerts(); diff --git a/bin/send-reports b/bin/send-reports index feee74c76..fbbd3db5e 100755 --- a/bin/send-reports +++ b/bin/send-reports @@ -192,14 +192,11 @@ while (my $row = $unsent->next) { die 'Report not going anywhere for ID ' . $row->id . '!'; } - my $testing_email = mySociety::Config::get('TESTING_EMAIL'); - if ($row->user->email eq $testing_email) { - @recips = ( $testing_email ); - $send_web = 0; - $send_email = 1; - } elsif (mySociety::Config::get('STAGING_SITE')) { + if (mySociety::Config::get('STAGING_SITE')) { # on a staging server send emails to ourselves rather than the councils @recips = ( mySociety::Config::get('CONTACT_EMAIL') ); + $send_web = 0; + $send_email = 1; } elsif ($site eq 'emptyhomes') { my $council = $row->council; my $country = $areas_info->{$council}->{country}; diff --git a/conf/general-example b/conf/general-example index 7e750de96..510557e46 100644 --- a/conf/general-example +++ b/conf/general-example @@ -30,7 +30,6 @@ define('OPTION_BASE_URL', 'http://www.example.org'); # Which country are you operating in? ISO3166-alpha2 code please define('OPTION_COUNTRY', 'GB'); -define('OPTION_TESTING_EMAIL', 'testing@example.com'); define('OPTION_EMAIL_DOMAIN', 'example.org'); define('OPTION_CONTACT_EMAIL', 'team@'.OPTION_EMAIL_DOMAIN); define('OPTION_TEST_EMAIL_PREFIX', null); diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm index d8e783431..b3067abc9 100644 --- a/perllib/FixMyStreet/App/Controller/Alert.pm +++ b/perllib/FixMyStreet/App/Controller/Alert.pm @@ -63,6 +63,9 @@ sub subscribe : Path('subscribe') : Args(0) { elsif ( exists $c->req->params->{'rznvy'} ) { $c->detach('subscribe_email'); } + elsif ( $c->req->params->{'id'} ) { + $c->go('updates'); + } # shouldn't get to here but if we have then do something sensible $c->go('index'); @@ -198,7 +201,7 @@ sub create_alert : Private { $options->{cobrand_data} = $c->cobrand->extra_update_data(); $options->{lang} = $c->stash->{lang_code}; - if ( $c->user && $c->user->id == $c->stash->{alert_user}->id ) { + if ( $c->user && $c->stash->{alert_user}->in_storage && $c->user->id == $c->stash->{alert_user}->id ) { $options->{confirmed} = 1; } diff --git a/perllib/FixMyStreet/Alert.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm index 64bd40dba..405210861 100644 --- a/perllib/FixMyStreet/Alert.pm +++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm @@ -1,46 +1,29 @@ -#!/usr/bin/perl -w -# -# FixMyStreet::Alert.pm -# Alerts by email or RSS. -# -# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved. -# Email: matthew@mysociety.org; WWW: http://www.mysociety.org/ -# -# $Id: Alert.pm,v 1.71 2010-01-06 16:50:27 louise Exp $ - -package FixMyStreet::Alert; +package FixMyStreet::DB::ResultSet::AlertType; +use base 'DBIx::Class::ResultSet'; use strict; -use Error qw(:try); +use warnings; + use File::Slurp; -use FindBin; -use POSIX qw(strftime); -use Cobrand; -use mySociety::AuthToken; use mySociety::DBHandle qw(dbh); -use mySociety::Email; use mySociety::EmailUtil; use mySociety::Gaze; use mySociety::Locale; use mySociety::MaPit; -use mySociety::Random qw(random_bytes); # Child must have confirmed, id, email, state(!) columns # If parent/child, child table must also have name and text # and foreign key to parent must be PARENT_id sub email_alerts ($) { - my ($testing_email) = @_; - my $url; - my $q = dbh()->prepare("select * from alert_type where ref not like '%local_problems%'"); - $q->execute(); - my $testing_email_clause = ''; - while (my $alert_type = $q->fetchrow_hashref) { - my $ref = $alert_type->{ref}; - my $head_table = $alert_type->{head_table}; - my $item_table = $alert_type->{item_table}; - my $testing_email_clause = "and $item_table.email <> '$testing_email'" if $testing_email; - my $query = 'select alert.id as alert_id, alert.email as alert_email, alert.lang as alert_lang, alert.cobrand as alert_cobrand, + my ( $rs ) = @_; + + my $q = $rs->search( { ref => { -not_like => '%local_problems%' } } ); + while (my $alert_type = $q->next) { + my $ref = $alert_type->ref; + my $head_table = $alert_type->head_table; + my $item_table = $alert_type->item_table; + my $query = 'select alert.id as alert_id, alert_user.email as alert_email, alert.lang as alert_lang, alert.cobrand as alert_cobrand, alert.cobrand_data as alert_cobrand_data, alert.parameter as alert_parameter, alert.parameter2 as alert_parameter2, '; if ($head_table) { $query .= " @@ -48,19 +31,21 @@ sub email_alerts ($) { $head_table.* from alert inner join $item_table on alert.parameter::integer = $item_table.${head_table}_id - inner join $head_table on alert.parameter::integer = $head_table.id"; + inner join $head_table on alert.parameter::integer = $head_table.id + inner join users as alert_user on alert.user_id = alert_user.id"; } else { $query .= " $item_table.*, $item_table.id as item_id - from alert, $item_table"; + from alert + cross join $item_table + inner join users as alert_user on alert.user_id = alert_user.id"; } $query .= " where alert_type='$ref' and whendisabled is null and $item_table.confirmed >= whensubscribed and $item_table.confirmed >= ms_current_timestamp() - '7 days'::interval and (select whenqueued from alert_sent where alert_sent.alert_id = alert.id and alert_sent.parameter::integer = $item_table.id) is null - and $item_table.email <> alert.email - $testing_email_clause - and $alert_type->{item_where} + and $item_table.user_id <> alert.user_id + and " . $alert_type->item_where . " and alert.confirmed = 1 order by alert.id, $item_table.confirmed"; # XXX Ugh - needs work @@ -69,18 +54,24 @@ sub email_alerts ($) { $query = dbh()->prepare($query); $query->execute(); my $last_alert_id; - my %data = ( template => $alert_type->{template}, data => '' ); + my %data = ( template => $alert_type->template, data => '' ); while (my $row = $query->fetchrow_hashref) { + + my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->{alert_cobrand})->new(); + # Cobranded and non-cobranded messages can share a database. In this case, the conf file # should specify a vhost to send the reports for each cobrand, so that they don't get sent # more than once if there are multiple vhosts running off the same database. The email_host # call checks if this is the host that sends mail for this cobrand. - next unless (Cobrand::email_host($row->{alert_cobrand})); + next unless $cobrand->email_host; - dbh()->do('insert into alert_sent (alert_id, parameter) values (?,?)', {}, $row->{alert_id}, $row->{item_id}); + FixMyStreet::App->model('DB::AlertSent')->create( { + alert_id => $row->{alert_id}, + parameter => $row->{item_id}, + } ); if ($last_alert_id && $last_alert_id != $row->{alert_id}) { _send_aggregated_alert_email(%data); - %data = ( template => $alert_type->{template}, data => '' ); + %data = ( template => $alert_type->template, data => '' ); } # create problem status message for the templates @@ -89,7 +80,7 @@ sub email_alerts ($) { ? _("This report is currently marked as fixed.") : _("This report is currently marked as open."); - $url = Cobrand::base_url_for_emails($row->{alert_cobrand}, $row->{alert_cobrand_data}); + my $url = $cobrand->base_url_for_emails( $row->{alert_cobrand_data} ); if ($row->{item_text}) { $data{problem_url} = $url . "/report/" . $row->{id}; $data{data} .= $row->{item_name} . ' : ' if $row->{item_name}; @@ -119,35 +110,44 @@ sub email_alerts ($) { } # Nearby done separately as the table contains the parameters - my $template = dbh()->selectrow_array("select template from alert_type where ref = 'local_problems'"); - my $query = "select * from alert where alert_type='local_problems' and whendisabled is null and confirmed=1 order by id"; - $query = dbh()->prepare($query); - $query->execute(); - while (my $alert = $query->fetchrow_hashref) { - next unless (Cobrand::email_host($alert->{cobrand})); - my $longitude = $alert->{parameter}; - my $latitude = $alert->{parameter2}; - $url = Cobrand::base_url_for_emails($alert->{cobrand}, $alert->{cobrand_data}); - my ($site_restriction, $site_id) = Cobrand::site_restriction($alert->{cobrand}, $alert->{cobrand_data}); + my $template = $rs->find( { ref => 'local_problems' } )->template; + my $query = FixMyStreet::App->model('DB::Alert')->search( { + alert_type => 'local_problems', + whendisabled => undef, + confirmed => 1 + }, { + order_by => 'id' + } ); + while (my $alert = $query->next) { + my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($alert->cobrand)->new(); + next unless $cobrand->email_host; + + my $longitude = $alert->parameter; + my $latitude = $alert->parameter2; + my $url = $cobrand->base_url_for_emails( $alert->cobrand_data ); + my ($site_restriction, $site_id) = $cobrand->site_restriction( $alert->cobrand_data ); my $d = mySociety::Gaze::get_radius_containing_population($latitude, $longitude, 200000); # Convert integer to GB locale string (with a ".") $d = mySociety::Locale::in_gb_locale { sprintf("%f", int($d*10+0.5)/10); }; - my $testing_email_clause = "and problem.email <> '$testing_email'" if $testing_email; - my %data = ( template => $template, data => '', alert_id => $alert->{id}, alert_email => $alert->{email}, lang => $alert->{lang}, cobrand => $alert->{cobrand}, cobrand_data => $alert->{cobrand_data} ); - my $q = "select * from problem_find_nearby(?, ?, ?) as nearby, problem - where nearby.problem_id = problem.id and problem.state in ('confirmed', 'fixed') + my %data = ( template => $template, data => '', alert_id => $alert->id, alert_email => $alert->user->email, lang => $alert->lang, cobrand => $alert->cobrand, cobrand_data => $alert->cobrand_data ); + my $q = "select problem.id, problem.title from problem_find_nearby(?, ?, ?) as nearby, problem, users + where nearby.problem_id = problem.id + and problem.user_id = users.id + and problem.state in ('confirmed', 'fixed') and problem.confirmed >= ? and problem.confirmed >= ms_current_timestamp() - '7 days'::interval and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null - and problem.email <> ? - $testing_email_clause + and users.email <> ? $site_restriction order by confirmed desc"; $q = dbh()->prepare($q); - $q->execute($latitude, $longitude, $d, $alert->{whensubscribed}, $alert->{id}, $alert->{email}); + $q->execute($latitude, $longitude, $d, $alert->whensubscribed, $alert->id, $alert->user->email); while (my $row = $q->fetchrow_hashref) { - dbh()->do('insert into alert_sent (alert_id, parameter) values (?,?)', {}, $alert->{id}, $row->{id}); + FixMyStreet::App->model('DB::AlertSent')->create( { + alert_id => $alert->id, + parameter => $row->{id}, + } ); $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n"; } _send_aggregated_alert_email(%data) if $data{data}; @@ -156,32 +156,47 @@ sub email_alerts ($) { sub _send_aggregated_alert_email(%) { my %data = @_; - Cobrand::set_lang_and_domain($data{cobrand}, $data{lang}, 1); - - $data{unsubscribe_url} = Cobrand::base_url_for_emails($data{cobrand}, $data{cobrand_data}) . '/A/' - . mySociety::AuthToken::store('alert', { id => $data{alert_id}, type => 'unsubscribe', email => $data{alert_email} } ); - my $template = "$FindBin::Bin/../templates/emails/$data{template}"; - if ($data{cobrand}) { - my $template_cobrand = "$FindBin::Bin/../templates/emails/$data{cobrand}/$data{template}"; - $template = $template_cobrand if -e $template_cobrand; - } + + my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($data{cobrand})->new(); + + $cobrand->set_lang_and_domain( $data{lang}, 1 ); + + my $token = FixMyStreet::App->model("DB::Token")->new_result( { + scope => 'alert', + data => { + id => $data{alert_id}, + type => 'unsubscribe', + email => $data{alert_email}, + } + } ); + $data{unsubscribe_url} = $cobrand->base_url_for_emails( $data{cobrand_data} ) . '/A/' . $token->token; + + my $template = FixMyStreet->path_to( + "templates", "email", $cobrand->moniker, "$data{template}.txt" + )->stringify; + my $template_cobrand = FixMyStreet->path_to( + "templates", "email", $cobrand->moniker, $data{lang}, "$data{template}.txt" + )->stringify; + $template = $template_cobrand if -e $template_cobrand; $template = File::Slurp::read_file($template); - my $sender = Cobrand::contact_email($data{cobrand}); - my $sender_name = Cobrand::contact_name($data{cobrand}); + + my $sender = $cobrand->contact_email; (my $from = $sender) =~ s/team/fms-DO-NOT-REPLY/; # XXX - my $email = mySociety::Email::construct_email({ - _template_ => _($template), - _parameters_ => \%data, - From => [ $from, _($sender_name) ], - To => $data{alert_email}, - 'Message-ID' => sprintf('<alert-%s-%s@mysociety.org>', time(), unpack('h*', random_bytes(5, 1))), - }); - - my $result = mySociety::EmailUtil::send_email($email, $sender, $data{alert_email}); + my $result = FixMyStreet::App->send_email_cron( + { + _template_ => $template, + _parameters_ => \%data, + From => [ $from, _($cobrand->contact_name) ], + To => $data{alert_email}, + }, + $sender, + [ $data{alert_email} ], + 0, + ); + if ($result == mySociety::EmailUtil::EMAIL_SUCCESS) { - dbh()->commit(); + $token->insert(); } else { - dbh()->rollback(); print "Failed to send alert $data{alert_id}!"; } } diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index c9f1d7dde..3dd4e84e9 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -151,8 +151,11 @@ sub delete_user { ok( $_->delete, "delete questionnaire " . $_->id ) for $p->questionnaires; ok( $p->delete, "delete problem " . $p->title ); } + for my $a ( $user->alerts ) { + $a->alert_sents->delete; + ok( $a->delete, "delete alert " . $a->alert_type ); + } ok( $_->delete, "delete comment " . $_->text ) for $user->comments; - ok( $_->delete, "delete alert " . $_->alert_type ) for $user->alerts; ok $user->delete, "delete test user " . $user->email; return 1; diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index 91e86bd46..ff1acd480 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -43,8 +43,8 @@ foreach my $test ( email_text => 'confirm the alert', uri => '/alert/subscribe?type=local&rznvy=test@example.com&feed=local:10.2:20.1', - param1 => 10.2, - param2 => 20.1, + param1 => 20.1, + param2 => 10.2, }, { email => 'test@example.com', @@ -66,7 +66,6 @@ foreach my $test ( ->find( { email => $test->{email} } ); # we don't want an alert - my $alert; if ($user) { $mech->delete_user($user); } @@ -80,7 +79,7 @@ foreach my $test ( ok $user, 'user created for alert'; - $alert = FixMyStreet::App->model('DB::Alert')->find( + my $alert = FixMyStreet::App->model('DB::Alert')->find( { user => $user, alert_type => $type, @@ -129,7 +128,7 @@ foreach my $test ( ); ok $token, 'new token found in database'; - ok $token->data->{id} == $existing_id, 'subscribed to exsiting alert'; + ok $token->data->{id} == $existing_id, 'subscribed to existing alert'; $mech->get_ok("/A/$url_token"); $mech->content_contains('successfully confirmed'); @@ -138,6 +137,7 @@ foreach my $test ( FixMyStreet::App->model('DB::Alert')->find( { id => $existing_id, } ); ok $alert->confirmed, 'alert set to confirmed'; + $mech->delete_user($user); }; } @@ -162,18 +162,14 @@ foreach my $test ( FixMyStreet::App->model('DB::User') ->find_or_create( { email => $test->{email} } ); - my $alert; - if ($user) { - $alert = FixMyStreet::App->model('DB::Alert')->find( - { - user => $user, - alert_type => $type - } - ); - - # clear existing data so we can be sure we're creating it - ok $alert->delete() if $alert; - } + my $alert = FixMyStreet::App->model('DB::Alert')->find( + { + user => $user, + alert_type => $type + } + ); + # clear existing data so we can be sure we're creating it + ok $alert->delete() if $alert; $mech->get_ok( $test->{uri} ); @@ -190,6 +186,7 @@ foreach my $test ( $mech->content_contains( 'Now check your email' ); ok $alert, 'New alert created with existing user'; + $mech->delete_user($user); }; } @@ -199,8 +196,6 @@ foreach my $test ( user => 'test-login@example.com', email => 'test-login@example.com', type => 'council', - content => 'your alert will not be activated', - email_text => 'confirm the alert', param1 => 2651, param2 => 2651, confirmed => 1, @@ -210,8 +205,6 @@ foreach my $test ( user => 'loggedin@example.com', email => 'test-login@example.com', type => 'council', - content => 'your alert will not be activated', - email_text => 'confirm the alert', param1 => 2651, param2 => 2651, confirmed => 0, @@ -350,6 +343,112 @@ for my $test ( ok !$alert->confirmed, 'alert not set to confirmed'; $abuse->delete; + $mech->delete_user($user); }; } + +subtest "Test normal alert signups and that alerts are sent" => sub { + my $user1 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'reporter@example.com', name => 'Reporter User' } ); + ok $user1, "created test user"; + $user1->alerts->delete; + + my $user2 = FixMyStreet::App->model('DB::User') + ->find_or_create( { email => 'alerts@example.com', name => 'Alert User' } ); + ok $user2, "created test user"; + $user2->alerts->delete; + + for my $alert ( + { feed => 'local:55.951963:-3.189944', email_confirm => 1 }, + { feed => 'council:2651:City_of_Edinburgh', }, + ) { + $mech->get_ok( '/alert' ); + $mech->submit_form_ok( { with_fields => { pc => 'EH11BB' } } ); + $mech->submit_form_ok( { + button => 'alert', + with_fields => { + rznvy => $user2->email, + feed => $alert->{feed}, + } + } ); + if ( $alert->{email_confirm} ) { + my $email = $mech->get_email; + $mech->clear_emails_ok; + my ( $url, $url_token ) = $email->body =~ m{http://\S+(/A/(\S+))}; + my $token = FixMyStreet::App->model('DB::Token')->find( { token => $url_token, scope => 'alert' } ); + $mech->get_ok( $url ); + $mech->content_contains('successfully confirmed'); + } else { + $mech->content_contains('successfully created'); + } + } + + my $dt = DateTime->now()->add( days => 2); + + my $report_time = '2011-03-01 12:00:00'; + my $report = FixMyStreet::App->model('DB::Problem')->find_or_create( { + postcode => 'EH1 1BB', + council => '2651', + areas => ',11808,135007,14419,134935,2651,20728,', + category => 'Street lighting', + title => 'Testing', + detail => 'Testing Detail', + used_map => 1, + name => $user1->name, + anonymous => 0, + state => 'confirmed', + confirmed => $dt, + lastupdate => $dt, + whensent => $dt->clone->add( minutes => 5 ), + lang => 'en-gb', + service => '', + cobrand => 'default', + cobrand_data => '', + send_questionnaire => 1, + latitude => '55.951963', + longitude => '-3.189944', + user_id => $user1->id, + } ); + my $report_id = $report->id; + ok $report, "created test report - $report_id"; + + my $alert = FixMyStreet::App->model('DB::Alert')->create( { + parameter => $report_id, + alert_type => 'new_updates', + user => $user1, + } )->confirm; + ok $alert, 'created alert for reporter'; + + my $update = FixMyStreet::App->model('DB::Comment')->create( { + problem_id => $report_id, + user_id => $user2->id, + name => 'Other User', + mark_fixed => 'false', + text => 'This is some update text', + state => 'confirmed', + confirmed => $dt->clone->add( hours => 7 ), + anonymous => 'f', + } ); + my $update_id = $update->id; + ok $update, "created test update - $update_id"; + + FixMyStreet::App->model('DB::AlertType')->email_alerts(); + $mech->email_count_is(3); + my @emails = $mech->get_email; + my $count; + for (@emails) { + $count++ if $_->body =~ /The following updates have been left on this problem:/; + $count++ if $_->body =~ /The following new problems have been reported to City of\s*Edinburgh Council:/; + $count++ if $_->body =~ /The following nearby problems have been added:/; + } + is $count, 3, 'Three emails with the right things in them'; + + my ( $url, $url_token ) = $emails[0]->body =~ m{http://\S+(/A/(\S+))}; + $mech->get_ok( $url ); + $mech->content_contains('successfully deleted'); + + $mech->delete_user($user1); + $mech->delete_user($user2); +}; + done_testing(); diff --git a/templates/web/default/alert/list.html b/templates/web/default/alert/list.html index a8f962c5d..bb515232a 100644 --- a/templates/web/default/alert/list.html +++ b/templates/web/default/alert/list.html @@ -35,13 +35,13 @@ [% IF pretty_pc %] [% tprintf( loc('Here are the types of local problem alerts for ‘%s’.'), pretty_pc ) %] [% END %] - [% loc('Select which type of alert you\'d like and click the button for an RSS feed, or enter your email address to subscribe to an email alert') %] + [% loc('Select which type of alert you\'d like and click the button for an RSS feed, or enter your email address to subscribe to an email alert.') %] </p> [% INCLUDE 'errors.html' %] <p> - [% loc('The simplest alert is our geographic one') %] + [% loc('The simplest alert is our geographic one:') %] </p> <p id="rss_local"> diff --git a/templates/web/default/report/display.html b/templates/web/default/report/display.html index 4fa58c1db..b877874e5 100644 --- a/templates/web/default/report/display.html +++ b/templates/web/default/report/display.html @@ -39,7 +39,7 @@ </p> <div id="alert_links"> - <a rel="nofollow" id="email_alert" href="[% c.uri_for( '/alert', { type => 'updates', id => problem.id } ) %]">[% loc('Email me updates' ) %]</a> + <a rel="nofollow" id="email_alert" href="[% c.uri_for( '/alert/subscribe', { id => problem.id } ) %]">[% loc('Email me updates' ) %]</a> <form action="[% c.uri_for( '/alert/subscribe' ) %]" method="post" id="email_alert_box"> <p>[% loc('Receive email when updates are left on this problem.' ) %]</p> |