aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/App/Controller
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2013-02-01 15:28:08 +0000
committerMatthew Somerville <matthew@mysociety.org>2013-02-04 06:53:02 +0000
commit488a8f21a0c1bc2b9501c9d94d69db56cccd80ae (patch)
tree68becf501e9492466a80015e8ace9a7fb1557cfa /perllib/FixMyStreet/App/Controller
parent3e0d12e8584d132b573f536ab5cd01e24241827b (diff)
parent28aa1dd7fb1c9bc93aa204afae67cf68fe36ee6b (diff)
Merge remote branch 'origin/zurich'
Conflicts: bin/open311-populate-service-list bin/send-comments bin/update-all-reports conf/crontab.ugly db/schema.sql perllib/FixMyStreet/App/Controller/Admin.pm perllib/FixMyStreet/App/Controller/Report/New.pm perllib/FixMyStreet/App/Controller/Reports.pm perllib/FixMyStreet/Cobrand/Default.pm perllib/FixMyStreet/Cobrand/LichfieldDC.pm perllib/FixMyStreet/DB/Result/Open311conf.pm perllib/FixMyStreet/DB/Result/Problem.pm perllib/FixMyStreet/DB/ResultSet/Problem.pm perllib/FixMyStreet/SendReport.pm perllib/FixMyStreet/SendReport/Email.pm perllib/FixMyStreet/SendReport/Open311.pm perllib/Open311/GetServiceRequestUpdates.pm perllib/Open311/PopulateServiceList.pm t/app/controller/report_new.t t/app/controller/rss.t templates/web/bromley/report/display.html templates/web/default/admin/council_contacts.html templates/web/default/common_header_tags.html templates/web/default/dashboard/index.html templates/web/default/front/stats.html templates/web/default/report/_main.html templates/web/default/report/update-form.html templates/web/emptyhomes/index.html templates/web/emptyhomes/report/display.html templates/web/emptyhomes/report/new/councils_text_all.html templates/web/emptyhomes/reports/body.html templates/web/emptyhomes/reports/index.html templates/web/fixmystreet/report/new/fill_in_details_form.html templates/web/fixmystreet/report/update-form.html web/cobrands/fixmystreet/fixmystreet.js web/js/fixmystreet.js
Diffstat (limited to 'perllib/FixMyStreet/App/Controller')
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm473
-rw-r--r--perllib/FixMyStreet/App/Controller/Alert.pm6
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm73
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Council.pm52
-rw-r--r--perllib/FixMyStreet/App/Controller/Dashboard.pm21
-rwxr-xr-xperllib/FixMyStreet/App/Controller/JS.pm4
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm20
-rw-r--r--perllib/FixMyStreet/App/Controller/Open311.pm24
-rw-r--r--perllib/FixMyStreet/App/Controller/Photo.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm41
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm122
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/Update.pm8
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm360
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Rss.pm11
-rw-r--r--perllib/FixMyStreet/App/Controller/Tokens.pm22
16 files changed, 727 insertions, 515 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index e14c7dc66..a3a241590 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -4,8 +4,9 @@ use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller'; }
+use Path::Class;
use POSIX qw(strftime strcoll);
-use Digest::MD5 qw(md5_hex);
+use Digest::SHA1 qw(sha1_hex);
use mySociety::EmailUtil qw(is_valid_email);
use if !$ENV{TRAVIS}, 'Image::Magick';
@@ -23,23 +24,32 @@ Admin pages
=cut
-=head2 summary
-
-Redirect to index page. There to make the allowed pages stuff neater
-
-=cut
-
sub begin : Private {
my ( $self, $c ) = @_;
$c->uri_disposition('relative');
- if ( $c->cobrand->moniker eq 'seesomething' ) {
+ if ( $c->cobrand->moniker eq 'zurich' || $c->cobrand->moniker eq 'seesomething' ) {
$c->detach( '/auth/redirect' ) unless $c->user_exists;
- $c->detach( '/auth/redirect' ) unless $c->user->from_council;
+ $c->detach( '/auth/redirect' ) unless $c->user->from_body;
+ }
+ if ( $c->cobrand->moniker eq 'zurich' ) {
+ $c->cobrand->admin_type();
}
}
+sub auto : Private {
+ my ( $self, $c ) = @_;
+
+ $c->forward('check_page_allowed');
+}
+
+=head2 summary
+
+Redirect to index page. There to make the allowed pages stuff neater
+
+=cut
+
sub summary : Path( 'summary' ) : Args(0) {
my ( $self, $c ) = @_;
$c->go( 'index' );
@@ -54,7 +64,9 @@ Displays some summary information for the requests.
sub index : Path : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
+ if ($c->cobrand->moniker eq 'zurich' && $c->stash->{admin_type} ne 'super') {
+ return $c->cobrand->admin();
+ }
my $site_restriction = $c->cobrand->site_restriction();
@@ -124,8 +136,6 @@ sub index : Path : Args(0) {
sub timeline : Path( 'timeline' ) : Args(0) {
my ($self, $c) = @_;
- $c->forward('check_page_allowed');
-
my $site_restriction = $c->cobrand->site_restriction();
my %time;
@@ -175,8 +185,6 @@ sub timeline : Path( 'timeline' ) : Args(0) {
sub questionnaire : Path('questionnaire') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
-
my $questionnaires = $c->model('DB::Questionnaire')->search(
{ whenanswered => { '!=', undef } },
{ group_by => [ 'ever_reported' ],
@@ -207,10 +215,10 @@ sub questionnaire : Path('questionnaire') : Args(0) {
return 1;
}
-sub council_list : Path('council_list') : Args(0) {
+sub bodies : Path('bodies') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
+ $c->forward( 'get_token' );
my $edit_activity = $c->model('DB::ContactsHistory')->search(
undef,
@@ -224,54 +232,74 @@ sub council_list : Path('council_list') : Args(0) {
$c->stash->{edit_activity} = $edit_activity;
- # Not London, as treated separately
- my $area_types = $c->cobrand->moniker eq 'emptyhomes'
- ? $c->cobrand->area_types
- : [ grep { $_ ne 'LBO' } @{ $c->cobrand->area_types } ];
- my $areas = mySociety::MaPit::call('areas', $area_types);
+ my $posted = $c->req->param('posted') || '';
+ if ( $posted eq 'body' ) {
+ $c->forward('check_token');
- my @councils_ids = sort { strcoll($areas->{$a}->{name}, $areas->{$b}->{name}) } keys %$areas;
- @councils_ids = $c->cobrand->filter_all_council_ids_list( @councils_ids );
+ my $params = $c->forward('body_params');
+ my $body = $c->model('DB::Body')->create( $params );
+ my $area_ids = $c->req->params->{area_ids};
+ if ($area_ids) {
+ $area_ids = [ $area_ids ] unless ref $area_ids;
+ foreach (@$area_ids) {
+ $c->model('DB::BodyArea')->create( { body => $body, area_id => $_ } );
+ }
+ }
+
+ $c->stash->{updated} = _('New body added');
+ }
+
+ $c->forward( 'fetch_all_bodies' );
+
+ # XXX For fixmystreet.com, need to exclude bodies that are covering London.
+ # But soon, this means just don't have bodies covering London.
my $contacts = $c->model('DB::Contact')->search(
undef,
{
- select => [ 'area_id', { count => 'id' }, { count => \'case when deleted then 1 else null end' },
+ select => [ 'body_id', { count => 'id' }, { count => \'case when deleted then 1 else null end' },
{ count => \'case when confirmed then 1 else null end' } ],
- as => [qw/area_id c deleted confirmed/],
- group_by => [ 'area_id' ],
+ as => [qw/body_id c deleted confirmed/],
+ group_by => [ 'body_id' ],
result_class => 'DBIx::Class::ResultClass::HashRefInflator'
}
);
- my %council_info = map { $_->{area_id} => $_ } $contacts->all;
+ my %council_info = map { $_->{body_id} => $_ } $contacts->all;
- my @no_info = grep { !$council_info{$_} } @councils_ids;
- my @one_plus_deleted = grep { $council_info{$_} && $council_info{$_}->{deleted} } @councils_ids;
- my @unconfirmeds = grep { $council_info{$_} && !$council_info{$_}->{deleted} && $council_info{$_}->{confirmed} != $council_info{$_}->{c} } @councils_ids;
- my @all_confirmed = grep { $council_info{$_} && !$council_info{$_}->{deleted} && $council_info{$_}->{confirmed} == $council_info{$_}->{c} } @councils_ids;
-
- $c->stash->{areas} = $areas;
$c->stash->{counts} = \%council_info;
- $c->stash->{no_info} = \@no_info;
- $c->stash->{one_plus_deleted} = \@one_plus_deleted;
- $c->stash->{unconfirmeds} = \@unconfirmeds;
- $c->stash->{all_confirmed} = \@all_confirmed;
+
+ $c->forward( 'body_form_dropdowns' );
return 1;
}
-sub council_contacts : Path('council_contacts') : Args(1) {
- my ( $self, $c, $area_id ) = @_;
+sub body_form_dropdowns : Private {
+ my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
+ my $areas;
+ if ($c->cobrand->moniker eq 'zurich') {
+ $areas = mySociety::MaPit::call('areas', 274456);
+ } else {
+ $areas = mySociety::MaPit::call('areas', $c->cobrand->area_types);
+ }
+ $c->stash->{areas} = [ sort { strcoll($a->{name}, $b->{name}) } values %$areas ];
- my $posted = $c->req->param('posted') || '';
- $c->stash->{area_id} = $area_id;
+ my @methods = map { $_ =~ s/FixMyStreet::SendReport:://; $_ } keys %{ FixMyStreet::SendReport->get_senders };
+ $c->stash->{send_methods} = \@methods;
+}
+
+sub body : Path('body') : Args(1) {
+ my ( $self, $c, $body_id ) = @_;
+
+ $c->stash->{body_id} = $body_id;
$c->forward( 'get_token' );
+ $c->forward( 'lookup_body' );
+ $c->forward( 'fetch_all_bodies' );
+ $c->forward( 'body_form_dropdowns' );
- if ( $posted ) {
+ if ( $c->req->param('posted') ) {
$c->log->debug( 'posted' );
$c->forward('update_contacts');
}
@@ -285,7 +313,7 @@ sub update_contacts : Private {
my ( $self, $c ) = @_;
my $posted = $c->req->param('posted');
- my $editor = $c->req->remote_user || _('*unknown*');
+ my $editor = $c->forward('get_user');
if ( $posted eq 'new' ) {
$c->forward('check_token');
@@ -297,7 +325,7 @@ sub update_contacts : Private {
my $contact = $c->model('DB::Contact')->find_or_new(
{
- area_id => $c->stash->{area_id},
+ body_id => $c->stash->{body_id},
category => $category,
}
);
@@ -331,7 +359,7 @@ sub update_contacts : Private {
my $contacts = $c->model('DB::Contact')->search(
{
- area_id => $c->stash->{area_id},
+ body_id => $c->stash->{body_id},
category => { -in => \@categories },
}
);
@@ -346,69 +374,50 @@ sub update_contacts : Private {
);
$c->stash->{updated} = _('Values updated');
- } elsif ( $posted eq 'open311' ) {
+ } elsif ( $posted eq 'body' ) {
$c->forward('check_token');
- my %params = map { $_ => $c->req->param($_) || '' } qw/open311_id endpoint jurisdiction api_key area_id send_method send_comments suppress_alerts extended_statuses comment_user_id devolved/;
-
- if ( $params{open311_id} ) {
- my $conf = $c->model('DB::Open311Conf')->find( { id => $params{open311_id} } );
-
- $conf->endpoint( $params{endpoint} );
- $conf->jurisdiction( $params{jurisdiction} );
- $conf->api_key( $params{api_key} );
- $conf->send_method( $params{send_method} );
- $conf->send_comments( $params{send_comments} || 0);
- $conf->suppress_alerts( $params{suppress_alerts} || 0);
- $conf->comment_user_id( $params{comment_user_id} || undef );
- $conf->can_be_devolved( $params{devolved} || 0 );
- $conf->send_extended_statuses( $params{extended_statuses} || 0 );
-
- $conf->update();
-
- $c->stash->{updated} = _('Configuration updated');
- } else {
- my $conf = $c->model('DB::Open311Conf')->find_or_new( { area_id => $params{area_id} } );
-
- $conf->endpoint( $params{endpoint} );
- $conf->jurisdiction( $params{jurisdiction} );
- $conf->api_key( $params{api_key} );
- $conf->send_method( $params{send_method} );
- $conf->send_comments( $params{send_comments} || 0);
- $conf->suppress_alerts( $params{suppress_alerts} || 0);
- $conf->comment_user_id( $params{comment_user_id} || undef );
- $conf->can_be_devolved( $params{devolved} || 0 );
- $conf->send_extended_statuses( $params{extended_statuses} || 0 );
-
- $conf->insert();
-
- $c->stash->{updated} = _('Configuration updated - contacts will be generated automatically later');
+ my $params = $c->forward( 'body_params' );
+ $c->stash->{body}->update( $params );
+ my @current = $c->stash->{body}->body_areas->all;
+ my %current = map { $_->area_id => 1 } @current;
+ my $area_ids = $c->req->params->{area_ids};
+ if ($area_ids) {
+ $area_ids = [ $area_ids ] unless ref $area_ids;
+ foreach (@$area_ids) {
+ $c->model('DB::BodyArea')->find_or_create( { body => $c->stash->{body}, area_id => $_ } );
+ delete $current{$_};
+ }
}
+ # Remove any others
+ $c->stash->{body}->body_areas->search( { area_id => [ keys %current ] } )->delete;
+
+ $c->stash->{updated} = _('Configuration updated - contacts will be generated automatically later');
}
}
-sub display_contacts : Private {
+sub body_params : Private {
my ( $self, $c ) = @_;
- $c->forward('setup_council_details');
-
- my $area_id = $c->stash->{area_id};
-
- my $contacts = $c->model('DB::Contact')->search(
- { area_id => $area_id },
- { order_by => ['category'] }
+ my @fields = qw/name endpoint jurisdiction api_key send_method send_comments suppress_alerts send_extended_statuses comment_user_id can_be_devolved parent/;
+ my %defaults = map { $_ => '' } @fields;
+ %defaults = ( %defaults,
+ send_comments => 0,
+ suppress_alerts => 0,
+ comment_user_id => undef,
+ send_extended_statuses => 0,
+ can_be_devolved => 0,
+ parent => undef,
);
+ my %params = map { $_ => $c->req->param($_) || $defaults{$_} } @fields;
+ return \%params;
+}
- $c->stash->{contacts} = $contacts;
-
- my @methods = map { $_ =~ s/FixMyStreet::SendReport:://; $_ } keys %{ FixMyStreet::SendReport->get_senders };
- $c->stash->{send_methods} = \@methods;
-
- my $open311 = $c->model('DB::Open311Conf')->search(
- { area_id => $area_id }
- );
+sub display_contacts : Private {
+ my ( $self, $c ) = @_;
- $c->stash->{open311} = $open311;
+ my $contacts = $c->stash->{body}->contacts->search(undef, { order_by => [ 'category' ] } );
+ $c->stash->{contacts} = $contacts;
if ( $c->req->param('text') && $c->req->param('text') == 1 ) {
$c->stash->{template} = 'admin/council_contacts.txt';
@@ -419,59 +428,52 @@ sub display_contacts : Private {
return 1;
}
-sub setup_council_details : Private {
+sub lookup_body : Private {
my ( $self, $c ) = @_;
- my $area_id = $c->stash->{area_id};
-
- my $mapit_data = mySociety::MaPit::call('area', $area_id);
-
- $c->stash->{council_name} = $mapit_data->{name};
-
- my $example_postcode = mySociety::MaPit::call('area/example_postcode', $area_id);
-
- if ($example_postcode && ! ref $example_postcode) {
- $c->stash->{example_pc} = $example_postcode;
+ my $body_id = $c->stash->{body_id};
+ my $body = $c->model('DB::Body')->find($body_id);
+ $c->detach( '/page_error_404_not_found' )
+ unless $body;
+ $c->stash->{body} = $body;
+
+ if ($body->body_areas->first) {
+ my $example_postcode = mySociety::MaPit::call('area/example_postcode', $body->body_areas->first->area_id);
+ if ($example_postcode && ! ref $example_postcode) {
+ $c->stash->{example_pc} = $example_postcode;
+ }
}
return 1;
}
-sub council_edit_all : Path('council_edit') {
- my ( $self, $c, $area_id, @category ) = @_;
+# This is for if the category name contains a '/'
+sub body_edit_all : Path('body_edit') {
+ my ( $self, $c, $body_id, @category ) = @_;
my $category = join( '/', @category );
- $c->go( 'council_edit', [ $area_id, $category ] );
+ $c->go( 'body_edit', [ $body_id, $category ] );
}
-sub council_edit : Path('council_edit') : Args(2) {
- my ( $self, $c, $area_id, $category ) = @_;
+sub body_edit : Path('body_edit') : Args(2) {
+ my ( $self, $c, $body_id, $category ) = @_;
- $c->forward('check_page_allowed');
-
- $c->stash->{area_id} = $area_id;
+ $c->stash->{body_id} = $body_id;
$c->forward( 'get_token' );
- $c->forward('setup_council_details');
-
- my $contact = $c->model('DB::Contact')->search(
- {
- area_id => $area_id,
- category => $category
- }
- )->first;
+ $c->forward( 'lookup_body' );
+ my $contact = $c->stash->{body}->contacts->search( { category => $category } )->first;
$c->stash->{contact} = $contact;
my $history = $c->model('DB::ContactsHistory')->search(
{
- area_id => $area_id,
+ body_id => $body_id,
category => $category
},
{
order_by => ['contacts_history_id']
},
);
-
$c->stash->{history} = $history;
my @methods = map { $_ =~ s/FixMyStreet::SendReport:://; $_ } keys %{ FixMyStreet::SendReport->get_senders };
@@ -480,13 +482,11 @@ sub council_edit : Path('council_edit') : Args(2) {
return 1;
}
-sub search_reports : Path('search_reports') {
+sub reports : Path('reports') {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
-
if (my $search = $c->req->param('search')) {
- $c->stash->{searched} = 1;
+ $c->stash->{searched} = $search;
my $site_restriction = $c->cobrand->site_restriction;
@@ -523,7 +523,7 @@ sub search_reports : Path('search_reports') {
'me.name' => { ilike => $like_search },
'me.title' => { ilike => $like_search },
detail => { ilike => $like_search },
- council => { like => $like_search },
+ bodies_str => { like => $like_search },
cobrand_data => { like => $like_search },
];
}
@@ -542,8 +542,8 @@ sub search_reports : Path('search_reports') {
# will have been turned off
$c->stash->{problems} = [ $problems->all ];
- $c->stash->{edit_council_contacts} = 1
- if ( grep {$_ eq 'councilcontacts'} keys %{$c->stash->{allowed_pages}});
+ $c->stash->{edit_body_contacts} = 1
+ if ( grep {$_ eq 'body'} keys %{$c->stash->{allowed_pages}});
if (is_valid_email($search)) {
$query = [
@@ -574,7 +574,7 @@ sub search_reports : Path('search_reports') {
-or => $query,
},
{
- -select => [ 'me.*', qw/problem.council problem.state/ ],
+ -select => [ 'me.*', qw/problem.bodies_str problem.state/ ],
prefetch => [qw/user problem/],
order_by => [\"(me.state='hidden')",\"(problem.state='hidden')",'me.created']
}
@@ -592,11 +592,7 @@ sub report_edit : Path('report_edit') : Args(1) {
my $site_restriction = $c->cobrand->site_restriction;
- my $problem = $c->cobrand->problems->search(
- {
- id => $id,
- }
- )->first;
+ my $problem = $c->cobrand->problems->search( { id => $id } )->first;
$c->detach( '/page_error_404_not_found' )
unless $problem;
@@ -604,7 +600,32 @@ sub report_edit : Path('report_edit') : Args(1) {
$c->stash->{problem} = $problem;
$c->forward('get_token');
- $c->forward('check_page_allowed');
+
+ if ( $c->req->param('rotate_photo') ) {
+ $c->forward('rotate_photo');
+ return 1;
+ }
+
+ if ( $c->cobrand->moniker eq 'zurich' ) {
+
+ FixMyStreet::Map::display_map(
+ $c,
+ latitude => $problem->latitude,
+ longitude => $problem->longitude,
+ pins => $problem->used_map
+ ? [ {
+ latitude => $problem->latitude,
+ longitude => $problem->longitude,
+ colour => 'yellow',
+ type => 'big',
+ } ]
+ : [],
+ );
+
+ my $done = $c->cobrand->admin_report_edit();
+ return if $done;
+ }
+
$c->forward('check_email_for_abuse', [ $problem->user->email ] );
$c->stash->{updates} =
@@ -633,9 +654,6 @@ sub report_edit : Path('report_edit') : Args(1) {
elsif ( $c->req->param('banuser') ) {
$c->forward('ban_user');
}
- elsif ( $c->req->param('rotate_photo') ) {
- $c->forward('rotate_photo');
- }
elsif ( $c->req->param('submit') ) {
$c->forward('check_token');
@@ -664,6 +682,7 @@ sub report_edit : Path('report_edit') : Args(1) {
|| $c->req->param('email') ne $problem->user->email
|| $c->req->param('title') ne $problem->title
|| $c->req->param('detail') ne $problem->detail
+ || ($c->req->param('body') && $c->req->param('body') ne $problem->bodies_str)
|| $flagged != $problem->flagged
|| $non_public != $problem->non_public )
{
@@ -673,8 +692,10 @@ sub report_edit : Path('report_edit') : Args(1) {
$problem->anonymous( $c->req->param('anonymous') );
$problem->title( $c->req->param('title') );
$problem->detail( $c->req->param('detail') );
- $problem->state( $c->req->param('state') );
+ $problem->state( $new_state );
$problem->name( $c->req->param('name') );
+ $problem->bodies_str( $c->req->param('body') ) if $c->req->param('body');
+
$problem->flagged( $flagged );
$problem->non_public( $non_public );
@@ -721,26 +742,22 @@ sub report_edit : Path('report_edit') : Args(1) {
return 1;
}
-sub search_users: Path('search_users') : Args(0) {
+sub users: Path('users') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
-
if (my $search = $c->req->param('search')) {
- $c->stash->{searched} = 1;
+ $c->stash->{searched} = $search;
- my $search = $c->req->param('search');
my $isearch = '%' . $search . '%';
-
my $search_n = 0;
$search_n = int($search) if $search =~ /^\d+$/;
my $users = $c->model('DB::User')->search(
{
-or => [
- email => { ilike => $isearch },
- name => { ilike => $isearch },
- from_council => $search_n,
+ email => { ilike => $isearch },
+ name => { ilike => $isearch },
+ from_body => $search_n,
]
}
);
@@ -762,6 +779,9 @@ sub search_users: Path('search_users') : Args(0) {
}
}
+ } else {
+ $c->forward('get_token');
+ $c->forward('fetch_all_bodies');
}
return 1;
@@ -782,7 +802,6 @@ sub update_edit : Path('update_edit') : Args(1) {
unless $update;
$c->forward('get_token');
- $c->forward('check_page_allowed');
$c->stash->{update} = $update;
@@ -837,6 +856,11 @@ sub update_edit : Path('update_edit') : Args(1) {
if ( $new_state eq 'confirmed' and $old_state eq 'unconfirmed' ) {
$update->confirmed( \'ms_current_timestamp()' );
+ if ( $update->problem_state && $update->created > $update->problem->lastupdate ) {
+ $update->problem->state( $update->problem_state );
+ $update->problem->lastupdate( \'ms_current_timestamp()' );
+ $update->problem->update;
+ }
}
$update->update;
@@ -868,16 +892,44 @@ sub update_edit : Path('update_edit') : Args(1) {
return 1;
}
+sub user_add : Path('user_edit') : Args(0) {
+ my ( $self, $c ) = @_;
+
+ $c->stash->{template} = 'admin/user_edit.html';
+ $c->forward('get_token');
+ $c->forward('fetch_all_bodies');
+
+ return 1 unless $c->req->param('submit');
+
+ $c->forward('check_token');
+
+ my $user = $c->model('DB::User')->find_or_create( {
+ name => $c->req->param('name'),
+ email => $c->req->param('email'),
+ from_body => $c->req->param('body') || undef,
+ flagged => $c->req->param('flagged') || 0,
+ }, {
+ key => 'users_email_key'
+ } );
+ $c->stash->{user} = $user;
+
+ $c->forward( 'log_edit', [ $user->id, 'user', 'edit' ] );
+
+ $c->stash->{status_message} =
+ '<p><em>' . _('Updated!') . '</em></p>';
+
+ return 1;
+}
+
sub user_edit : Path('user_edit') : Args(1) {
my ( $self, $c, $id ) = @_;
- $c->forward('check_page_allowed');
$c->forward('get_token');
my $user = $c->model('DB::User')->find( { id => $id } );
$c->stash->{user} = $user;
- $c->forward('set_up_council_details');
+ $c->forward('fetch_all_bodies');
if ( $c->req->param('submit') ) {
$c->forward('check_token');
@@ -886,13 +938,15 @@ sub user_edit : Path('user_edit') : Args(1) {
if ( $user->email ne $c->req->param('email') ||
$user->name ne $c->req->param('name' ) ||
- $user->from_council != $c->req->param('council') ) {
+ ($user->from_body && $user->from_body->id ne $c->req->param('body')) ||
+ (!$user->from_body && $c->req->param('body'))
+ ) {
$edited = 1;
}
$user->name( $c->req->param('name') );
$user->email( $c->req->param('email') );
- $user->from_council( $c->req->param('council') || undef );
+ $user->from_body( $c->req->param('body') || undef );
$user->flagged( $c->req->param('flagged') || 0 );
$user->update;
@@ -907,11 +961,9 @@ sub user_edit : Path('user_edit') : Args(1) {
return 1;
}
-sub list_flagged : Path('list_flagged') : Args(0) {
+sub flagged : Path('flagged') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
-
my $problems = $c->model('DB::Problem')->search( { flagged => 1 } );
# pass in as array ref as using same template as search_reports
@@ -928,9 +980,7 @@ sub list_flagged : Path('list_flagged') : Args(0) {
sub stats : Path('stats') : Args(0) {
my ( $self, $c ) = @_;
- $c->forward('check_page_allowed');
-
- $c->forward('set_up_council_details');
+ $c->forward('fetch_all_bodies');
if ( $c->cobrand->moniker eq 'seesomething' ) {
return $c->cobrand->admin_stats();
@@ -970,11 +1020,11 @@ sub stats : Path('stats') : Args(0) {
my $bymonth = $c->req->param('bymonth');
$c->stash->{bymonth} = $bymonth;
- my ( %council, %dates );
- $council{council} = { like => $c->req->param('council') }
- if $c->req->param('council');
+ my ( %body, %dates );
+ $body{bodies_str} = { like => $c->req->param('body') }
+ if $c->req->param('body');
- $c->stash->{selected_council} = $c->req->param('council');
+ $c->stash->{selected_body} = $c->req->param('body');
my $field = 'confirmed';
@@ -1009,7 +1059,7 @@ sub stats : Path('stats') : Args(0) {
$field => { '>=', $start_date},
$field => { '<=', $end_date + $one_day },
],
- %council,
+ %body,
%dates,
},
\%select,
@@ -1038,16 +1088,16 @@ sub set_allowed_pages : Private {
if( !$pages ) {
$pages = {
'summary' => [_('Summary'), 0],
- 'council_list' => [_('Bodies'), 1],
- 'search_reports' => [_('Reports'), 2],
+ 'bodies' => [_('Bodies'), 1],
+ 'reports' => [_('Reports'), 2],
'timeline' => [_('Timeline'), 3],
'questionnaire' => [_('Survey'), 4],
- 'search_users' => [_('Users'), 5],
- 'list_flagged' => [_('Flagged'), 6],
+ 'users' => [_('Users'), 5],
+ 'flagged' => [_('Flagged'), 6],
'stats' => [_('Stats'), 6],
'user_edit' => [undef, undef],
- 'council_contacts' => [undef, undef],
- 'council_edit' => [undef, undef],
+ 'body' => [undef, undef],
+ 'body_edit' => [undef, undef],
'report_edit' => [undef, undef],
'update_edit' => [undef, undef],
'abuse_edit' => [undef, undef],
@@ -1062,6 +1112,16 @@ sub set_allowed_pages : Private {
return 1;
}
+sub get_user : Private {
+ my ( $self, $c ) = @_;
+
+ my $user = $c->req->remote_user();
+ $user ||= ($c->user && $c->user->name);
+ $user ||= '';
+
+ return $user;
+}
+
=item get_token
Generate a token based on user and secret
@@ -1072,12 +1132,8 @@ sub get_token : Private {
my ( $self, $c ) = @_;
my $secret = $c->model('DB::Secret')->search()->first;
-
- my $user = $c->req->remote_user();
- $user ||= '';
-
- my $token = md5_hex(($user . $secret->secret));
-
+ my $user = $c->forward('get_user');
+ my $token = sha1_hex($user . $secret->secret);
$c->stash->{token} = $token;
return 1;
@@ -1104,7 +1160,7 @@ sub check_token : Private {
$c->forward( 'log_edit', [ $object_id, $object_type, $action_performed ] );
-Adds an entry into the admin_log table using the current remote_user.
+Adds an entry into the admin_log table using the current user.
=cut
@@ -1112,7 +1168,7 @@ sub log_edit : Private {
my ( $self, $c, $id, $object_type, $action ) = @_;
$c->model('DB::AdminLog')->create(
{
- admin_user => ( $c->req->remote_user() || '' ),
+ admin_user => $c->forward('get_user'),
object_type => $object_type,
action => $action,
object_id => $id,
@@ -1232,21 +1288,42 @@ sub rotate_photo : Private {
my ( $self, $c ) =@_;
my $direction = $c->req->param('rotate_photo');
-
return unless $direction =~ /Left/ or $direction =~ /Right/;
- my $photo = _rotate_image( $c->stash->{problem}->photo, $direction =~ /Left/ ? -90 : 90 );
+ my $photo = $c->stash->{problem}->photo;
+ my $file;
+
+ # If photo field contains a hash
+ if ( length($photo) == 40 ) {
+ $file = file( $c->config->{UPLOAD_DIR}, "$photo.jpeg" );
+ $photo = $file->slurp;
+ }
- if ( $photo ) {
- $c->stash->{rotated} = 1;
- $c->stash->{problem}->photo( $photo );
+ $photo = _rotate_image( $photo, $direction =~ /Left/ ? -90 : 90 );
+ return unless $photo;
+
+ my $fileid;
+ if ( !$file ) {
+ $fileid = sha1_hex($photo);
+ $file = file( $c->config->{UPLOAD_DIR}, "$fileid.jpeg" );
+ }
+
+ $c->stash->{rotated} = 1;
+
+ my $fh = $file->open('w');
+ print $fh $photo;
+ close $fh;
+
+ unlink glob FixMyStreet->path_to( 'web', 'photo', $c->stash->{problem}->id . '.*' );
+
+ if ( $fileid ) {
+ $c->stash->{problem}->photo( $fileid );
$c->stash->{problem}->update();
}
return 1;
}
-
=head2 check_page_allowed
Checks if the current catalyst action is in the list of allowed pages and
@@ -1270,16 +1347,16 @@ sub check_page_allowed : Private {
return 1;
}
-sub set_up_council_details : Private {
+sub fetch_all_bodies : Private {
my ($self, $c ) = @_;
- my $areas = mySociety::MaPit::call('areas', $c->cobrand->area_types);
-
- my @councils_ids = sort { strcoll($areas->{$a}->{name}, $areas->{$b}->{name}) } keys %$areas;
- @councils_ids = $c->cobrand->filter_all_council_ids_list( @councils_ids );
-
- $c->stash->{council_ids} = \@councils_ids;
- $c->stash->{council_details} = $areas;
+ my @bodies = $c->model('DB::Body')->all;
+ if ( $c->cobrand->moniker eq 'zurich' ) {
+ @bodies = $c->cobrand->admin_fetch_all_bodies( @bodies );
+ } else {
+ @bodies = sort { strcoll($a->name, $b->name) } @bodies;
+ }
+ $c->stash->{bodies} = \@bodies;
return 1;
}
diff --git a/perllib/FixMyStreet/App/Controller/Alert.pm b/perllib/FixMyStreet/App/Controller/Alert.pm
index 91ea61fbc..e821b7467 100644
--- a/perllib/FixMyStreet/App/Controller/Alert.pm
+++ b/perllib/FixMyStreet/App/Controller/Alert.pm
@@ -407,13 +407,13 @@ Generate the details required to display the council/ward/area RSS feeds
sub setup_council_rss_feeds : Private {
my ( $self, $c ) = @_;
- $c->stash->{council_check_action} = 'alert';
- unless ( $c->forward('/council/load_and_check_councils_and_wards') ) {
+ $c->stash->{area_check_action} = 'alert';
+ unless ( $c->forward('/council/load_and_check_areas_and_wards') ) {
$c->go('index');
}
( $c->stash->{options}, $c->stash->{reported_to_options} ) =
- $c->cobrand->council_rss_alert_options( $c->stash->{all_councils}, $c );
+ $c->cobrand->council_rss_alert_options( $c->stash->{all_areas}, $c );
return 1;
}
diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm
index f2bb23350..9a754f063 100644
--- a/perllib/FixMyStreet/App/Controller/Around.pm
+++ b/perllib/FixMyStreet/App/Controller/Around.pm
@@ -44,7 +44,7 @@ sub around_index : Path : Args(0) {
unless $c->forward('/location/determine_location_from_coords')
|| $c->forward('/location/determine_location_from_pc');
- # Check to see if the spot is covered by a council - if not show an error.
+ # Check to see if the spot is covered by a area - if not show an error.
return unless $c->cobrand->moniker eq 'fixmybarangay' || $c->forward('check_location_is_acceptable');
# If we have a partial - redirect to /report/new so that it can be
@@ -192,7 +192,7 @@ sub display_location : Private {
longitude => $p->longitude,
colour => $colour,
id => $p->id,
- title => $p->title,
+ title => $p->title_safe,
}
} @$on_map_all, @$around_map;
}
@@ -212,7 +212,7 @@ sub display_location : Private {
=head2 check_location_is_acceptable
-Find the lat and lon in stash and check that they are acceptable to the council,
+Find the lat and lon in stash and check that they are acceptable to the area,
and that they are in UK (if we are in UK).
=cut
@@ -220,10 +220,10 @@ and that they are in UK (if we are in UK).
sub check_location_is_acceptable : Private {
my ( $self, $c ) = @_;
- # check that there are councils that can accept this location
- $c->stash->{council_check_action} = 'submit_problem';
- $c->stash->{remove_redundant_councils} = 1;
- return $c->forward('/council/load_and_check_councils');
+ # check that there are areas that can accept this location
+ $c->stash->{area_check_action} = 'submit_problem';
+ $c->stash->{remove_redundant_areas} = 1;
+ return $c->forward('/council/load_and_check_areas');
}
=head2 /ajax
@@ -281,6 +281,65 @@ sub ajax : Path('/ajax') {
$c->res->body($body);
}
+
+sub location_autocomplete : Path('/ajax/geocode') {
+ my ( $self, $c ) = @_;
+ $c->res->content_type('application/json; charset=utf-8');
+ unless ( $c->req->param('term') ) {
+ $c->res->status(404);
+ $c->res->body('');
+ return;
+ }
+ # we want the match even if there's no ambiguity, so recommendation doesn't
+ # disappear when it's the last choice being offered in the autocomplete.
+ $c->stash->{allow_single_geocode_match_strings} = 1;
+ return $self->_geocode( $c, $c->req->param('term') );
+}
+
+sub location_lookup : Path('/ajax/lookup_location') {
+ my ( $self, $c ) = @_;
+ $c->res->content_type('application/json; charset=utf-8');
+ unless ( $c->req->param('term') ) {
+ $c->res->status(404);
+ $c->res->body('');
+ return;
+ }
+
+ return $self->_geocode( $c, $c->req->param('term') );
+}
+
+sub _geocode : Private {
+ my ( $self, $c, $term ) = @_;
+
+ my ( $lat, $long, $suggestions ) =
+ FixMyStreet::Geocode::lookup( $c->req->param('term'), $c );
+
+ my ($response, @addresses);
+
+ if ( $lat && $long ) {
+ $response = { latitude => $lat, longitude => $long };
+ } else {
+ if ( ref($suggestions) eq 'ARRAY' ) {
+ foreach (@$suggestions) {
+ push @addresses, decode_utf8($_->{address});
+ }
+ $response = { suggestions => \@addresses };
+ } else {
+ $response = { error => $suggestions };
+ }
+ }
+
+ if ( $c->stash->{allow_single_geocode_match_strings} ) {
+ $response = \@addresses;
+ }
+
+ my $body = JSON->new->utf8(1)->encode(
+ $response
+ );
+ $c->res->body($body);
+
+}
+
__PACKAGE__->meta->make_immutable;
1;
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm
index 3dc25dedf..f4d6d86e4 100644
--- a/perllib/FixMyStreet/App/Controller/Auth.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth.pm
@@ -31,7 +31,7 @@ sub general : Path : Args(0) {
my $req = $c->req;
$c->detach( 'redirect_on_signin', [ $req->param('r') ] )
- if $c->user && $req->param('r');
+ if $c->user && $req->param('r') && $req->param('r') !~ /admin/;
# all done unless we have a form posted to us
return unless $req->method eq 'POST';
diff --git a/perllib/FixMyStreet/App/Controller/Council.pm b/perllib/FixMyStreet/App/Controller/Council.pm
index cb9e78421..5d95c2538 100644
--- a/perllib/FixMyStreet/App/Controller/Council.pm
+++ b/perllib/FixMyStreet/App/Controller/Council.pm
@@ -14,34 +14,34 @@ Catalyst Controller.
=head1 METHODS
-=head2 load_and_check_councils_and_wards
+=head2 load_and_check_areas_and_wards
-Try to load councils and wards for this location and check that we have at least one. If
-there are no councils then return false.
+Try to load areas and wards for this location and check that we have at least one. If
+there are no areas then return false.
=cut
-sub load_and_check_councils_and_wards : Private {
+sub load_and_check_areas_and_wards : Private {
my ( $self, $c ) = @_;
my $area_types = [ @{$c->cobrand->area_types}, @{$c->cobrand->area_types_children} ];
$c->stash->{area_types} = $area_types;
- $c->forward('load_and_check_councils');
+ $c->forward('load_and_check_areas');
}
-=head2 load_and_check_councils
+=head2 load_and_check_areas
-Try to load councils for this location and check that we have at least one. If
-there are no councils then return false.
+Try to load areas for this location and check that we have at least one. If
+there are no areas then return false.
=cut
-sub load_and_check_councils : Private {
+sub load_and_check_areas : Private {
my ( $self, $c ) = @_;
my $latitude = $c->stash->{latitude};
my $longitude = $c->stash->{longitude};
- # Look up councils and do checks for the point we've got
+ # Look up areas and do checks for the point we've got
my $area_types;
if ( $c->stash->{area_types} and scalar @{ $c->stash->{area_types} } ) {
$area_types = $c->stash->{area_types};
@@ -52,49 +52,49 @@ sub load_and_check_councils : Private {
my $short_latitude = Utils::truncate_coordinate($latitude);
my $short_longitude = Utils::truncate_coordinate($longitude);
- my $all_councils;
+ my $all_areas;
if ( $c->stash->{fetch_all_areas} ) {
my %area_types = map { $_ => 1 } @$area_types;
- my $all_areas =
+ $all_areas =
mySociety::MaPit::call( 'point', "4326/$short_longitude,$short_latitude" );
- $c->stash->{all_areas} = $all_areas;
- $all_councils = {
+ $c->stash->{all_areas_mapit} = $all_areas;
+ $all_areas = {
map { $_ => $all_areas->{$_} }
grep { $area_types{ $all_areas->{$_}->{type} } }
keys %$all_areas
};
} else {
- $all_councils =
+ $all_areas =
mySociety::MaPit::call( 'point', "4326/$short_longitude,$short_latitude",
type => $area_types );
}
- if ($all_councils->{error}) {
- $c->stash->{location_error} = $all_councils->{error};
+ if ($all_areas->{error}) {
+ $c->stash->{location_error} = $all_areas->{error};
return;
}
# Let cobrand do a check
my ( $success, $error_msg ) =
- $c->cobrand->council_check( { all_councils => $all_councils },
- $c->stash->{council_check_action} );
+ $c->cobrand->area_check( { all_areas => $all_areas },
+ $c->stash->{area_check_action} );
if ( !$success ) {
$c->stash->{location_error} = $error_msg;
return;
}
# edit hash in-place
- $c->cobrand->remove_redundant_councils($all_councils) if $c->stash->{remove_redundant_councils};
+ $c->cobrand->remove_redundant_areas($all_areas) if $c->stash->{remove_redundant_areas};
- # If we don't have any councils we can't accept the report
- if ( !scalar keys %$all_councils ) {
+ # If we don't have any areas we can't accept the report
+ if ( !scalar keys %$all_areas ) {
$c->stash->{location_error} = _('That location does not appear to be covered by a council; perhaps it is offshore or outside the country. Please try again.');
return;
}
- # all good if we have some councils left
- $c->stash->{all_councils} = $all_councils;
- $c->stash->{all_council_names} =
- [ map { $_->{name} } values %$all_councils ];
+ # all good if we have some areas left
+ $c->stash->{all_areas} = $all_areas;
+ $c->stash->{all_area_names} =
+ [ map { $_->{name} } values %$all_areas ];
return 1;
}
diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm
index 17fd8b867..028b9aadd 100644
--- a/perllib/FixMyStreet/App/Controller/Dashboard.pm
+++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm
@@ -29,7 +29,7 @@ sub example : Local : Args(0) {
}
# TODO Set up manual version of what the below would do
- #$c->forward( '/report/new/setup_categories_and_councils' );
+ #$c->forward( '/report/new/setup_categories_and_bodies' );
# See if we've had anything from the dropdowns - perhaps vary results if so
$c->stash->{ward} = $c->req->param('ward');
@@ -74,9 +74,9 @@ sub check_page_allowed : Private {
$c->detach( '/auth/redirect' ) unless $c->user_exists;
$c->detach( '/page_error_404_not_found' )
- unless $c->user_exists && $c->user->from_council;
+ unless $c->user_exists && $c->user->from_body;
- return $c->user->from_council;
+ return $c->user->from_body;
}
=head2 index
@@ -88,20 +88,23 @@ Show the dashboard table.
sub index : Path : Args(0) {
my ( $self, $c ) = @_;
- my $council = $c->forward('check_page_allowed');
+ my $body = $c->forward('check_page_allowed');
# Set up the data for the dropdowns
- my $council_detail = mySociety::MaPit::call('area', $council );
+ # Just take the first area ID we find
+ my $area_id = $body->body_areas->first->area_id;
+
+ my $council_detail = mySociety::MaPit::call('area', $area_id );
$c->stash->{council} = $council_detail;
- my $children = mySociety::MaPit::call('area/children', $council,
+ my $children = mySociety::MaPit::call('area/children', $area_id,
type => $c->cobrand->area_types_children,
);
$c->stash->{children} = $children;
- $c->stash->{all_councils} = { $council => $council_detail };
- $c->forward( '/report/new/setup_categories_and_councils' );
+ $c->stash->{all_areas} = { $area_id => $council_detail };
+ $c->forward( '/report/new/setup_categories_and_bodies' );
# See if we've had anything from the dropdowns
@@ -109,7 +112,7 @@ sub index : Path : Args(0) {
$c->stash->{category} = $c->req->param('category');
my %where = (
- council => $council, # XXX This will break in a two tier council. Restriction needs looking at...
+ bodies_str => $body->id, # XXX Does this break in a two tier council? Restriction needs looking at...
'problem.state' => [ FixMyStreet::DB::Result::Problem->visible_states() ],
);
$where{areas} = { 'like', '%,' . $c->stash->{ward} . ',%' }
diff --git a/perllib/FixMyStreet/App/Controller/JS.pm b/perllib/FixMyStreet/App/Controller/JS.pm
index d7847af75..483c3c2cc 100755
--- a/perllib/FixMyStreet/App/Controller/JS.pm
+++ b/perllib/FixMyStreet/App/Controller/JS.pm
@@ -11,13 +11,13 @@ FixMyStreet::App::Controller::JS - Catalyst Controller
=head1 DESCRIPTION
JS Catalyst Controller. To return a language-dependent list
-of validation strings.
+of translation strings.
=head1 METHODS
=cut
-sub validation_strings : LocalRegex('^validation_strings\.(.*?)\.js$') : Args(0) {
+sub translation_strings : LocalRegex('^translation_strings\.(.*?)\.js$') : Args(0) {
my ( $self, $c ) = @_;
my $lang = $c->req->captures->[0];
$c->cobrand->set_lang_and_domain( $lang, 1 );
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
index f3607341a..1a7c1915b 100644
--- a/perllib/FixMyStreet/App/Controller/JSON.pm
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -92,7 +92,7 @@ sub problems : Local {
my @problems = $c->cobrand->problems->search( $query, {
order_by => { -asc => 'confirmed' },
columns => [
- 'id', 'title', 'council', 'category',
+ 'id', 'title', 'bodies_str', 'category',
'detail', 'name', 'anonymous', 'confirmed',
'whensent', 'service',
'latitude', 'longitude', 'used_map',
@@ -100,23 +100,13 @@ sub problems : Local {
]
} );
- my @councils;
foreach my $problem (@problems) {
$problem->name( '' ) if $problem->anonymous == 1;
$problem->service( 'Web interface' ) if $problem->service eq '';
- if ($problem->council) {
- (my $council = $problem->council) =~ s/\|.*//g;
- my @council_ids = split /,/, $council;
- push(@councils, @council_ids);
- $problem->council( \@council_ids );
- }
- }
- @councils = uniq @councils;
- my $areas_info = mySociety::MaPit::call('areas', \@councils);
- foreach my $problem (@problems) {
- if ($problem->council) {
- my @council_names = map { $areas_info->{$_}->{name} } @{$problem->council} ;
- $problem->council( join(' and ', @council_names) );
+ my $bodies = $problem->bodies;
+ if (keys %$bodies) {
+ my @body_names = map { $_->name } values %$bodies;
+ $problem->bodies_str( join(' and ', @body_names) );
}
}
diff --git a/perllib/FixMyStreet/App/Controller/Open311.pm b/perllib/FixMyStreet/App/Controller/Open311.pm
index 3382c0cea..7b8cb649f 100644
--- a/perllib/FixMyStreet/App/Controller/Open311.pm
+++ b/perllib/FixMyStreet/App/Controller/Open311.pm
@@ -164,12 +164,12 @@ sub get_services : Private {
if ($lat || $lon) {
my $area_types = $c->cobrand->area_types;
- my $all_councils = mySociety::MaPit::call('point',
+ my $all_areas = mySociety::MaPit::call('point',
"4326/$lon,$lat",
type => $area_types);
$categories = $categories->search( {
- area_id => [ keys %$all_councils ],
- } );
+ 'body_areas.area_id' => [ keys %$all_areas ],
+ }, { join => { 'body' => 'body_areas' } } );
}
my @categories = $categories->search( undef, {
@@ -223,19 +223,11 @@ sub output_requests : Private {
);
my @problemlist;
- my @councils;
while ( my $problem = $problems->next ) {
my $id = $problem->id;
$problem->service( 'Web interface' ) unless $problem->service;
- if ($problem->council) {
- (my $council = $problem->council) =~ s/\|.*//g;
- my @council_ids = split(/,/, $council);
- push(@councils, @council_ids);
- $problem->council( \@council_ids );
- }
-
$problem->state( $statusmap{$problem->state} );
my $request =
@@ -256,7 +248,7 @@ sub output_requests : Private {
'service_code' => [ $problem->category ],
'service_name' => [ $problem->category ],
# 'service_notice' => [ {} ],
- 'agency_responsible' => $problem->council , # FIXME Not according to Open311 v2
+ 'agency_responsible' => $problem->bodies , # FIXME Not according to Open311 v2
# 'zipcode' => [ {} ],
'interface_used' => [ $problem->service ], # Not in Open311 v2
};
@@ -288,12 +280,12 @@ sub output_requests : Private {
}
push(@problemlist, $request);
}
- my $areas_info = mySociety::MaPit::call('areas', \@councils);
+
foreach my $request (@problemlist) {
if ($request->{agency_responsible}) {
- my @council_names = map { $areas_info->{$_}->{name} } @{$request->{agency_responsible}} ;
+ my @body_names = map { $_->name } values %{$request->{agency_responsible}} ;
$request->{agency_responsible} =
- [ {'recipient' => [ @council_names ] } ];
+ [ {'recipient' => [ @body_names ] } ];
}
}
$c->forward( 'format_output', [ {
@@ -319,7 +311,7 @@ sub get_requests : Private {
service_request_id => [ '=', 'id' ],
service_code => [ '=', 'category' ],
status => [ 'IN', 'state' ],
- agency_responsible => [ '~', 'council' ],
+ agency_responsible => [ '~', 'bodies_str' ],
interface_used => [ '=', 'service' ],
has_photo => [ '=', 'photo' ],
);
diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm
index fa4baf045..279623922 100644
--- a/perllib/FixMyStreet/App/Controller/Photo.pm
+++ b/perllib/FixMyStreet/App/Controller/Photo.pm
@@ -102,10 +102,7 @@ sub output : Private {
File::Path::make_path( FixMyStreet->path_to( 'web', 'photo', 'c' )->stringify );
File::Slurp::write_file( FixMyStreet->path_to( 'web', $c->req->path )->stringify, \$photo );
- my $dt = DateTime->now()->add( years => 1 );
-
$c->res->content_type( 'image/jpeg' );
- $c->res->header( 'expires', DateTime::Format::HTTP->format_datetime( $dt ) );
$c->res->body( $photo );
}
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index ef966a8a8..460ccaec5 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -51,6 +51,25 @@ sub display : Path('') : Args(1) {
return $c->res->redirect( $c->uri_for($1), 301 );
}
+ $c->forward( '_display', [ $id ] );
+}
+
+=head2 ajax
+
+Return JSON formatted details of a report
+
+=cut
+
+sub ajax : Path('ajax') : Args(1) {
+ my ( $self, $c, $id ) = @_;
+
+ $c->stash->{ajax} = 1;
+ $c->forward( '_display', [ $id ] );
+}
+
+sub _display : Private {
+ my ( $self, $c, $id ) = @_;
+
$c->forward( 'load_problem_or_display_error', [ $id ] );
$c->forward( 'load_updates' );
$c->forward( 'format_problem_for_display' );
@@ -66,7 +85,7 @@ sub support : Path('support') : Args(0) {
? $c->uri_for( '/report', $id )
: $c->uri_for('/');
- if ( $id && $c->cobrand->can_support_problems && $c->user && $c->user->from_council ) {
+ if ( $id && $c->cobrand->can_support_problems && $c->user && $c->user->from_body ) {
$c->forward( 'load_problem_or_display_error', [ $id ] );
$c->stash->{problem}->update( { interest_count => \'interest_count +1' } );
}
@@ -83,7 +102,7 @@ sub load_problem_or_display_error : Private {
: $c->cobrand->problems->find( { id => $id } );
# check that the problem is suitable to show.
- if ( !$problem || $problem->state eq 'unconfirmed' || $problem->state eq 'partial' ) {
+ if ( !$problem || ($problem->state eq 'unconfirmed' && !$c->cobrand->show_unconfirmed_reports) || $problem->state eq 'partial' ) {
$c->detach( '/page_error_404_not_found', [ _('Unknown problem ID') ] );
}
elsif ( $problem->state eq 'hidden' ) {
@@ -147,10 +166,19 @@ sub format_problem_for_display : Private {
$c->stash->{add_alert} = 1;
}
- $c->stash->{extra_name_info} = $problem->council && $problem->council eq '2482' ? 1 : 0;
+ $c->stash->{extra_name_info} = $problem->bodies_str && $problem->bodies_str eq '2482' ? 1 : 0;
$c->forward('generate_map_tags');
+ if ( $c->stash->{ajax} ) {
+ $c->res->content_type('application/json; charset=utf-8');
+ my $content = JSON->new->utf8(1)->encode(
+ $problem->as_hashref( $c )
+ );
+ $c->res->body( $content );
+ return 1;
+ }
+
return 1;
}
@@ -187,11 +215,10 @@ sub delete :Local :Args(1) {
return $c->res->redirect($uri) unless $c->user_exists;
- my $council = $c->user->obj->from_council;
- return $c->res->redirect($uri) unless $council;
+ my $body = $c->user->obj->from_body;
+ return $c->res->redirect($uri) unless $body;
- my %councils = map { $_ => 1 } @{$p->councils};
- return $c->res->redirect($uri) unless $councils{$council};
+ return $c->res->redirect($uri) unless $p->bodies->{$body};
$p->state('hidden');
$p->lastupdate( \'ms_current_timestamp()' );
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index 9194f5318..687e54fbe 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -89,7 +89,7 @@ sub report_new : Path : Args(0) {
# create a problem from the submitted details
$c->stash->{template} = "report/new/fill_in_details.html";
- $c->forward('setup_categories_and_councils');
+ $c->forward('setup_categories_and_bodies');
$c->forward('generate_map');
$c->forward('check_for_category');
@@ -119,7 +119,7 @@ sub report_new_ajax : Path('mobile') : Args(0) {
return 1;
}
- $c->forward('setup_categories_and_councils');
+ $c->forward('setup_categories_and_bodies');
$c->forward('process_user');
$c->forward('process_report');
$c->forward('/photo/process_photo');
@@ -147,7 +147,7 @@ sub report_new_ajax : Path('mobile') : Args(0) {
} else {
$c->stash->{token_url} = $c->uri_for_email( '/P', $token->token );
$c->send_email( 'problem-confirm.txt', {
- to => [ [ $report->user->email, $report->name ] ],
+ to => [ $report->name ? [ $report->user->email, $report->name ] : $report->user->email ],
} );
$c->stash->{ json_response } = { success => 1 };
}
@@ -180,7 +180,7 @@ sub report_form_ajax : Path('ajax') : Args(0) {
return;
}
- $c->forward('setup_categories_and_councils');
+ $c->forward('setup_categories_and_bodies');
# render templates to get the html
my $category = $c->render_fragment( 'report/new/category.html');
@@ -216,7 +216,7 @@ sub category_extras_ajax : Path('category_extras') : Args(0) {
$c->res->body($body);
return 1;
}
- $c->forward('setup_categories_and_councils');
+ $c->forward('setup_categories_and_bodies');
my $category_extra = '';
if ( $c->stash->{category_extras}->{ $c->req->param('category') } && @{ $c->stash->{category_extras}->{ $c->req->param('category') } } >= 1 ) {
@@ -569,27 +569,34 @@ sub determine_location_from_report : Private {
return;
}
-=head2 setup_categories_and_councils
+=head2 setup_categories_and_bodies
-Look up categories for this council or councils
+Look up categories for the relevant body or bodies.
=cut
-sub setup_categories_and_councils : Private {
+sub setup_categories_and_bodies : Private {
my ( $self, $c ) = @_;
- my $all_councils = $c->stash->{all_councils};
- my $first_council = ( values %$all_councils )[0];
+ my $all_areas = $c->stash->{all_areas};
+ my $first_area = ( values %$all_areas )[0];
+
+ my @bodies = $c->model('DB::Body')->search(
+ { 'body_areas.area_id' => [ keys %$all_areas ] },
+ { join => 'body_areas' }
+ )->all;
+ my %bodies = map { $_->id => $_ } @bodies;
+ my $first_body = ( values %bodies )[0];
my @contacts #
= $c #
->model('DB::Contact') #
->not_deleted #
- ->search( { area_id => [ keys %$all_councils ] } ) #
+ ->search( { body_id => [ keys %bodies ] } )
->all;
# variables to populate
- my %area_ids_to_list = (); # Areas with categories assigned
+ my %bodies_to_list = (); # Bodies with categories assigned
my @category_options = (); # categories to show
my $category_label = undef; # what to call them
my %category_extras = (); # extra fields to fill in for open311
@@ -599,9 +606,9 @@ sub setup_categories_and_councils : Private {
# FIXME - implement in cobrand
if ( $c->cobrand->moniker eq 'emptyhomes' ) {
- # add all areas found to the list
+ # add all bodies found to the list
foreach (@contacts) {
- $area_ids_to_list{ $_->area_id } = 1;
+ $bodies_to_list{ $_->body_id } = 1;
}
# set our own categories
@@ -616,11 +623,11 @@ sub setup_categories_and_councils : Private {
);
$category_label = _('Property type:');
- } elsif ($first_council->{id} != COUNCIL_ID_BROMLEY && $first_council->{type} eq 'LBO') {
+ } elsif ($first_area->{id} != COUNCIL_ID_BROMLEY && $first_area->{type} eq 'LBO') {
- $area_ids_to_list{ $first_council->{id} } = 1;
+ $bodies_to_list{ $first_body->id } = 1;
my @local_categories;
- if ($first_council->{id} == COUNCIL_ID_BARNET) {
+ if ($first_area->{id} == COUNCIL_ID_BARNET) {
@local_categories = sort keys %{ Utils::barnet_categories() }
} else {
@local_categories = sort keys %{ Utils::london_categories() }
@@ -639,7 +646,7 @@ sub setup_categories_and_councils : Private {
my %seen;
foreach my $contact (@contacts) {
- $area_ids_to_list{ $contact->area_id } = 1;
+ $bodies_to_list{ $contact->body_id } = 1;
unless ( $seen{$contact->category} ) {
push @category_options, $contact->category;
@@ -661,24 +668,21 @@ sub setup_categories_and_councils : Private {
}
# put results onto stash for display
- $c->stash->{area_ids_to_list} = [ keys %area_ids_to_list ];
+ $c->stash->{bodies} = \%bodies;
+ $c->stash->{all_body_names} = [ map { $_->name } values %bodies ];
+ $c->stash->{bodies_to_list} = [ keys %bodies_to_list ];
$c->stash->{category_label} = $category_label;
$c->stash->{category_options} = \@category_options;
$c->stash->{category_extras} = \%category_extras;
$c->stash->{non_public_categories} = \%non_public_categories;
$c->stash->{category_extras_json} = encode_json \%category_extras;
- $c->stash->{extra_name_info} = $first_council->{id} == COUNCIL_ID_BROMLEY ? 1 : 0;
-
- my @missing_details_councils =
- grep { !$area_ids_to_list{$_} } #
- keys %$all_councils;
+ $c->stash->{extra_name_info} = $first_area->{id} == COUNCIL_ID_BROMLEY ? 1 : 0;
- my @missing_details_council_names =
- map { $all_councils->{$_}->{name} } #
- @missing_details_councils;
+ my @missing_details_bodies = grep { !$bodies_to_list{$_->id} } values %bodies;
+ my @missing_details_body_names = map { $_->name } @missing_details_bodies;
- $c->stash->{missing_details_councils} = \@missing_details_councils;
- $c->stash->{missing_details_council_names} = \@missing_details_council_names;
+ $c->stash->{missing_details_bodies} = \@missing_details_bodies;
+ $c->stash->{missing_details_body_names} = \@missing_details_body_names;
}
=head2 check_form_submitted
@@ -820,60 +824,62 @@ sub process_report : Private {
$report->subcategory( $params{subcategory} );
- my $areas = $c->stash->{all_areas};
+ my $areas = $c->stash->{all_areas_mapit};
$report->areas( ',' . join( ',', sort keys %$areas ) . ',' );
# From earlier in the process.
- my $councils = $c->stash->{all_councils};
- my $first_council = ( values %$councils )[0];
+ $areas = $c->stash->{all_areas};
+ my $bodies = $c->stash->{bodies};
+ my $first_area = ( values %$areas )[0];
+ my $first_body = ( values %$bodies )[0];
if ( $c->cobrand->moniker eq 'emptyhomes' ) {
- $councils = join( ',', @{ $c->stash->{area_ids_to_list} } ) || -1;
- $report->council( $councils );
+ $bodies = join( ',', @{ $c->stash->{bodies_to_list} } ) || -1;
+ $report->bodies_str( $bodies );
- } elsif ( $first_council->{id} == COUNCIL_ID_BARNET ) {
+ } elsif ( $first_area->{id} == COUNCIL_ID_BARNET ) {
unless ( exists Utils::barnet_categories()->{ $report->category } ) {
$c->stash->{field_errors}->{category} = _('Please choose a category');
}
- $report->council( $first_council->{id} );
+ $report->bodies_str( $first_body->id );
- } elsif ( $first_council->{id} != COUNCIL_ID_BROMLEY && $first_council->{type} eq 'LBO') {
+ } elsif ( $first_area->{id} != COUNCIL_ID_BROMLEY && $first_area->{type} eq 'LBO') {
unless ( Utils::london_categories()->{ $report->category } ) {
$c->stash->{field_errors}->{category} = _('Please choose a category');
}
- $report->council( $first_council->{id} );
+ $report->bodies_str( $first_body->id );
} elsif ( $report->category ) {
- # FIXME All contacts were fetched in setup_categories_and_councils,
+ # FIXME All contacts were fetched in setup_categories_and_bodies,
# so can this DB call also be avoided?
my @contacts = $c-> #
model('DB::Contact') #
->not_deleted #
->search(
{
- area_id => [ keys %$councils ],
+ body_id => [ keys %$bodies ],
category => $report->category
}
)->all;
unless ( @contacts ) {
$c->stash->{field_errors}->{category} = _('Please choose a category');
- $report->council( -1 );
+ $report->bodies_str( -1 );
return 1;
}
- # construct the council string:
- # 'x,x' - x are council IDs that have this category
- # 'x,x|y,y' - x are council IDs that have this category, y council IDs with *no* contact
- my $council_string = join( ',', map { $_->area_id } @contacts );
- $council_string .=
- '|' . join( ',', @{ $c->stash->{missing_details_councils} } )
- if $council_string && @{ $c->stash->{missing_details_councils} };
- $report->council($council_string);
+ # construct the bodies string:
+ # 'x,x' - x are body IDs that have this category
+ # 'x,x|y' - x are body IDs that have this category, y body IDs with *no* contact
+ my $body_string = join( ',', map { $_->body_id } @contacts );
+ $body_string .=
+ '|' . join( ',', map { $_->id } @{ $c->stash->{missing_details_bodies} } )
+ if $body_string && @{ $c->stash->{missing_details_bodies} };
+ $report->bodies_str($body_string);
my @extra = ();
my $metas = $contacts[0]->extra;
@@ -895,13 +901,13 @@ sub process_report : Private {
$report->non_public( 1 );
}
- $c->cobrand->process_extras( $c, $contacts[0]->area_id, \@extra );
+ $c->cobrand->process_extras( $c, $contacts[0]->body_id, \@extra );
if ( @extra ) {
$c->stash->{report_meta} = { map { $_->{name} => $_ } @extra };
$report->extra( \@extra );
}
- } elsif ( @{ $c->stash->{area_ids_to_list} } ) {
+ } elsif ( @{ $c->stash->{bodies_to_list} } ) {
# There was an area with categories, but we've not been given one. Bail.
$c->stash->{field_errors}->{category} = _('Please choose a category');
@@ -910,7 +916,7 @@ sub process_report : Private {
# If we're here, we've been submitted somewhere
# where we have no contact information at all.
- $report->council( -1 );
+ $report->bodies_str( -1 );
}
@@ -944,6 +950,8 @@ sub check_for_errors : Private {
if ( $c->cobrand->moniker eq 'zurich' ) {
delete $field_errors{title};
delete $field_errors{name};
+ my $report = $c->stash->{report};
+ $report->title( Utils::cleanup_text( substr($report->detail, 0, 25) ) );
}
# FIXME: need to check for required bromley fields here
@@ -1006,8 +1014,10 @@ sub save_user_and_report : Private {
$c->log->info($report->user->id . ' created for this report');
}
elsif ( $c->user && $report->user->id == $c->user->id ) {
+ # Logged in and matches, so instantly confirm (except Zurich, with no confirmation)
$report->user->update();
- $report->confirm;
+ $report->confirm
+ unless $c->cobrand->moniker eq 'zurich';
$c->log->info($report->user->id . ' is logged in for this report');
}
else {
@@ -1032,7 +1042,7 @@ sub save_user_and_report : Private {
$report->category( _('Other') ) unless $report->category;
# Set unknown to DB unknown
- $report->council( undef ) if $report->council eq '-1';
+ $report->bodies_str( undef ) if $report->bodies_str eq '-1';
# if there is a Message Manager message ID, pass it back to the client view
if ($c->cobrand->moniker eq 'fixmybarangay' && $c->req->param('external_source_id')=~/^\d+$/) {
@@ -1113,7 +1123,7 @@ sub redirect_or_confirm_creation : Private {
$c->forward( 'create_reporter_alert' );
my $report_uri;
- if ( $c->cobrand->moniker eq 'fixmybarangay' && $c->user->from_council && $c->stash->{external_source_id}) {
+ if ( $c->cobrand->moniker eq 'fixmybarangay' && $c->user->from_body && $c->stash->{external_source_id}) {
$report_uri = $c->uri_for( '/report', $report->id, undef, { external_source_id => $c->stash->{external_source_id} } );
} elsif ( $c->cobrand->never_confirm_reports && $report->non_public ) {
$c->log->info( 'cobrand was set to always confirm reports and report was non public, success page showed');
@@ -1138,7 +1148,7 @@ sub redirect_or_confirm_creation : Private {
} );
$c->stash->{token_url} = $c->uri_for_email( '/P', $token->token );
$c->send_email( 'problem-confirm.txt', {
- to => [ [ $report->user->email, $report->name ] ],
+ to => [ $report->name ? [ $report->user->email, $report->name ] : $report->user->email ],
} );
# tell user that they've been sent an email
diff --git a/perllib/FixMyStreet/App/Controller/Report/Update.pm b/perllib/FixMyStreet/App/Controller/Report/Update.pm
index 5e0d9f388..dbfd57e78 100644
--- a/perllib/FixMyStreet/App/Controller/Report/Update.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/Update.pm
@@ -76,7 +76,7 @@ sub update_problem : Private {
$problem->state('confirmed');
}
- if ( $c->cobrand->can_support_problems && $c->user && $c->user->from_council && $c->req->param('external_source_id') ) {
+ if ( $c->cobrand->can_support_problems && $c->user && $c->user->from_body && $c->req->param('external_source_id') ) {
$problem->interest_count( \'interest_count + 1' );
}
@@ -201,7 +201,7 @@ sub process_update : Private {
if ( $params{state} ) {
$params{state} = 'fixed - council'
- if $params{state} eq 'fixed' && $c->user && $c->user->belongs_to_council( $update->problem->council );
+ if $params{state} eq 'fixed' && $c->user && $c->user->belongs_to_body( $update->problem->bodies_str );
$update->problem_state( $params{state} );
} else {
# we do this so we have a record of the state of the problem at this point
@@ -223,7 +223,7 @@ sub process_update : Private {
my @extra; # Next function fills this, but we don't need it here.
# This is just so that the error checkign for these extra fields runs.
# TODO Use extra here as it is used on reports.
- $c->cobrand->process_extras( $c, $update->problem->council, \@extra );
+ $c->cobrand->process_extras( $c, $update->problem->bodies_str, \@extra );
if ( $c->req->param('fms_extra_title') ) {
my %extras = ();
@@ -261,7 +261,7 @@ sub check_for_errors : Private {
# they have to be an authority user to update the state
if ( $c->req->param('state') ) {
my $error = 0;
- $error = 1 unless $c->user && $c->user->belongs_to_council( $c->stash->{update}->problem->council );
+ $error = 1 unless $c->user && $c->user->belongs_to_body( $c->stash->{update}->problem->bodies_str );
my $state = $c->req->param('state');
$state = 'fixed - council' if $state eq 'fixed';
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index 1fcbfbd72..781dee698 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -5,6 +5,7 @@ use namespace::autoclean;
use File::Slurp;
use List::MoreUtils qw(zip);
use POSIX qw(strcoll);
+use RABX;
use mySociety::MaPit;
BEGIN { extends 'Catalyst::Controller'; }
@@ -30,34 +31,26 @@ Show the summary page of all reports.
sub index : Path : Args(0) {
my ( $self, $c ) = @_;
- # Fetch all areas of the types we're interested in
- my $areas_info;
- eval {
- my $area_types = $c->cobrand->area_types;
- $areas_info = mySociety::MaPit::call('areas', $area_types,
- min_generation => $c->cobrand->area_min_generation
+ # Zurich goes straight to map page, with all reports
+ if ( $c->cobrand->moniker eq 'zurich' ) {
+ $c->forward( 'load_and_group_problems' );
+ my $pins = $c->stash->{pins};
+ $c->stash->{page} = 'reports';
+ FixMyStreet::Map::display_map(
+ $c,
+ latitude => @$pins ? $pins->[0]{latitude} : 0,
+ longitude => @$pins ? $pins->[0]{longitude} : 0,
+ area => 274456,
+ pins => $pins,
+ any_zoom => 1,
);
- };
- if ($@) {
- $c->stash->{message} = _("Unable to look up areas in MaPit. Please try again later.") . ' ' .
- sprintf(_('The error was: %s'), $@);
- $c->stash->{template} = 'errors/generic.html';
- return;
+ return 1;
}
- # For each area, add its link and perhaps alter its name if we need to for
- # places with the same name.
- foreach (values %$areas_info) {
- $_->{url} = $c->uri_for( '/reports/' . $c->cobrand->short_name( $_, $areas_info ) );
- if ($_->{parent_area} && $_->{url} =~ /,|%2C/) {
- $_->{name} .= ', ' . $areas_info->{$_->{parent_area}}{name};
- }
- }
-
- $c->stash->{areas_info} = $areas_info;
- my @keys = sort { strcoll($areas_info->{$a}{name}, $areas_info->{$b}{name}) } keys %$areas_info;
- @keys = $c->cobrand->filter_all_council_ids_list( @keys );
- $c->stash->{areas_info_sorted} = [ map { $areas_info->{$_} } @keys ];
+ # Fetch all areas of the types we're interested in
+ my @bodies = $c->model('DB::Body')->all;
+ @bodies = sort { strcoll($a->name, $b->name) } @bodies;
+ $c->stash->{bodies} = \@bodies;
eval {
my $data = File::Slurp::read_file(
@@ -99,21 +92,20 @@ Show the summary page for a particular ward.
=cut
sub ward : Path : Args(2) {
- my ( $self, $c, $council, $ward ) = @_;
+ my ( $self, $c, $body, $ward ) = @_;
- $c->forward( 'body_check', [ $council ] );
+ $c->forward( 'body_check', [ $body ] );
$c->forward( 'ward_check', [ $ward ] )
if $ward;
- $c->forward( 'load_parent' );
- $c->forward( 'check_canonical_url', [ $council ] );
+ $c->forward( 'check_canonical_url', [ $body ] );
$c->forward( 'load_and_group_problems' );
- my $council_short = $c->cobrand->short_name( $c->stash->{council}, $c->stash->{areas_info} );
- $c->stash->{rss_url} = '/rss/reports/' . $council_short;
+ my $body_short = $c->cobrand->short_name( $c->stash->{body} );
+ $c->stash->{rss_url} = '/rss/reports/' . $body_short;
$c->stash->{rss_url} .= '/' . $c->cobrand->short_name( $c->stash->{ward} )
if $c->stash->{ward};
- $c->stash->{council_url} = '/reports/' . $council_short;
+ $c->stash->{body_url} = '/reports/' . $body_short;
$c->stash->{stats} = $c->cobrand->get_report_stats();
@@ -123,7 +115,7 @@ sub ward : Path : Args(2) {
my %map_params = (
latitude => @$pins ? $pins->[0]{latitude} : 0,
longitude => @$pins ? $pins->[0]{longitude} : 0,
- area => $c->stash->{ward} ? $c->stash->{ward}->{id} : $c->stash->{council}->{id},
+ area => $c->stash->{ward} ? $c->stash->{ward}->{id} : [ keys %{$c->stash->{body}->areas} ],
any_zoom => 1,
);
if ( $c->cobrand->moniker eq 'emptyhomes' ) {
@@ -139,64 +131,121 @@ sub ward : Path : Args(2) {
$c->cobrand->tweak_all_reports_map( $c );
# List of wards
- # Ignore external_body special council thing
- unless ($c->stash->{ward} || !$c->stash->{council}->{id}) {
- my $children = mySociety::MaPit::call('area/children', [ $c->stash->{council}->{id} ],
+ # Ignore external_body special body thing
+ unless ($c->stash->{ward} || !$c->stash->{body}->id) {
+ my $children = mySociety::MaPit::call('area/children', [ $c->stash->{body}->body_areas->first->area_id ],
type => $c->cobrand->area_types_children,
);
- foreach (values %$children) {
- $_->{url} = $c->uri_for( $c->stash->{council_url}
- . '/' . $c->cobrand->short_name( $_ )
- );
+ unless ($children->{error}) {
+ foreach (values %$children) {
+ $_->{url} = $c->uri_for( $c->stash->{body_url}
+ . '/' . $c->cobrand->short_name( $_ )
+ );
+ }
+ $c->stash->{children} = $children;
}
- $c->stash->{children} = $children;
}
}
-sub rss_body : Regex('^rss/(reports|area)$') : Args(1) {
- my ( $self, $c, $body ) = @_;
- $c->detach( 'rss_ward', [ $body ] );
+sub rss_area : Path('/rss/area') : Args(1) {
+ my ( $self, $c, $area ) = @_;
+ $c->detach( 'rss_area_ward', [ $area ] );
}
-sub rss_ward : Regex('^rss/(reports|area)$') : Args(2) {
- my ( $self, $c, $council, $ward ) = @_;
-
- my ( $rss ) = $c->req->captures->[0];
+sub rss_area_ward : Path('/rss/area') : Args(2) {
+ my ( $self, $c, $area, $ward ) = @_;
$c->stash->{rss} = 1;
- $c->forward( 'body_check', [ $council ] );
- $c->forward( 'ward_check', [ $ward ] ) if $ward;
+ # area_check
+
+ $area =~ s/\+/ /g;
+ $area =~ s/\.html//;
- if ($rss eq 'area' && $c->stash->{council}{type} ne 'DIS' && $c->stash->{council}{type} ne 'CTY') {
- # Two possibilites are the same for one-tier councils, so redirect one to the other
- $c->detach( 'redirect_area' );
+ # If we're passed an ID number (don't think this is used anywhere, it
+ # certainly shouldn't be), just look that up on mapit and redirect
+ if ($area =~ /^\d+$/) {
+ my $council = mySociety::MaPit::call('area', $area);
+ $c->detach( 'redirect_index') if $council->{error};
+ $c->stash->{body} = $council;
+ $c->detach( 'redirect_body' );
+ }
+
+ # We must now have a string to check on mapit
+ my $areas = mySociety::MaPit::call( 'areas', $area,
+ type => $c->cobrand->area_types,
+ );
+
+ if (keys %$areas == 1) {
+ ($c->stash->{area}) = values %$areas;
+ } else {
+ foreach (keys %$areas) {
+ if (lc($areas->{$_}->{name}) eq lc($area) || $areas->{$_}->{name} =~ /^\Q$area\E (Borough|City|District|County) Council$/i) {
+ $c->stash->{area} = $areas->{$_};
+ }
+ }
}
- my $url = $c->cobrand->short_name( $c->stash->{council} );
- $url .= '/' . $c->cobrand->short_name( $c->stash->{ward} ) if $c->stash->{ward};
+ $c->forward( 'ward_check', [ $ward ] ) if $ward;
+
+ my $url = $c->cobrand->short_name( $c->stash->{area} );
+ $url .= '/' . $c->cobrand->short_name( $c->stash->{ward} ) if $c->stash->{ward};
$c->stash->{qs} = "/$url";
- if ( $rss eq 'area' && $c->stash->{ward} ) {
+ if ($c->stash->{area}{type} ne 'DIS' && $c->stash->{area}{type} ne 'CTY') {
+ # UK-specific types - two possibilites are the same for one-tier councils, so redirect one to the other
+ # With bodies, this should presumably redirect if only one body covers
+ # the area, and then it will need that body's name (rather than
+ # assuming as now it is the same as the area)
+ $c->stash->{body} = $c->stash->{area};
+ $c->detach( 'redirect_body' );
+ }
+
+ $c->stash->{type} = 'area_problems';
+ if ( $c->stash->{ward} ) {
# All problems within a particular ward
- $c->stash->{type} = 'area_problems';
$c->stash->{title_params} = { NAME => $c->stash->{ward}{name} };
$c->stash->{db_params} = [ $c->stash->{ward}->{id} ];
- } elsif ( $rss eq 'area' ) {
- # Problems within a particular council
- $c->stash->{type} = 'area_problems';
- $c->stash->{title_params} = { NAME => $c->stash->{council}{name} };
- $c->stash->{db_params} = [ $c->stash->{council}->{id} ];
- } elsif ($c->stash->{ward}) {
+ } else {
+ # Problems within a particular area
+ $c->stash->{title_params} = { NAME => $c->stash->{area}->{name} };
+ $c->stash->{db_params} = [ $c->stash->{area}->{id} ];
+ }
+
+ # Send on to the RSS generation
+ $c->forward( '/rss/output' );
+
+}
+
+sub rss_body : Path('/rss/reports') : Args(1) {
+ my ( $self, $c, $body ) = @_;
+ $c->detach( 'rss_ward', [ $body ] );
+}
+
+sub rss_ward : Path('/rss/reports') : Args(2) {
+ my ( $self, $c, $body, $ward ) = @_;
+
+ $c->stash->{rss} = 1;
+
+ $c->forward( 'body_check', [ $body ] );
+ $c->forward( 'ward_check', [ $ward ] ) if $ward;
+
+ my $url = $c->cobrand->short_name( $c->stash->{body} );
+ $url .= '/' . $c->cobrand->short_name( $c->stash->{ward} ) if $c->stash->{ward};
+ $c->stash->{qs} = "/$url";
+
+ if ($c->stash->{ward}) {
# Problems sent to a council, restricted to a ward
$c->stash->{type} = 'ward_problems';
- $c->stash->{title_params} = { COUNCIL => $c->stash->{council}{name}, WARD => $c->stash->{ward}{name} };
- $c->stash->{db_params} = [ $c->stash->{council}->{id}, $c->stash->{ward}->{id} ];
+ $c->stash->{title_params} = { COUNCIL => $c->stash->{body}->name, WARD => $c->stash->{ward}{name} };
+ $c->stash->{db_params} = [ $c->stash->{body}->id, $c->stash->{ward}->{id} ];
} else {
# Problems sent to a council
$c->stash->{type} = 'council_problems';
- $c->stash->{title_params} = { COUNCIL => $c->stash->{council}{name} };
- $c->stash->{db_params} = [ $c->stash->{council}->{id}, $c->stash->{council}->{id} ];
+ $c->stash->{title_params} = { COUNCIL => $c->stash->{body}->name };
+ # XXX This looks up in both bodies_str and areas, but is only using body ID.
+ # This will not work properly in any install where body IDs are not === area IDs.
+ $c->stash->{db_params} = [ $c->stash->{body}->id, $c->stash->{body}->id ];
}
# Send on to the RSS generation
@@ -205,60 +254,56 @@ sub rss_ward : Regex('^rss/(reports|area)$') : Args(2) {
=head2 body_check
-This action checks the council or external_body name (or code) given in a URI
-exists, is valid and so on. If it is, it stores the area or body in the stash,
-otherwise it redirects to the all reports page.
+This action checks the body name (or code) given in a URI exists, is valid and
+so on. If it is, it stores the body in the stash, otherwise it redirects to the
+all reports page.
=cut
sub body_check : Private {
- my ( $self, $c, $q_council ) = @_;
+ my ( $self, $c, $q_body ) = @_;
- $q_council =~ s/\+/ /g;
- $q_council =~ s/\.html//;
+ $q_body =~ s/\+/ /g;
+ $q_body =~ s/\.html//;
# Check cobrand specific incantations - e.g. ONS codes for UK,
# Oslo/ kommunes sharing a name in Norway
- return if $c->cobrand->reports_body_check( $c, $q_council );
+ return if $c->cobrand->reports_body_check( $c, $q_body );
# If we're passed an ID number (don't think this is used anywhere, it
# certainly shouldn't be), just look that up on MaPit and redirect
- if ($q_council =~ /^\d+$/) {
- my $council = mySociety::MaPit::call('area', $q_council);
- $c->detach( 'redirect_index') if $council->{error};
- $c->stash->{council} = $council;
- $c->detach( 'redirect_area' );
+ if ($q_body =~ /^\d+$/) {
+ my $area = mySociety::MaPit::call('area', $q_body);
+ $c->detach( 'redirect_index') if $area->{error};
+ $c->stash->{body} = $area;
+ $c->detach( 'redirect_body' );
}
if ( $c->cobrand->reports_by_body ) {
- my $problem = $c->cobrand->problems->search({ 'lower(me.external_body)' => lc $q_council }, { columns => [ 'external_body' ], rows => 1 })->single;
+ my $problem = $c->cobrand->problems->search({ 'lower(me.external_body)' => lc $q_body }, { columns => [ 'external_body' ], rows => 1 })->single;
if ( $problem ) {
- # If external_body, put as a council with ID 0 for the moment.
- $c->stash->{council} = { id => 0, name => $problem->external_body };
+ # If external_body, put as a body with ID 0 for the moment.
+ $c->stash->{body} = $c->model('DB::Body')->new( { id => 0, name => $problem->external_body } );
return;
}
}
# We must now have a string to check
- my $area_types = $c->cobrand->area_types;
- my $areas = mySociety::MaPit::call( 'areas', $q_council,
- type => $area_types,
- min_generation => $c->cobrand->area_min_generation
- );
+ my @bodies = $c->model('DB::Body')->search( { name => { -like => "$q_body%" } } )->all;
- if (keys %$areas == 1) {
- ($c->stash->{council}) = values %$areas;
+ if (@bodies == 1) {
+ $c->stash->{body} = $bodies[0];
return;
} else {
- foreach (keys %$areas) {
- if (lc($areas->{$_}->{name}) eq lc($q_council) || $areas->{$_}->{name} =~ /^\Q$q_council\E (Borough|City|District|County) Council$/i) {
- $c->stash->{council} = $areas->{$_};
+ foreach (@bodies) {
+ if (lc($_->name) eq lc($q_body) || $_->name =~ /^\Q$q_body\E (Borough|City|District|County) Council$/i) {
+ $c->stash->{body} = $_;
return;
}
}
}
- # No result, bad council name.
+ # No result, bad body name.
$c->detach( 'redirect_index' );
}
@@ -266,7 +311,7 @@ sub body_check : Private {
This action checks the ward name from a URI exists and is part of the right
parent, already found with body_check. It either stores the ward Area if
-okay, or redirects to the council page if bad.
+okay, or redirects to the body page if bad.
=cut
@@ -277,48 +322,41 @@ sub ward_check : Private {
$ward =~ s/\.html//;
$ward =~ s{_}{/}g;
- my $council = $c->stash->{council};
+ # Could be from RSS area, or body...
+ my $parent_id;
+ if ( $c->stash->{body} ) {
+ $parent_id = $c->stash->{body}->body_areas->first->area_id;
+ } else {
+ $parent_id = $c->stash->{area}->{id};
+ }
my $qw = mySociety::MaPit::call('areas', $ward,
type => $c->cobrand->area_types_children,
- min_generation => $c->cobrand->area_min_generation
);
foreach my $area (sort { $a->{name} cmp $b->{name} } values %$qw) {
- if ($area->{parent_area} == $council->{id}) {
+ if ($area->{parent_area} == $parent_id) {
$c->stash->{ward} = $area;
return;
}
}
# Given a false ward name
- $c->detach( 'redirect_area' );
-}
-
-sub load_parent : Private {
- my ( $self, $c ) = @_;
-
- my $council = $c->stash->{council};
- my $areas_info;
- if ($council->{parent_area}) {
- $c->stash->{areas_info} = mySociety::MaPit::call('areas', [ $council->{id}, $council->{parent_area} ])
- } else {
- $c->stash->{areas_info} = { $council->{id} => $council };
- }
+ $c->detach( 'redirect_body' );
}
=head2 check_canonical_url
-Given an already found (case-insensitively) council, check what URL
+Given an already found (case-insensitively) body, check what URL
we are at and redirect accordingly if different.
=cut
sub check_canonical_url : Private {
- my ( $self, $c, $q_council ) = @_;
+ my ( $self, $c, $q_body ) = @_;
- my $council_short = $c->cobrand->short_name( $c->stash->{council}, $c->stash->{areas_info} );
- my $url_short = URI::Escape::uri_escape_utf8($q_council);
+ my $body_short = $c->cobrand->short_name( $c->stash->{body} );
+ my $url_short = URI::Escape::uri_escape_utf8($q_body);
$url_short =~ s/%2B/+/g;
- $c->detach( 'redirect_area' ) unless $council_short eq $url_short;
+ $c->detach( 'redirect_body' ) unless $body_short eq $url_short;
}
sub load_and_group_problems : Private {
@@ -332,69 +370,57 @@ sub load_and_group_problems : Private {
};
if ($c->stash->{ward}) {
$where->{areas} = { 'like', '%,' . $c->stash->{ward}->{id} . ',%' };
- $where->{council} = [
+ $where->{bodies_str} = [
undef,
- $c->stash->{council}->{id},
- { 'like', $c->stash->{council}->{id} . ',%' },
- { 'like', '%,' . $c->stash->{council}->{id} },
+ $c->stash->{body}->id,
+ { 'like', $c->stash->{body}->id . ',%' },
+ { 'like', '%,' . $c->stash->{body}->id },
];
- } elsif ($c->stash->{council} && $c->stash->{council}->{id} == 0) {
+ } elsif ($c->stash->{body} && $c->stash->{body}->id == 0) {
# A proxy for an external_body
- $where->{'lower(external_body)'} = lc $c->stash->{council}->{name};
- } elsif ($c->stash->{council}) {
- $where->{areas} = { 'like', '%,' . $c->stash->{council}->{id} . ',%' };
- $where->{council} = [
- undef,
- $c->stash->{council}->{id},
- { 'like', $c->stash->{council}->{id} . ',%' },
- { 'like', '%,' . $c->stash->{council}->{id} },
+ $where->{'lower(external_body)'} = lc $c->stash->{body}->name;
+ } elsif ($c->stash->{body}) {
+ # XXX FixMyStreet used to have the following line so that reports not
+ # currently sent anywhere could still be listed in the appropriate
+ # (body/area), as they were the same. Now they're not, not sure if
+ # there's a way to do this easily.
+ #$where->{areas} = { 'like', '%,' . $c->stash->{body}->id . ',%' };
+ $where->{bodies_str} = [
+ # undef,
+ $c->stash->{body}->id,
+ { 'like', $c->stash->{body}->id . ',%' },
+ { 'like', '%,' . $c->stash->{body}->id },
];
}
my $problems = $c->cobrand->problems->search(
$where,
{
- columns => [
- 'id', 'council', 'state', 'areas', 'latitude', 'longitude', 'title', 'cobrand',
- #{ duration => { extract => "epoch from current_timestamp-lastupdate" } },
- #{ age => { extract => "epoch from current_timestamp-confirmed" } },
- { confirmed => { extract => 'epoch from confirmed' } },
- { whensent => { extract => 'epoch from whensent' } },
- { lastupdate => { extract => 'epoch from lastupdate' } },
- { photo => 'photo is not null' },
- ],
order_by => { -desc => 'lastupdate' },
rows => $c->cobrand->reports_per_page,
}
)->page( $page );
$c->stash->{pager} = $problems->pager;
- $problems = $problems->cursor; # Raw DB cursor for speed
my ( %problems, @pins );
- my $re_councils = join('|', keys %{$c->stash->{areas_info}});
- my @cols = ( 'id', 'council', 'state', 'areas', 'latitude', 'longitude', 'title', 'cobrand', 'confirmed', 'whensent', 'lastupdate', 'photo' );
- while ( my @problem = $problems->next ) {
- my %problem = zip @cols, @problem;
- $problem{is_fixed} = FixMyStreet::DB::Result::Problem->fixed_states()->{$problem{state}};
- $c->log->debug( $problem{'cobrand'} . ', cobrand is ' . $c->cobrand->moniker );
- if ( !$c->stash->{council}->{id} ) {
+ while ( my $problem = $problems->next ) {
+ $c->log->debug( $problem->cobrand . ', cobrand is ' . $c->cobrand->moniker );
+ if ( !$c->stash->{body} || !$c->stash->{body}->id ) {
# An external_body entry
- add_row( \%problem, 0, \%problems, \@pins );
+ add_row( $c, $problem, 0, \%problems, \@pins );
next;
}
- if ( !$problem{council} ) {
- # Problem was not sent to any council, add to possible councils
- $problem{councils} = 0;
- while ($problem{areas} =~ /,($re_councils)(?=,)/g) {
- add_row( \%problem, $1, \%problems, \@pins );
+ if ( !$problem->bodies_str ) {
+ # Problem was not sent to any body, add to all possible areas XXX
+ while ($problem->areas =~ /,(\d+)(?=,)/g) {
+ add_row( $c, $problem, $1, \%problems, \@pins );
}
} else {
- # Add to councils it was sent to
- (my $council = $problem{council}) =~ s/\|.*$//;
- my @council = split( /,/, $council );
- $problem{councils} = scalar @council;
- foreach ( @council ) {
- next if $_ != $c->stash->{council}->{id};
- add_row( \%problem, $_, \%problems, \@pins );
+ # Add to bodies it was sent to
+ # XXX Assumes body ID matches "council ID"
+ my $bodies = $problem->bodies_str_ids;
+ foreach ( @$bodies ) {
+ next if $_ != $c->stash->{body}->id;
+ add_row( $c, $problem, $_, \%problems, \@pins );
}
}
}
@@ -413,26 +439,26 @@ sub redirect_index : Private {
$c->res->redirect( $c->uri_for($url) );
}
-sub redirect_area : Private {
+sub redirect_body : Private {
my ( $self, $c ) = @_;
my $url = '';
$url .= "/rss" if $c->stash->{rss};
$url .= '/reports';
- $url .= '/' . $c->cobrand->short_name( $c->stash->{council}, $c->stash->{areas_info} );
+ $url .= '/' . $c->cobrand->short_name( $c->stash->{body} );
$url .= '/' . $c->cobrand->short_name( $c->stash->{ward} )
if $c->stash->{ward};
$c->res->redirect( $c->uri_for($url) );
}
sub add_row {
- my ( $problem, $council, $problems, $pins ) = @_;
- push @{$problems->{$council}}, $problem;
+ my ( $c, $problem, $body, $problems, $pins ) = @_;
+ push @{$problems->{$body}}, $problem;
push @$pins, {
- latitude => $problem->{latitude},
- longitude => $problem->{longitude},
- colour => 'yellow', # FixMyStreet::DB::Result::Problem->fixed_states()->{$problem->{state}} ? 'green' : 'red',
- id => $problem->{id},
- title => $problem->{title},
+ latitude => $problem->latitude,
+ longitude => $problem->longitude,
+ colour => $c->cobrand->pin_colour( $problem, 'reports' ),
+ id => $problem->id,
+ title => $problem->title_safe,
};
}
diff --git a/perllib/FixMyStreet/App/Controller/Rss.pm b/perllib/FixMyStreet/App/Controller/Rss.pm
index baaa3b927..90ab7ad41 100755
--- a/perllib/FixMyStreet/App/Controller/Rss.pm
+++ b/perllib/FixMyStreet/App/Controller/Rss.pm
@@ -241,6 +241,15 @@ sub add_row : Private {
$row->{name} = 'anonymous' if $row->{anonymous} || !$row->{name};
my $pubDate;
+ if ($row->{created}) {
+ $row->{created} =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/;
+ $pubDate = mySociety::Locale::in_gb_locale {
+ strftime("%a, %d %b %Y %H:%M:%S %z", $6, $5, $4, $3, $2-1, $1-1900, -1, -1, 0)
+ };
+ $row->{created} = strftime("%e %B", $6, $5, $4, $3, $2-1, $1-1900, -1, -1, 0);
+ $row->{created} =~ s/^\s+//;
+ $row->{created} =~ s/^(\d+)/ordinal($1)/e if $c->stash->{lang_code} eq 'en-gb';
+ }
if ($row->{confirmed}) {
$row->{confirmed} =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/;
$pubDate = mySociety::Locale::in_gb_locale {
@@ -257,7 +266,7 @@ sub add_row : Private {
my $hashref_restriction = $c->cobrand->site_restriction;
my $base_url = $c->cobrand->base_url;
- if ( $hashref_restriction && $hashref_restriction->{council} && $row->{council} && $row->{council} ne $hashref_restriction->{council} ) {
+ if ( $hashref_restriction && $hashref_restriction->{bodies_str} && $row->{bodies_str} && $row->{bodies_str} ne $hashref_restriction->{bodies_str} ) {
$base_url = $c->config->{BASE_URL};
}
my $url = $base_url . $link;
diff --git a/perllib/FixMyStreet/App/Controller/Tokens.pm b/perllib/FixMyStreet/App/Controller/Tokens.pm
index 03dc69b00..740822876 100644
--- a/perllib/FixMyStreet/App/Controller/Tokens.pm
+++ b/perllib/FixMyStreet/App/Controller/Tokens.pm
@@ -53,6 +53,28 @@ sub confirm_problem : Path('/P') {
return;
}
+ # For Zurich, email confirmation simply sets a flag, it does not change the
+ # problem state, log in, or anything else
+ if ($c->cobrand->moniker eq 'zurich') {
+ my $extra = { %{ $problem->extra || {} } };
+ $extra->{email_confirmed} = 1;
+ $problem->update( {
+ extra => $extra,
+ confirmed => \'ms_current_timestamp()',
+ } );
+
+ $c->stash->{report} = $c->stash->{problem};
+ $c->forward( '/report/new/create_reporter_alert' );
+
+ if ( ref($data) && ( $data->{name} || $data->{password} ) ) {
+ $problem->user->name( $data->{name} ) if $data->{name};
+ $problem->user->phone( $data->{phone} ) if $data->{phone};
+ $problem->user->update;
+ }
+
+ return 1;
+ }
+
# We have a problem - confirm it if needed!
my $old_state = $problem->state;
$problem->update(