diff options
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin/Triage.pm | 163 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Around.pm | 14 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 11 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report/New.pm | 19 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Reports.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/FixMyStreet.pm | 112 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/IsleOfWight.pm | 236 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UKCouncils.pm | 6 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Comment.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/Problem.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/User.pm | 6 | ||||
-rw-r--r-- | perllib/FixMyStreet/Map/IsleOfWight.pm | 63 | ||||
-rw-r--r-- | perllib/FixMyStreet/SendReport/Triage.pm | 20 | ||||
-rwxr-xr-x | perllib/Open311/PostServiceRequestUpdates.pm | 10 |
15 files changed, 648 insertions, 24 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 5373220a7..c2c4e7588 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -678,6 +678,9 @@ sub categories_for_point : Private { shift @{$c->stash->{category_options}} if @{$c->stash->{category_options}}; $c->stash->{categories_hash} = { map { $_->category => 1 } @{$c->stash->{category_options}} }; + + $c->forward('/admin/triage/setup_categories'); + } sub alerts_for_report : Private { diff --git a/perllib/FixMyStreet/App/Controller/Admin/Triage.pm b/perllib/FixMyStreet/App/Controller/Admin/Triage.pm new file mode 100644 index 000000000..385248cd1 --- /dev/null +++ b/perllib/FixMyStreet/App/Controller/Admin/Triage.pm @@ -0,0 +1,163 @@ +package FixMyStreet::App::Controller::Admin::Triage; +use Moose; +use namespace::autoclean; + +BEGIN { extends 'Catalyst::Controller'; } + +=head1 NAME + +FixMyStreet::App::Controller::Admin::Triage - Catalyst Controller + +=head1 DESCRIPTION + +Admin pages for triaging reports. + +This allows reports to be triaged before being sent to the council. It works +by having a set of categories with a send_method of Triage which sets the report +state to 'for_triage'. Any reports with the state are then show on '/admin/triage' +which is available to users with the 'triage' permission. + +Clicking on reports on this list will then allow a user to change the category of +the report to one that has an alternative send method, which will trigger the report +to be resent. + +In order for this to work additional work needs to be done to the cobrand to only +display triageable categories to the user. + +=head1 METHODS + +=cut + +sub auto : Private { + my ( $self, $c ) = @_; + + unless ( $c->user->has_body_permission_to('triage') ) { + $c->detach('/page_error_403_access_denied', []); + } +} + +sub index : Path : Args(0) { + my ( $self, $c ) = @_; + + # default sort to oldest + unless ( $c->get_param('sort') ) { + $c->set_param('sort', 'created-asc'); + } + $c->stash->{body} = $c->forward('/reports/body_find', [ $c->cobrand->council_area ]); + $c->forward( 'stash_report_filter_status' ); + $c->forward( '/reports/load_and_group_problems' ); + $c->stash->{page} = 'reports'; # So the map knows to make clickable pins + + if ($c->get_param('ajax')) { + my $ajax_template = $c->stash->{ajax_template} || 'reports/_problem-list.html'; + $c->detach('/reports/ajax', [ $ajax_template ]); + } + + my @categories = $c->stash->{body}->contacts->not_deleted->search( undef, { + columns => [ 'id', 'category', 'extra' ], + distinct => 1, + order_by => [ 'category' ], + } )->all; + $c->stash->{filter_categories} = \@categories; + $c->stash->{filter_category} = { map { $_ => 1 } $c->get_param_list('filter_category', 1) }; + my $pins = $c->stash->{pins} || []; + + my %map_params = ( + latitude => @$pins ? $pins->[0]{latitude} : 0, + longitude => @$pins ? $pins->[0]{longitude} : 0, + area => [ $c->stash->{wards} ? map { $_->{id} } @{$c->stash->{wards}} : keys %{$c->stash->{body}->areas} ], + any_zoom => 1, + ); + FixMyStreet::Map::display_map( + $c, %map_params, pins => $pins, + ); +} + +sub stash_report_filter_status : Private { + my ( $self, $c ) = @_; + $c->stash->{filter_problem_states} = { 'for triage' => 1 }; + return 1; +} + +sub setup_categories : Private { + my ( $self, $c ) = @_; + + if ( $c->stash->{problem}->state eq 'for triage' ) { + $c->stash->{holding_options} = [ grep { $_->send_method && $_->send_method eq 'Triage' } @{$c->stash->{category_options}} ]; + $c->stash->{holding_categories} = { map { $_->category => 1 } @{$c->stash->{holding_options}} }; + $c->stash->{end_options} = [ grep { !$_->send_method || $_->send_method ne 'Triage' } @{$c->stash->{category_options}} ]; + $c->stash->{end_categories} = { map { $_->category => 1 } @{$c->stash->{end_options}} }; + delete $c->stash->{categories_hash}; + my %category_groups = (); + for my $category (@{$c->stash->{end_options}}) { + my $group = $category->{group} // $category->get_extra_metadata('group') // ['']; + # this could be an array ref or a string + my @groups = ref $group eq 'ARRAY' ? @$group : ($group); + push( @{$category_groups{$_}}, $category ) for @groups; + } + my @category_groups = (); + for my $group ( grep { $_ ne _('Other') } sort keys %category_groups ) { + push @category_groups, { name => $group, categories => $category_groups{$group} }; + } + $c->stash->{end_groups} = \@category_groups; + } + + return 1; +} + +sub update : Private { + my ($self, $c) = @_; + + my $problem = $c->stash->{problem}; + + my $current_category = $problem->category; + my $new_category = $c->get_param('category'); + + my $changed = $c->forward('/admin/report_edit_category', [ $problem, 1 ] ); + + if ( $changed ) { + $c->stash->{problem}->update( { state => 'confirmed' } ); + $c->forward( '/admin/log_edit', [ $problem->id, 'problem', 'triage' ] ); + + my $name = $c->user->moderating_user_name; + my $extra = { is_superuser => 1 }; + if ($c->user->from_body) { + delete $extra->{is_superuser}; + $extra->{is_body_user} = $c->user->from_body->id; + } + + $extra->{triage_report} = 1; + $extra->{holding_category} = $current_category; + $extra->{new_category} = $new_category; + + my $timestamp = \'current_timestamp'; + my $comment = $problem->add_to_comments( { + text => "Report triaged from $current_category to $new_category", + created => $timestamp, + confirmed => $timestamp, + user_id => $c->user->id, + name => $name, + mark_fixed => 0, + anonymous => 0, + state => 'confirmed', + problem_state => $problem->state, + extra => $extra, + whensent => \'current_timestamp', + } ); + + my @alerts = FixMyStreet::DB->resultset('Alert')->search( { + alert_type => 'new_updates', + parameter => $problem->id, + confirmed => 1, + } ); + + for my $alert (@alerts) { + my $alerts_sent = FixMyStreet::DB->resultset('AlertSent')->find_or_create( { + alert_id => $alert->id, + parameter => $comment->id, + } ); + } + } +} + +1; diff --git a/perllib/FixMyStreet/App/Controller/Around.pm b/perllib/FixMyStreet/App/Controller/Around.pm index 203296c4d..ebb3d4839 100644 --- a/perllib/FixMyStreet/App/Controller/Around.pm +++ b/perllib/FixMyStreet/App/Controller/Around.pm @@ -234,12 +234,18 @@ sub check_and_stash_category : Private { my @list_of_names = map { $_->name } values %bodies; my $csv = Text::CSV->new(); $csv->combine(@list_of_names); + $c->stash->{bodies} = \@bodies; $c->{stash}->{list_of_names_as_string} = $csv->string; + my $where = { body_id => [ keys %bodies ], }; + + my $cobrand_where = $c->cobrand->call_hook('munge_around_category_where', $where ); + if ( $cobrand_where ) { + $where = $cobrand_where; + } + my @categories = $c->model('DB::Contact')->not_deleted->search( - { - body_id => [ keys %bodies ], - }, + $where, { columns => [ 'category', 'extra' ], order_by => [ 'category' ], @@ -252,6 +258,7 @@ sub check_and_stash_category : Private { my $categories = [ $c->get_param_list('filter_category', 1) ]; my %valid_categories = map { $_ => 1 } grep { $_ && $categories_mapped{$_} } @$categories; $c->stash->{filter_category} = \%valid_categories; + $c->cobrand->call_hook('munge_around_filter_category_list'); } sub map_features : Private { @@ -312,6 +319,7 @@ sub ajax : Path('/ajax') { my %valid_categories = map { $_ => 1 } $c->get_param_list('filter_category', 1); $c->stash->{filter_category} = \%valid_categories; + $c->cobrand->call_hook('munge_around_filter_category_list'); $c->forward('map_features', [ { bbox => $c->stash->{bbox} } ]); $c->forward('/reports/ajax', [ 'around/on_map_list_items.html' ]); diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 9b90da161..eb6050fde 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -86,7 +86,7 @@ sub display :PathPart('') :Chained('id') :Args(0) { $c->forward( 'format_problem_for_display' ); my $permissions = $c->stash->{_permissions} ||= $c->forward( 'check_has_permission_to', - [ qw/report_inspect report_edit_category report_edit_priority report_mark_private/ ] ); + [ qw/report_inspect report_edit_category report_edit_priority report_mark_private triage/ ] ); if (any { $_ } values %$permissions) { $c->stash->{template} = 'report/inspect.html'; $c->forward('inspect'); @@ -396,7 +396,14 @@ sub inspect : Private { $c->stash->{max_detailed_info_length} = $c->cobrand->max_detailed_info_length; - if ( $c->get_param('save') ) { + if ( $c->get_param('triage') ) { + $c->forward('/auth/check_csrf_token'); + $c->forward('/admin/triage/update'); + my $redirect_uri = $c->uri_for( '/admin/triage' ); + $c->log->debug( "Redirecting to: " . $redirect_uri ); + $c->res->redirect( $redirect_uri ); + } + elsif ( $c->get_param('save') ) { $c->forward('/auth/check_csrf_token'); my $valid = 1; diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm index 554fbc3b7..9b7a925b8 100644 --- a/perllib/FixMyStreet/App/Controller/Report/New.pm +++ b/perllib/FixMyStreet/App/Controller/Report/New.pm @@ -261,15 +261,20 @@ sub category_extras_ajax : Path('category_extras') : Args(0) { sub by_category_ajax_data : Private { my ($self, $c, $type, $category) = @_; - my $bodies = $c->forward('contacts_to_bodies', [ $category ]); - my $list_of_names = [ map { $_->name } ($category ? @$bodies : values %{$c->stash->{bodies_to_list}}) ]; - my $vars = { - $category ? (list_of_names => $list_of_names) : (), - }; + my @bodies; + my $bodies = []; + my $vars = {}; + if ($category) { + $bodies = $c->forward('contacts_to_bodies', [ $category ]); + @bodies = @$bodies; + $vars->{list_of_names} = [ map { $_->cobrand_name } @bodies ]; + } else { + @bodies = values %{$c->stash->{bodies_to_list}}; + } my $non_public = $c->stash->{non_public_categories}->{$category}; my $body = { - bodies => $list_of_names, + bodies => [ map { $_->name } @bodies ], $non_public ? ( non_public => JSON->true ) : (), }; @@ -743,7 +748,7 @@ sub setup_categories_and_bodies : Private { push @category_options, $seen{_('Other')} if $seen{_('Other')}; } - $c->cobrand->call_hook(munge_category_list => \@category_options, \@contacts, \%category_extras); + $c->cobrand->call_hook(munge_report_new_category_list => \@category_options, \@contacts, \%category_extras); # put results onto stash for display $c->stash->{bodies} = \%bodies; diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm index d8d52a2d9..741cbb60f 100644 --- a/perllib/FixMyStreet/App/Controller/Reports.pm +++ b/perllib/FixMyStreet/App/Controller/Reports.pm @@ -165,10 +165,13 @@ sub ward : Path : Args(2) { $c->stash->{stats} = $c->cobrand->get_report_stats(); my @categories = $c->stash->{body}->contacts->not_deleted->search( undef, { - columns => [ 'id', 'category', 'extra' ], + columns => [ 'id', 'category', 'extra', 'body_id', 'send_method' ], distinct => 1, order_by => [ 'category' ], } )->all; + + $c->cobrand->call_hook('munge_reports_category_list', \@categories); + $c->stash->{filter_categories} = \@categories; $c->stash->{filter_category} = { map { $_ => 1 } $c->get_param_list('filter_category', 1) }; diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm index e5327b084..38e9e09a0 100644 --- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm +++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm @@ -7,6 +7,7 @@ use warnings; use mySociety::Random; use constant COUNCIL_ID_BROMLEY => 2482; +use constant COUNCIL_ID_ISLEOFWIGHT => 2636; sub on_map_default_status { return 'open'; } @@ -37,13 +38,116 @@ sub restriction { return {}; } -sub munge_category_list { +sub munge_around_category_where { + my ($self, $where) = @_; + + my $user = $self->{c}->user; + my @iow = grep { $_->name eq 'Isle of Wight Council' } @{ $self->{c}->stash->{bodies} }; + return unless @iow; + + # display all the categories on Isle of Wight at the moment as there's no way to + # do the expand bit later as we fetch it using ajax which uses a bounding box so + # can't determine the body + $where->{send_method} = [ { '!=' => 'Triage' }, undef ]; + return $where; +} + +sub munge_reports_categories_list { + my ($self, $categories) = @_; + + my %bodies = map { $_->body->name => $_->body } @$categories; + if ( $bodies{'Isle of Wight Council'} ) { + my $user = $self->{c}->user; + my $b = $bodies{'Isle of Wight Council'}; + + if ( $user && ( $user->is_superuser || $user->belongs_to_body( $b->id ) ) ) { + @$categories = grep { !$_->send_method || $_->send_method ne 'Triage' } @$categories; + return @$categories; + } + + @$categories = grep { $_->send_method && $_->send_method eq 'Triage' } @$categories; + return @$categories; + } +} + +sub munge_report_new_category_list { my ($self, $options, $contacts, $extras) = @_; # No TfL Traffic Lights category in Hounslow - my %bodies = map { $_->body->name => 1 } @$contacts; - return unless $bodies{'Hounslow Borough Council'}; - @$options = grep { ($_->{category} || $_->category) !~ /^Traffic lights$/i } @$options; + my %bodies = map { $_->body->name => $_->body } @$contacts; + if ( $bodies{'Hounslow Borough Council'} ) { + @$options = grep { ($_->{category} || $_->category) !~ /^Traffic lights$/i } @$options; + } + + if ( $bodies{'Isle of Wight Council'} ) { + my $user = $self->{c}->user; + if ( $user && ( $user->is_superuser || $user->belongs_to_body( $bodies{'Isle of Wight Council'}->id ) ) ) { + @$contacts = grep { !$_->send_method || $_->send_method ne 'Triage' } @$contacts; + my $seen = { map { $_->category => 1 } @$contacts }; + @$options = grep { my $c = ($_->{category} || $_->category); $c =~ 'Pick a category' || $seen->{ $c } } @$options; + return; + } + + @$contacts = grep { $_->send_method && $_->send_method eq 'Triage' } @$contacts; + my $seen = { map { $_->category => 1 } @$contacts }; + @$options = grep { my $c = ($_->{category} || $_->category); $c =~ 'Pick a category' || $seen->{ $c } } @$options; + } +} + +sub munge_load_and_group_problems { + my ($self, $where, $filter) = @_; + + return unless $where->{category} && $self->{c}->stash->{body}->name eq 'Isle of Wight Council'; + + my $cat_names = $self->expand_triage_cat_list($where->{category}); + + $where->{category} = $cat_names; + my $problems = $self->problems->search($where, $filter); + return $problems; +} + +sub expand_triage_cat_list { + my ($self, $categories) = @_; + + my $b = $self->{c}->stash->{body}; + + my $all_cats = $self->{c}->model('DB::Contact')->not_deleted->search( + { + body_id => $b->id, + send_method => [{ '!=', 'Triage'}, undef] + } + ); + + my %group_to_category; + while ( my $cat = $all_cats->next ) { + next unless $cat->get_extra_metadata('group'); + my $groups = $cat->get_extra_metadata('group'); + $groups = ref $groups eq 'ARRAY' ? $groups : [ $groups ]; + for my $group ( @$groups ) { + $group_to_category{$group} //= []; + push @{ $group_to_category{$group} }, $cat->category; + } + } + + my $cats = $self->{c}->model('DB::Contact')->not_deleted->search( + { + body_id => $b->id, + category => $categories + } + ); + + my @cat_names; + while ( my $cat = $cats->next ) { + if ( $cat->send_method && $cat->send_method eq 'Triage' ) { + # include the category itself + push @cat_names, $cat->category; + push @cat_names, @{ $group_to_category{$cat->category} } if $group_to_category{$cat->category}; + } else { + push @cat_names, $cat->category; + } + } + + return \@cat_names; } sub title_list { diff --git a/perllib/FixMyStreet/Cobrand/IsleOfWight.pm b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm new file mode 100644 index 000000000..49356e3ae --- /dev/null +++ b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm @@ -0,0 +1,236 @@ +package FixMyStreet::Cobrand::IsleOfWight; +use parent 'FixMyStreet::Cobrand::Whitelabel'; + +use strict; +use warnings; + +sub council_area_id { 2636 } +sub council_area { 'Isle of Wight' } +sub council_name { 'Island Roads' } +sub council_url { 'isleofwight' } +sub all_reports_single_body { { name => "Isle of Wight Council" } } +sub link_to_council_cobrand { "Island Roads" } + +sub enter_postcode_text { + my ($self) = @_; + return 'Enter an ' . $self->council_area . ' postcode, or street name and area'; +} + +sub admin_user_domain { ('islandroads.com') } + +sub on_map_default_status { 'open' } + +sub send_questionnaires { 0 } + +sub report_sent_confirmation_email { 'external_id' } + +sub map_type { 'IsleOfWight' } + +sub disambiguate_location { + my $self = shift; + my $string = shift; + + return { + %{ $self->SUPER::disambiguate_location() }, + centre => '50.675761,-1.296571', + bounds => [ 50.574653, -1.591732, 50.767567, -1.062957 ], + }; +} + +sub updates_disallowed { + my ($self, $problem) = @_; + + my $c = $self->{c}; + return 0 if $c->user_exists && $c->user->id eq $problem->user->id; + return 1; +} + +sub get_geocoder { 'OSM' } + +sub open311_pre_send { + my ($self, $row, $open311) = @_; + + return unless $row->extra; + my $extra = $row->get_extra_fields; + if (@$extra) { + @$extra = grep { $_->{name} ne 'urgent' } @$extra; + $row->set_extra_fields(@$extra); + } +} + +sub open311_config { + my ($self, $row, $h, $params) = @_; + + my $extra = $row->get_extra_fields; + push @$extra, + { name => 'report_url', + value => $h->{url} }, + { name => 'title', + value => $row->title }, + { name => 'description', + value => $row->detail }; + + $row->set_extra_fields(@$extra); +} + +# Make sure fetched report description isn't shown. +sub filter_report_description { "" } + +sub open311_munge_update_params { + my ($self, $params, $comment, $body) = @_; + + if ($comment->mark_fixed) { + $params->{description} = "[The customer indicated that this issue had been fixed]\n\n" . $params->{description}; + } + + if ( $comment->get_extra_metadata('triage_report') ) { + $params->{description} = "Triaged by " . $comment->user->name . ' (' . $comment->user->email . "). " . $params->{description}; + } + + $params->{description} = "FMS-Update: " . $params->{description}; +} + +# this handles making sure the user sees the right categories on the new report page +sub munge_reports_category_list { + my ($self, $categories) = @_; + + my $user = $self->{c}->user; + my %bodies = map { $_->body->name => $_->body } @$categories; + my $b = $bodies{'Isle of Wight Council'}; + + if ( $user && ( $user->is_superuser || $user->belongs_to_body( $b->id ) ) ) { + @$categories = grep { !$_->send_method || $_->send_method ne 'Triage' } @$categories; + return @$categories; + } + + @$categories = grep { $_->send_method && $_->send_method eq 'Triage' } @$categories; + return @$categories; +} + +sub munge_report_new_category_list { + my ($self, $options, $contacts, $extras) = @_; + + my $user = $self->{c}->user; + my %bodies = map { $_->body->name => $_->body } @$contacts; + my $b = $bodies{'Isle of Wight Council'}; + + if ( $user && ( $user->is_superuser || $user->belongs_to_body( $b->id ) ) ) { + @$contacts = grep { !$_->send_method || $_->send_method ne 'Triage' } @$contacts; + my $seen = { map { $_->category => 1 } @$contacts }; + @$options = grep { my $c = ($_->{category} || $_->category); $c =~ 'Pick a category' || $seen->{ $c } } @$options; + return; + } + + @$contacts = grep { $_->send_method && $_->send_method eq 'Triage' } @$contacts; + my $seen = { map { $_->category => 1 } @$contacts }; + @$options = grep { my $c = ($_->{category} || $_->category); $c =~ 'Pick a category' || $seen->{ $c } } @$options; +} + +sub munge_around_category_where { + my ($self, $where) = @_; + + my $user = $self->{c}->user; + my $b = $self->{c}->model('DB::Body')->for_areas( $self->council_area_id )->first; + if ( $user && ( $user->is_superuser || $user->belongs_to_body( $b->id ) ) ) { + $where->{send_method} = [ { '!=' => 'Triage' }, undef ]; + return $where; + } + + $where->{'send_method'} = 'Triage'; + return $where; +} + +sub munge_load_and_group_problems { + my ($self, $where, $filter) = @_; + + return unless $where->{category}; + + my $cat_names = $self->expand_triage_cat_list($where->{category}); + + $where->{category} = $cat_names; + my $problems = $self->problems->search($where, $filter); + return $problems; +} + +sub munge_around_filter_category_list { + my $self = shift; + + my $c = $self->{c}; + return unless $c->stash->{filter_category}; + + my $cat_names = $self->expand_triage_cat_list([ keys %{$c->stash->{filter_category}} ]); + $c->stash->{filter_category} = { map { $_ => 1 } @$cat_names }; +} + +# this assumes that each Triage category has the same name as a group +# and uses this to generate a list of categories that a triage category +# could be triaged to +sub expand_triage_cat_list { + my ($self, $categories) = @_; + + my $b = $self->{c}->model('DB::Body')->for_areas( $self->council_area_id )->first; + + my $all_cats = $self->{c}->model('DB::Contact')->not_deleted->search( + { + body_id => $b->id, + send_method => [{ '!=', 'Triage'}, undef] + } + ); + + my %group_to_category; + while ( my $cat = $all_cats->next ) { + next unless $cat->get_extra_metadata('group'); + my $groups = $cat->get_extra_metadata('group'); + $groups = ref $groups eq 'ARRAY' ? $groups : [ $groups ]; + for my $group ( @$groups ) { + $group_to_category{$group} //= []; + push @{ $group_to_category{$group} }, $cat->category; + } + } + + my $cats = $self->{c}->model('DB::Contact')->not_deleted->search( + { + body_id => $b->id, + category => $categories + } + ); + + my @cat_names; + while ( my $cat = $cats->next ) { + if ( $cat->send_method eq 'Triage' ) { + # include the category itself + push @cat_names, $cat->category; + push @cat_names, @{ $group_to_category{$cat->category} } if $group_to_category{$cat->category}; + } else { + push @cat_names, $cat->category; + } + } + + return \@cat_names; +} + +sub open311_get_update_munging { + my ($self, $comment) = @_; + + # If we've received an update via Open311 that's closed + # or fixed the report, also close it to updates. + $comment->problem->set_extra_metadata(closed_updates => 1) + if !$comment->problem->is_open; +} + +sub admin_pages { + my $self = shift; + my $pages = $self->next::method(); + $pages->{triage} = [ undef, undef ]; + return $pages; +} + +sub available_permissions { + my $self = shift; + + my $perms = $self->next::method(); + $perms->{Problems}->{triage} = "Triage reports"; + + return $perms; +} +1; diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm index 9f4610143..5f45609bb 100644 --- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm +++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm @@ -179,7 +179,11 @@ sub reports_body_check { } # We want to make sure we're only on our page. - unless ( $self->council_name =~ /^\Q$code\E/ ) { + my $council_name = $self->council_name; + if (my $override = $self->all_reports_single_body) { + $council_name = $override->{name}; + } + unless ( $council_name =~ /^\Q$code\E/ ) { $c->res->redirect( 'https://www.fixmystreet.com' . $c->req->uri->path_query, 301 ); $c->detach(); } diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm index 39f446549..1ffcc7b40 100644 --- a/perllib/FixMyStreet/DB/Result/Comment.pm +++ b/perllib/FixMyStreet/DB/Result/Comment.pm @@ -231,6 +231,8 @@ sub meta_line { $body = "$body <img src='/cobrands/greenwich/favicon.png' alt=''>"; } elsif ($body eq 'Hounslow Borough Council') { $body = 'Hounslow Highways'; + } elsif ($body eq 'Isle of Wight Council') { + $body = 'Island Roads'; } } my $cobrand_always_view_body_user = $c->cobrand->call_hook("always_view_body_contribute_details"); diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index 8159d7251..08b768719 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -751,7 +751,7 @@ sub defect_types { # Note: this only makes sense when called on a problem that has been sent! sub can_display_external_id { my $self = shift; - if ($self->external_id && $self->to_body_named('Oxfordshire|Lincolnshire')) { + if ($self->external_id && $self->to_body_named('Oxfordshire|Lincolnshire|Isle of Wight')) { return 1; } return 0; diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index 51f959e0e..85fdc790b 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -317,7 +317,11 @@ sub body { sub moderating_user_name { my $self = shift; - return $self->body || _('an administrator'); + my $body = $self->body; + if ( $body && $body eq 'Isle of Wight Council' ) { + $body = 'Island Roads'; + } + return $body || _('an administrator'); } =head2 belongs_to_body diff --git a/perllib/FixMyStreet/Map/IsleOfWight.pm b/perllib/FixMyStreet/Map/IsleOfWight.pm new file mode 100644 index 000000000..2316e2939 --- /dev/null +++ b/perllib/FixMyStreet/Map/IsleOfWight.pm @@ -0,0 +1,63 @@ +# FixMyStreet:Map::IsleOfWight +# IsleOfWight use their own tiles on their cobrand + +package FixMyStreet::Map::IsleOfWight; +use base 'FixMyStreet::Map::UKCouncilWMTS'; + +use strict; + +sub default_zoom { 7; } + +sub urls { [ 'https://gis.ringway.co.uk/server/rest/services/Hosted/IOW_OS/MapServer/WMTS/tile' ] } + +sub layer_names { [ 'Hosted_IOW_OS' ] } + +sub scales { + my $self = shift; + my @scales = ( + # The first 5 levels don't load and are really zoomed-out, so + # they're not included here. + # '600000', + # '500000', + # '400000', + # '300000', + # '200000', + '100000', + '75000', + '50000', + '25000', + '10000', + '8000', + '6000', + '4000', + '2000', + '1000', + '400', + ); + return @scales; +} + +sub zoom_parameters { + my $self = shift; + my $params = { + zoom_levels => scalar $self->scales, + default_zoom => $self->default_zoom, + min_zoom_level => 0, + id_offset => 5, # see note above about zoom layers we've skipped + }; + return $params; +} + +sub copyright { + return 'Contains Ordnance Survey data © Crown copyright and database rights 2019 OS 100019229. Use of this data is subject to <a href="/about/mapterms">terms and conditions</a>.'; +} + + +sub map_javascript { [ + '/vendor/OpenLayers/OpenLayers.wmts.js', + '/js/map-OpenLayers.js', + '/js/map-wmts-base.js', + '/js/map-wmts-isleofwight.js', +] } + +1; diff --git a/perllib/FixMyStreet/SendReport/Triage.pm b/perllib/FixMyStreet/SendReport/Triage.pm new file mode 100644 index 000000000..38341f3ff --- /dev/null +++ b/perllib/FixMyStreet/SendReport/Triage.pm @@ -0,0 +1,20 @@ +package FixMyStreet::SendReport::Triage; + +use Moo; + +BEGIN { extends 'FixMyStreet::SendReport'; } + +sub send { + my $self = shift; + my ( $row, $h ) = @_; + + $row->update({ + state => 'for triage' + }); + + $self->success(1); + + return 0; +} + +1; diff --git a/perllib/Open311/PostServiceRequestUpdates.pm b/perllib/Open311/PostServiceRequestUpdates.pm index 1f080b168..14bebfcb7 100755 --- a/perllib/Open311/PostServiceRequestUpdates.pm +++ b/perllib/Open311/PostServiceRequestUpdates.pm @@ -14,6 +14,7 @@ use Open311; use constant SEND_METHOD_OPEN311 => 'Open311'; has verbose => ( is => 'ro', default => 0 ); +has current_open311 => ( is => 'rw' ); sub send { my $self = shift; @@ -26,6 +27,7 @@ sub send { while ( my $body = $bodies->next ) { my $cobrand = $body->get_cobrand_handler; next if $cobrand && $cobrand->call_hook('open311_post_update_skip'); + $self->current_open311(Open311->new($self->open311_params($body))); $self->process_body($body); } } @@ -51,8 +53,6 @@ sub open311_params { sub process_body { my ($self, $body) = @_; - my $o = Open311->new( $self->open311_params($body) ); - my $comments = FixMyStreet::DB->resultset('Comment')->to_body($body)->search( { 'me.whensent' => undef, 'me.external_id' => undef, @@ -82,12 +82,14 @@ sub process_body { next if !$self->verbose && $comment->send_fail_count && retry_timeout($comment); - $self->process_update($body, $o, $comment, $cobrand); + $self->process_update($body, $comment, $cobrand); } } sub process_update { - my ($self, $body, $o, $comment, $cobrand) = @_; + my ($self, $body, $comment, $cobrand) = @_; + + my $o = $self->current_open311; $cobrand->call_hook(open311_pre_send => $comment, $o); |