aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--docs/install/ami.md6
-rw-r--r--perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm54
-rw-r--r--perllib/FixMyStreet/App.pm21
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm13
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin/Users.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Moderate.pm2
-rw-r--r--perllib/FixMyStreet/App/Controller/Photo.pm33
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm5
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm2
-rw-r--r--perllib/FixMyStreet/App/Model/PhotoSet.pm7
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm2
-rw-r--r--perllib/FixMyStreet/Roles/PhotoSet.pm7
-rw-r--r--t/app/controller/admin/templates.t24
-rw-r--r--t/app/controller/photo.t71
-rw-r--r--t/app/model/user.t16
-rw-r--r--templates/web/base/admin/report_edit.html5
-rw-r--r--templates/web/base/admin/template_edit.html4
-rw-r--r--templates/web/fixmystreet.com/report/new/roads_message.html16
-rw-r--r--templates/web/northamptonshire/report/new/roads_message.html16
-rw-r--r--templates/web/zurich/admin/template_edit.html3
-rw-r--r--web/cobrands/buckinghamshire/assets.js129
-rw-r--r--web/cobrands/fixmystreet-uk-councils/roadworks.js2
-rw-r--r--web/cobrands/fixmystreet/assets.js191
-rw-r--r--web/cobrands/lincolnshire/assets.js5
-rw-r--r--web/cobrands/lincolnshire/roadworks.js15
-rw-r--r--web/cobrands/northamptonshire/assets.js156
-rw-r--r--web/cobrands/oxfordshire/assets.js31
-rw-r--r--web/cobrands/sass/_admin.scss10
29 files changed, 525 insertions, 325 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dae414090..d1771247c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,8 @@
## Releases
* Unreleased
+ - Bugfixes:
+ - Prevent creation of two templates with same title.
- Development improvements:
- Upgrade the underlying framework and a number of other packages.
diff --git a/docs/install/ami.md b/docs/install/ami.md
index fd283945a..5b7c31e0a 100644
--- a/docs/install/ami.md
+++ b/docs/install/ami.md
@@ -24,9 +24,9 @@ for a year](http://aws.amazon.com/free/).
### Using our pre-built AMI
The AMI we've prepared for you can be found in the **EU West (Ireland)**
-region, with the ID `ami-05386aa7b2b4faee9` and name "FixMyStreet installation
-full 2018-12-21". You can launch an instance based on that AMI with
-[this link](https://console.aws.amazon.com/ec2/home?region=eu-west-1#launchAmi=ami-05386aa7b2b4faee9).
+region, with the ID `ami-0351dd8e5e3bfb51d` and name "FixMyStreet installation
+full 2019-05-03". You can launch an instance based on that AMI with
+[this link](https://console.aws.amazon.com/ec2/home?region=eu-west-1#launchAmi=ami-0351dd8e5e3bfb51d).
This AMI is based on the [latest tagged release](https://github.com/mysociety/fixmystreet/releases)
and contains everything you need to get a base install up and running.
diff --git a/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm b/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm
new file mode 100644
index 000000000..240f4b1de
--- /dev/null
+++ b/perllib/Catalyst/Authentication/Store/FixMyStreetUser.pm
@@ -0,0 +1,54 @@
+package Catalyst::Authentication::Store::FixMyStreetUser;
+
+use Moose;
+use namespace::autoclean;
+extends 'Catalyst::Authentication::Store::DBIx::Class::User';
+
+use Carp;
+use Try::Tiny;
+
+sub AUTOLOAD {
+ my $self = shift;
+ (my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
+ return if $method eq "DESTROY";
+
+ if (my $code = $self->_user->can($method)) {
+ return $self->_user->$code(@_);
+ }
+ elsif (my $accessor =
+ try { $self->_user->result_source->column_info($method)->{accessor} }) {
+ return $self->_user->$accessor(@_);
+ } else {
+ croak sprintf("Can't locate object method '%s'", $method);
+ }
+}
+
+__PACKAGE__->meta->make_immutable(inline_constructor => 0);
+
+1;
+__END__
+
+=head1 NAME
+
+Catalyst::Authentication::Store::FixMyStreetUser - The backing user
+class for the Catalyst::Authentication::Store::DBIx::Class storage
+module, adjusted to die on unknown lookups.
+
+=head1 DESCRIPTION
+
+The Catalyst::Authentication::Store::FixMyStreetUser class implements user
+storage connected to an underlying DBIx::Class schema object.
+
+=head1 SUBROUTINES / METHODS
+
+=head2 AUTOLOAD
+
+Delegates method calls to the underlying user row.
+Unlike the default, dies if an unknown method is called.
+
+=head1 LICENSE
+
+Copyright (c) 2007-2019. All rights reserved. This program is free software;
+you can redistribute it and/or modify it under the same terms as Perl itself.
+
+=cut
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index aa8d04988..27a5a4580 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -33,6 +33,12 @@ extends 'Catalyst';
our $VERSION = '0.01';
+my $store = { # Catalyst::Authentication::Store::DBIx::Class
+ class => 'DBIx::Class',
+ user_model => 'DB::User',
+ store_user_class => 'Catalyst::Authentication::Store::FixMyStreetUser',
+};
+
__PACKAGE__->config(
# Use REQUEST_URI, not PATH_INFO, to infer path. This fixes an issue
@@ -80,20 +86,14 @@ __PACKAGE__->config(
},
],
},
- store => { # Catalyst::Authentication::Store::DBIx::Class
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
no_password => { # use post confirm etc
credential => { # Catalyst::Authentication::Credential::Password
class => 'Password',
password_type => 'none',
},
- store => { # Catalyst::Authentication::Store::DBIx::Class
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
access_token => {
use_session => 0,
@@ -103,10 +103,7 @@ __PACKAGE__->config(
# This means the token has to be 18 characters long (as generated by AuthToken)
token_lookup => { like => "%access_token,T18:TOKEN,%" },
},
- store => {
- class => 'DBIx::Class',
- user_model => 'DB::User',
- },
+ store => $store,
},
},
);
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index 2f4669456..6167a16f5 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -535,8 +535,8 @@ sub report_edit : Path('report_edit') : Args(1) {
$self->remove_photo($c, $problem, $remove_photo_param);
}
- if ($problem->state eq 'hidden') {
- $problem->get_photoset->delete_cached;
+ if ($problem->state eq 'hidden' || $problem->non_public) {
+ $problem->get_photoset->delete_cached(plus_updates => 1);
}
if ( $problem->is_visible() and $old_state eq 'unconfirmed' ) {
@@ -782,6 +782,15 @@ sub template_edit : Path('templates') : Args(2) {
}
$template->title( $c->get_param('title') );
+ my $query = { title => $template->title };
+ if ($template->in_storage) {
+ $query->{id} = { '!=', $template->id };
+ }
+ if ($c->stash->{body}->response_templates->search($query)->count) {
+ $c->stash->{errors} ||= {};
+ $c->stash->{errors}->{title} = _("There is already a template with that title.");
+ }
+
$template->text( $c->get_param('text') );
$template->state( $c->get_param('state') );
$template->external_status_code( $c->get_param('external_status_code') );
diff --git a/perllib/FixMyStreet/App/Controller/Admin/Users.pm b/perllib/FixMyStreet/App/Controller/Admin/Users.pm
index bcbc808ed..6af4ae831 100644
--- a/perllib/FixMyStreet/App/Controller/Admin/Users.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin/Users.pm
@@ -497,7 +497,7 @@ sub user_hide_everywhere : Private {
my ( $self, $c, $user ) = @_;
my $problems = $user->problems->search({ state => { '!=' => 'hidden' } });
while (my $problem = $problems->next) {
- $problem->get_photoset->delete_cached;
+ $problem->get_photoset->delete_cached(plus_updates => 1);
$problem->update({ state => 'hidden' });
}
my $updates = $user->comments->search({ state => { '!=' => 'hidden' } });
diff --git a/perllib/FixMyStreet/App/Controller/Moderate.pm b/perllib/FixMyStreet/App/Controller/Moderate.pm
index 22869d531..f71698e84 100644
--- a/perllib/FixMyStreet/App/Controller/Moderate.pm
+++ b/perllib/FixMyStreet/App/Controller/Moderate.pm
@@ -214,7 +214,7 @@ sub report_moderate_hide : Private {
if ($c->get_param('problem_hide')) {
$problem->update({ state => 'hidden' });
- $problem->get_photoset->delete_cached;
+ $problem->get_photoset->delete_cached(plus_updates => 1);
$c->res->redirect( '/' ); # Go directly to front-page
$c->detach( 'report_moderate_audit', ['hide'] ); # break chain here.
diff --git a/perllib/FixMyStreet/App/Controller/Photo.pm b/perllib/FixMyStreet/App/Controller/Photo.pm
index 7b536a292..d7a5b4bb3 100644
--- a/perllib/FixMyStreet/App/Controller/Photo.pm
+++ b/perllib/FixMyStreet/App/Controller/Photo.pm
@@ -39,6 +39,7 @@ sub during :LocalRegex('^(temp|fulltemp)\.([0-9a-f]{40}\.(?:jpeg|png|gif|tiff))$
$size = $size eq 'temp' ? 'default' : 'full';
my $photo = $photoset->get_image_data(size => $size, default => $c->cobrand->default_photo_resize);
+ $c->stash->{non_public} = 0;
$c->forward( 'output', [ $photo ] );
}
@@ -52,10 +53,11 @@ sub index :LocalRegex('^(c/)?([1-9]\d*)(?:\.(\d+))?(?:\.(full|tn|fp))?\.(?:jpeg|
my $item;
if ( $is_update ) {
($item) = $c->model('DB::Comment')->search( {
- id => $id,
- state => 'confirmed',
- photo => { '!=', undef },
- } );
+ 'me.id' => $id,
+ 'me.state' => 'confirmed',
+ 'problem.state' => [ FixMyStreet::DB::Result::Problem->visible_states() ],
+ 'me.photo' => { '!=', undef },
+ }, { prefetch => 'problem' });
} else {
($item) = $c->cobrand->problems->search( {
id => $id,
@@ -68,6 +70,19 @@ sub index :LocalRegex('^(c/)?([1-9]\d*)(?:\.(\d+))?(?:\.(full|tn|fp))?\.(?:jpeg|
$c->detach( 'no_photo' ) unless $c->cobrand->allow_photo_display($item, $photo_number); # Should only be for reports, not updates
+ my $problem = $is_update ? $item->problem : $item;
+ $c->stash->{non_public} = $problem->non_public;
+
+ if ($c->stash->{non_public}) {
+ my $body_ids = $problem->bodies_str_ids;
+ # Check permission
+ $c->detach('no_photo') unless $c->user_exists;
+ $c->detach('no_photo') unless $c->user->is_superuser
+ || $c->user->id == $problem->user->id
+ || $c->user->has_permission_to('report_inspect', $body_ids)
+ || $c->user->has_permission_to('report_mark_private', $body_ids);
+ }
+
my $photo;
$photo = $item->get_photoset
->get_image_data( num => $photo_number, size => $size, default => $c->cobrand->default_photo_resize )
@@ -80,10 +95,12 @@ sub output : Private {
my ( $self, $c, $photo ) = @_;
# Save to file
- path(FixMyStreet->path_to('web', 'photo', 'c'))->mkpath;
- my $out = FixMyStreet->path_to('web', $c->req->path);
- my $symlink_exists = $photo->{symlink} ? symlink($photo->{symlink}, $out) : undef;
- path($out)->spew_raw($photo->{data}) unless $symlink_exists;
+ if (!FixMyStreet->config('LOGIN_REQUIRED') && !$c->stash->{non_public}) {
+ path(FixMyStreet->path_to('web', 'photo', 'c'))->mkpath;
+ my $out = FixMyStreet->path_to('web', $c->req->path);
+ my $symlink_exists = $photo->{symlink} ? symlink($photo->{symlink}, $out) : undef;
+ path($out)->spew_raw($photo->{data}) unless $symlink_exists;
+ }
$c->res->content_type( $photo->{content_type} );
$c->res->body( $photo->{data} );
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 7f798f4f4..f2f411635 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -435,7 +435,7 @@ sub inspect : Private {
$problem->confirmed( \'current_timestamp' );
}
if ( $problem->state eq 'hidden' ) {
- $problem->get_photoset->delete_cached;
+ $problem->get_photoset->delete_cached(plus_updates => 1);
}
if ( $problem->state eq 'duplicate') {
if (my $duplicate_of = $c->get_param('duplicate_of')) {
@@ -477,6 +477,9 @@ sub inspect : Private {
}
$problem->non_public($c->get_param('non_public') ? 1 : 0);
+ if ($problem->non_public) {
+ $problem->get_photoset->delete_cached(plus_updates => 1);
+ }
if ( !$c->forward( '/admin/report_edit_location', [ $problem ] ) ) {
# New lat/lon isn't valid, show an error
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index b352b049e..fc5176a07 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -659,7 +659,7 @@ sub check_non_public_reports_permission : Private {
if ( $c->user_exists ) {
my $user_has_permission;
- if ( $c->user->is_super_user ) {
+ if ( $c->user->is_superuser ) {
$user_has_permission = 1;
} else {
my $body = $c->stash->{body};
diff --git a/perllib/FixMyStreet/App/Model/PhotoSet.pm b/perllib/FixMyStreet/App/Model/PhotoSet.pm
index 58b352c73..8621286b0 100644
--- a/perllib/FixMyStreet/App/Model/PhotoSet.pm
+++ b/perllib/FixMyStreet/App/Model/PhotoSet.pm
@@ -235,7 +235,7 @@ sub get_image_data {
}
sub delete_cached {
- my ($self) = @_;
+ my ($self, %params) = @_;
my $object = $self->object or return;
my $id = $object->id or return;
@@ -256,6 +256,11 @@ sub delete_cached {
unlink FixMyStreet->path_to(@dirs, "$id.$i$size.$type");
}
}
+
+ # Loop through all the updates as well if requested
+ if ($params{plus_updates}) {
+ $_->get_photoset->delete_cached() foreach $object->comments->all;
+ }
}
sub remove_images {
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index dae946816..4f7c1dc5f 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -158,7 +158,7 @@ sub _recent {
# Need to reattach schema so that confirmed column gets reinflated.
$probs->[0]->result_source->schema( $rs->result_source->schema ) if $probs->[0];
# Catch any cached ones since hidden
- $probs = [ grep { $_->photo && ! $_->is_hidden } @$probs ];
+ $probs = [ grep { $_->photo && ! $_->is_hidden && !$_->non_public } @$probs ];
} else {
$probs = [ $rs->search( $query, $attrs )->all ];
Memcached::set($key, $probs, _cache_timeout());
diff --git a/perllib/FixMyStreet/Roles/PhotoSet.pm b/perllib/FixMyStreet/Roles/PhotoSet.pm
index 4a40ef3f9..27a63bad5 100644
--- a/perllib/FixMyStreet/Roles/PhotoSet.pm
+++ b/perllib/FixMyStreet/Roles/PhotoSet.pm
@@ -38,15 +38,18 @@ sub photos {
my $id = $self->id;
my $typ = $self->result_source->name eq 'comment' ? 'c/' : '';
+ my $non_public = $self->result_source->name eq 'comment'
+ ? $self->problem->non_public : $self->non_public;
+
my @photos = map {
my $cachebust = substr($_, 0, 8);
# Some Varnish configurations (e.g. on mySociety infra) strip cookies from
# images, which means image requests will be redirected to the login page
- # if LOGIN_REQUIRED is set. To stop this happening, Varnish should be
+ # if e.g. LOGIN_REQUIRED is set. To stop this happening, Varnish should be
# configured to not strip cookies if the cookie_passthrough param is
# present, which this line ensures will be if LOGIN_REQUIRED is set.
my $extra = '';
- if (FixMyStreet->config('LOGIN_REQUIRED')) {
+ if (FixMyStreet->config('LOGIN_REQUIRED') || $non_public) {
$cachebust .= '&cookie_passthrough=1';
$extra = '?cookie_passthrough=1';
}
diff --git a/t/app/controller/admin/templates.t b/t/app/controller/admin/templates.t
index 0d4430cad..6944f4b04 100644
--- a/t/app/controller/admin/templates.t
+++ b/t/app/controller/admin/templates.t
@@ -66,6 +66,30 @@ subtest "response templates can be added" => sub {
is $oxfordshire->response_templates->count, 1, "Response template was added";
};
+subtest "but not another with the same title" => sub {
+ my $fields = {
+ title => "Report acknowledgement",
+ text => "Another report acknowledgement.",
+ auto_response => undef,
+ "contacts[".$oxfordshirecontact->id."]" => 1,
+ };
+ my $list_url = "/admin/templates/" . $oxfordshire->id;
+ $mech->get_ok( "$list_url/new" );
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, "$list_url/new", 'not redirected';
+ $mech->content_contains( 'Please correct the errors below' );
+ $mech->content_contains( 'There is already a template with that title.' );
+
+ my @ts = $oxfordshire->response_templates->all;
+ is @ts, 1, "No new response template was added";
+
+ my $url = "$list_url/" . $ts[0]->id;
+ $mech->get_ok($url);
+ $mech->submit_form_ok( { with_fields => $fields } );
+ is $mech->uri->path, $list_url, 'redirected';
+ is $oxfordshire->response_templates->count, 1, "No new response template was added";
+};
+
subtest "response templates are included on page" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ 'oxfordshire' ],
diff --git a/t/app/controller/photo.t b/t/app/controller/photo.t
index 842daa0dc..e1bf35fcf 100644
--- a/t/app/controller/photo.t
+++ b/t/app/controller/photo.t
@@ -13,7 +13,7 @@ my $mech = FixMyStreet::TestMech->new;
my $sample_file = path(__FILE__)->parent->child("sample.jpg");
ok $sample_file->exists, "sample file $sample_file exists";
-my $westminster = $mech->create_body_ok(2527, 'Liverpool City Council');
+my $body = $mech->create_body_ok(2527, 'Liverpool City Council');
subtest "Check multiple upload worked" => sub {
$mech->get_ok('/around');
@@ -112,4 +112,73 @@ subtest "Check photo uploading URL and endpoints work" => sub {
};
};
+subtest "Check no access to update photos on hidden reports" => sub {
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title');
+ my $update = $mech->create_comment_for_problem($report, $report->user, $report->name, 'Text', $report->anonymous, 'confirmed', 'confirmed', { photo => $report->photo });
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy( path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg') );
+
+ $mech->get_ok('/photo/c/' . $update->id . '.0.jpeg');
+
+ $report->update({ state => 'hidden' });
+ $report->get_photoset->delete_cached(plus_updates => 1);
+
+ my $res = $mech->get('/photo/c/' . $update->id . '.0.jpeg');
+ is $res->code, 404, 'got 404';
+ };
+};
+
+subtest 'non_public photos only viewable by correct people' => sub {
+ my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
+ path(FixMyStreet->path_to('web/photo'))->remove_tree({ keep_root => 1 });
+
+ my ($report) = $mech->create_problems_for_body(1, $body->id, 'Title', {
+ non_public => 1,
+ });
+
+ FixMyStreet::override_config {
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
+ }, sub {
+ my $image_path = path('t/app/controller/sample.jpg');
+ $image_path->copy( path($UPLOAD_DIR, '74e3362283b6ef0c48686fb0e161da4043bbcc97.jpeg') );
+
+ $mech->log_out_ok;
+ my $i = '/photo/' . $report->id . '.0.jpeg';
+ my $res = $mech->get($i);
+ is $res->code, 404, 'got 404';
+
+ $mech->log_in_ok('test@example.com');
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+ my $image_file = FixMyStreet->path_to("web$i");
+ ok !-e $image_file, 'File not cached out';
+
+ my $user = $mech->log_in_ok('someoneelse@example.com');
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $res = $mech->get($i);
+ is $res->code, 404, 'got 404';
+
+ $user->update({ from_body => $body });
+ $user->user_body_permissions->create({ body => $body, permission_type => 'report_inspect' });
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+
+ $user->update({ from_body => undef, is_superuser => 1 });
+ $i = '/photo/' . $report->id . '.0.jpeg';
+ $mech->get_ok($i);
+ };
+};
+
done_testing();
diff --git a/t/app/model/user.t b/t/app/model/user.t
index 5a9c898a2..cbc0fe6cf 100644
--- a/t/app/model/user.t
+++ b/t/app/model/user.t
@@ -1,5 +1,8 @@
use FixMyStreet::TestMech;
use FixMyStreet::DB;
+use Catalyst::Test 'FixMyStreet::App';
+use HTTP::Request::Common;
+use Test::Exception;
my $mech = FixMyStreet::TestMech->new();
$mech->log_in_ok('test@example.com');
@@ -63,9 +66,16 @@ FixMyStreet::override_config {
$mech->content_like(qr/may_show_name[^>c]*>/);
};
-END {
- done_testing();
-}
+subtest 'Check non-existent methods on user object die' => sub {
+ my $c = ctx_request(POST '/auth', { username => 'test@example.com', password_sign_in => 'secret' });
+ throws_ok(
+ sub { $c->user->is_super_user },
+ qr/Can't locate object method 'is_super_user'/,
+ 'attempt to call non-existent method'
+ );
+};
+
+done_testing();
sub create_update {
my ($problem, %params) = @_;
diff --git a/templates/web/base/admin/report_edit.html b/templates/web/base/admin/report_edit.html
index e38932d7f..a26a35c50 100644
--- a/templates/web/base/admin/report_edit.html
+++ b/templates/web/base/admin/report_edit.html
@@ -87,6 +87,11 @@ class="admin-offsite-link">[% problem.latitude %], [% problem.longitude %]</a>
<input type="submit" class="btn" name="mark_sent" value="[% loc('Mark as sent') %]">
[% END %]
</li>
+[% IF c.user.is_superuser AND problem.send_fail_count > 0 %]
+<li class="sm">[% loc('Send Fail Count:') %] [% problem.send_fail_count %]</li>
+<li class="sm">[% loc('Last failure:') %] [% PROCESS format_time time=problem.send_fail_timestamp %]</li>
+<li class="sm truncate_height">[% loc('Reason:') %] [% problem.send_fail_reason | html %]</li>
+[% END %]
<li class="sm">[% loc('Last update:') %] [% PROCESS format_time time=problem.lastupdate %]</li>
<li>[% loc('Alerts:') %] [% alert_count %]</li>
<li>[% loc('Service:') %] [% problem.service OR '<em>' _ loc('None') _ '</em>' %]</li>
diff --git a/templates/web/base/admin/template_edit.html b/templates/web/base/admin/template_edit.html
index 2945e36c5..87218c7dd 100644
--- a/templates/web/base/admin/template_edit.html
+++ b/templates/web/base/admin/template_edit.html
@@ -13,7 +13,9 @@
<p class="error">[% loc('Please correct the errors below') %]</p>
[% END %]
-
+ [% IF errors.title %]
+ <div class="form-error">[% errors.title %]</div>
+ [% END %]
<div class="admin-hint">
<p>
[% loc('This is a <strong>private</strong> name for this template so you can identify it when updating reports or editing in the admin.') %]
diff --git a/templates/web/fixmystreet.com/report/new/roads_message.html b/templates/web/fixmystreet.com/report/new/roads_message.html
index f6a5d903a..6d1243354 100644
--- a/templates/web/fixmystreet.com/report/new/roads_message.html
+++ b/templates/web/fixmystreet.com/report/new/roads_message.html
@@ -13,20 +13,10 @@
</p>
</div>
<div id="js-not-a-road" class="hidden js-responsibility-message">
- <p>The location you have selected doesn't appear to be on a road.</p>
- <p>Please select a road on which to make a report.</p>
+ <p>The location you have selected doesn't appear to be on <span class="js-roads-asset" data-original="a road">a road</span>.</p>
+ <p>Please select <span class="js-roads-asset" data-original="a road">a road</span> on which to make a report.</p>
</div>
<div id="js-not-an-asset" class="hidden js-responsibility-message">
- <p>Please select <span id="js-roads-asset">an item</span> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-speedhump" class="hidden js-responsibility-message">
- <p>Please select <b>a speed hump</b> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-ped-barrier" class="hidden js-responsibility-message">
- <p>Please select <b>a pedestrian barrier</b> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-prow" class="hidden js-responsibility-message">
- <p>The location you have selected doesn't appear to be on a right of way.</p>
- <p>Please select a right of way on which to make a report.</p>
+ <p>Please select <span class="js-roads-asset" data-original="an item">an item</span> from the map on which to make a report.</p>
</div>
</div>
diff --git a/templates/web/northamptonshire/report/new/roads_message.html b/templates/web/northamptonshire/report/new/roads_message.html
index a6185a668..06244b36e 100644
--- a/templates/web/northamptonshire/report/new/roads_message.html
+++ b/templates/web/northamptonshire/report/new/roads_message.html
@@ -1,19 +1,9 @@
<div id="js-roads-responsibility" class="box-warning hidden">
<div id="js-not-an-asset" class="hidden js-responsibility-message">
- <p>Please select <span id="js-roads-asset">an item</span> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-speedhump" class="hidden js-responsibility-message">
- <p>Please select <b>a speed hump</b> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-ped-barrier" class="hidden js-responsibility-message">
- <p>Please select <b>a pedestrian barrier</b> from the map on which to make a report.</p>
- </div>
- <div id="js-not-a-prow" class="hidden js-responsibility-message">
- <p>The location you have selected doesn't appear to be on a right of way.</p>
- <p>Please select a right of way on which to make a report.</p>
+ <p>Please select <span class="js-roads-asset" data-original="an item">an item</span> from the map on which to make a report.</p>
</div>
<div id="js-not-a-road" class="hidden js-responsibility-message">
- <p>The location you have selected doesn't appear to be on a road.</p>
- <p>Please select a road on which to make a report.</p>
+ <p>The location you have selected doesn't appear to be on <span class="js-roads-asset" data-original="a road">a road</span>.</p>
+ <p>Please select <span class="js-roads-asset" data-original="a road">a road</span> on which to make a report.</p>
</div>
</div>
diff --git a/templates/web/zurich/admin/template_edit.html b/templates/web/zurich/admin/template_edit.html
index e954d566c..b6f68106c 100644
--- a/templates/web/zurich/admin/template_edit.html
+++ b/templates/web/zurich/admin/template_edit.html
@@ -16,6 +16,9 @@
accept-charset="utf-8"
class="validate">
+ [% IF errors.title %]
+ <div class="form-error">[% errors.title %]</div>
+ [% END %]
<p>
<strong>[% loc('Title:') %] </strong>
<input type="text" name="title" class="form-control required" size="30" value="[% rt.title| html %]">
diff --git a/web/cobrands/buckinghamshire/assets.js b/web/cobrands/buckinghamshire/assets.js
index 8135fe184..66590ca71 100644
--- a/web/cobrands/buckinghamshire/assets.js
+++ b/web/cobrands/buckinghamshire/assets.js
@@ -229,6 +229,8 @@ var bucks_types = [
"3B", // HW: SECONDARY DISTRIBUTOR
"4A", // HW: LINK ROAD
"4B", // HW: LOCAL ACCESS ROAD
+ "98", // HW: METALLED PUBLIC FOOTPATH
+ "99" // HW: METALLED PUBLIC BRIDLEWAY
];
// And these are roads they don't maintain.
var non_bucks_types = [
@@ -287,51 +289,11 @@ var rule_not_owned = new OpenLayers.Rule({
});
highways_style.addRules([rule_owned, rule_not_owned]);
-function show_responsibility_error(id) {
- hide_responsibility_errors();
- $("#js-roads-responsibility").removeClass("hidden");
- $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
- $('.js-update-coordinates').attr('href', function(i, href) {
- if (href.indexOf('?') != -1) {
- href = href.substring(0, href.indexOf('?'));
- }
- href += '?' + OpenLayers.Util.getParameterString({
- latitude: $('#fixmystreet\\.latitude').val(),
- longitude: $('#fixmystreet\\.longitude').val()
- });
- return href;
- });
- $(id).removeClass("hidden");
-}
-
-function hide_responsibility_errors() {
- $("#js-roads-responsibility").addClass("hidden");
- $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
-}
-
-function disable_report_form() {
- $("#problem_form").hide();
-}
-
-function enable_report_form() {
- $("#problem_form").show();
-}
-
-function is_only_body(body) {
- if (fixmystreet.bodies && fixmystreet.bodies.length == 1 && fixmystreet.bodies[0] == body) {
- return true;
- }
- return false;
-}
-
$(fixmystreet).on('report_new:highways_change', function() {
if (fixmystreet.body_overrides.get_only_send() === 'Highways England') {
- hide_responsibility_errors();
- enable_report_form();
$('#bucks_dangerous_msg').hide();
} else {
$('#bucks_dangerous_msg').show();
- $(fixmystreet).trigger('report_new:category_change', [ $('#form_category') ]);
}
});
@@ -352,54 +314,31 @@ fixmystreet.assets.add($.extend(true, {}, defaults, {
all_categories: true,
actions: {
found: function(layer, feature) {
- fixmystreet.body_overrides.allow_send(layer.fixmystreet.body);
- fixmystreet.body_overrides.remove_only_send();
+ var map = {
+ "HE": '#js-not-council-road-he',
+ "HWOA": '#js-not-council-road-other'
+ };
+ var msg_id = map[feature.attributes.feature_ty] || '#js-not-council-road';
+
+ fixmystreet.message_controller.road_found(layer, feature, function(feature) {
+ if (OpenLayers.Util.indexOf(bucks_types, feature.attributes.feature_ty) != -1) {
+ var cat = $('select#form_category').val();
+ if (cat === 'Flytipping') {
+ fixmystreet.body_overrides.only_send(layer.fixmystreet.body);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }, msg_id);
// Make sure Flytipping related things reset
$('#category_meta').show();
$('#form_road-placement').attr('required', '');
-
- if (fixmystreet.assets.selectedFeature()) {
- hide_responsibility_errors();
- enable_report_form();
- } else if (OpenLayers.Util.indexOf(bucks_types, feature.attributes.feature_ty) != -1) {
- var cat = $('select#form_category').val();
- if (cat === 'Flytipping') {
- fixmystreet.body_overrides.only_send(layer.fixmystreet.body);
- }
- hide_responsibility_errors();
- enable_report_form();
- } else {
- // User has clicked a road that Bucks don't maintain.
-
- var map = {
- "HE": '#js-not-council-road-he',
- "HWOA": '#js-not-council-road-other'
- };
-
- fixmystreet.body_overrides.do_not_send(layer.fixmystreet.body);
- if (is_only_body(layer.fixmystreet.body)) {
- var id = map[feature.attributes.feature_ty] || '#js-not-council-road';
- show_responsibility_error(id);
- disable_report_form();
- }
- }
},
not_found: function(layer) {
- // If a feature wasn't found at the location they've clicked, it's
- // probably a field or something. Show an error to that effect,
- // unless an asset is selected.
- fixmystreet.body_overrides.do_not_send(layer.fixmystreet.body);
- fixmystreet.body_overrides.remove_only_send();
- if (fixmystreet.assets.selectedFeature()) {
- fixmystreet.body_overrides.allow_send(layer.fixmystreet.body);
- hide_responsibility_errors();
- enable_report_form();
- } else if (is_only_body(layer.fixmystreet.body)) {
- show_responsibility_error("#js-not-a-road");
- disable_report_form();
- }
+ fixmystreet.message_controller.road_not_found(layer);
// If flytipping is picked, we don't want to ask the extra question
var cat = $('select#form_category').val();
@@ -411,6 +350,7 @@ fixmystreet.assets.add($.extend(true, {}, defaults, {
}
}
},
+ no_asset_msg_id: '#js-not-a-road',
usrn: {
attribute: 'site_code',
field: 'site_code'
@@ -465,27 +405,10 @@ fixmystreet.assets.add($.extend(true, {}, defaults, {
}
}));
-function check_rights_of_way() {
- var relevant_body = OpenLayers.Util.indexOf(fixmystreet.bodies, defaults.body) > -1;
- var relevant_cat = $('#form_category').val() == 'Rights of Way';
- var relevant = relevant_body && relevant_cat;
- var currently_shown = !!$('#row-message').length;
-
- if (relevant === currently_shown) {
- // Either should be shown and already is, or shouldn't be shown and isn't
- return;
- }
-
- if (!relevant) {
- $('#row-message').remove();
- $('.js-hide-if-invalid-category').show();
- return;
- }
-
- var $msg = $('<p id="row-message" class="box-warning">If you wish to report an issue on a Public Right of Way, please use <a href="https://www.buckscc.gov.uk/services/environment/public-rights-of-way/report-a-rights-of-way-issue/">this service</a>.</p>');
- $msg.insertBefore('#js-post-category-messages');
- $('.js-hide-if-invalid-category').hide();
-}
-$(fixmystreet).on('report_new:category_change', check_rights_of_way);
+fixmystreet.message_controller.register_category({
+ body: defaults.body,
+ category: 'Rights of Way',
+ message: 'If you wish to report an issue on a Public Right of Way, please use <a href="https://www.buckscc.gov.uk/services/environment/public-rights-of-way/report-a-rights-of-way-issue/">this service</a>.'
+});
})();
diff --git a/web/cobrands/fixmystreet-uk-councils/roadworks.js b/web/cobrands/fixmystreet-uk-councils/roadworks.js
index f7451f801..ea95d1d40 100644
--- a/web/cobrands/fixmystreet-uk-councils/roadworks.js
+++ b/web/cobrands/fixmystreet-uk-councils/roadworks.js
@@ -183,7 +183,7 @@ fixmystreet.roadworks.display_message = function(feature) {
tag_top = config.tag_top || 'p',
colon = config.colon ? ':' : '';
- var $msg = $('<div class="js-roadworks-message-' + feature.layer.id + ' box-warning"><' + tag_top + '>Roadworks are scheduled near this location, so you may not need to report your issue.</' + tag_top + '></div>');
+ var $msg = $('<div class="js-roadworks-message js-roadworks-message-' + feature.layer.id + ' box-warning"><' + tag_top + '>Roadworks are scheduled near this location, so you may not need to report your issue.</' + tag_top + '></div>');
var $dl = $("<dl></dl>").appendTo($msg);
$dl.append("<dt>Dates" + colon + "</dt>");
$dl.append($("<dd></dd>").text(start + " until " + end));
diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js
index 8b121066b..724628930 100644
--- a/web/cobrands/fixmystreet/assets.js
+++ b/web/cobrands/fixmystreet/assets.js
@@ -921,3 +921,194 @@ $(fixmystreet).on('body_overrides:change', function() {
fixmystreet.update_public_councils_text(
$('#js-councils_text').html(), bodies);
});
+
+/*
+Handling of the form-top messaging: This handles categories that hide the form
+and show a message, and categories where assets must be selected or the pin
+must be on a road, taking into account Highways England roads.
+*/
+
+fixmystreet.message_controller = (function() {
+ var stopperId = 'js-category-stopper',
+ stoppers = [];
+
+ // This shows an error message because e.g. an asset isn't selected or a road hasn't been clicked
+ function show_responsibility_error(id, asset_item, asset_type) {
+ $("#js-roads-responsibility").removeClass("hidden");
+ $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
+ var asset_strings = $('.js-roads-asset');
+ if (asset_item) {
+ asset_strings.html('a <b class="asset-' + asset_type + '">' + asset_item + '</b>');
+ } else {
+ asset_strings.html(asset_strings.data('original'));
+ }
+ $('.js-update-coordinates').attr('href', function(i, href) {
+ if (href.indexOf('?') != -1) {
+ href = href.substring(0, href.indexOf('?'));
+ }
+ href += '?' + OpenLayers.Util.getParameterString({
+ latitude: $('#fixmystreet\\.latitude').val(),
+ longitude: $('#fixmystreet\\.longitude').val()
+ });
+ return href;
+ });
+ $(id).removeClass("hidden");
+ }
+
+ // This hides the asset/road not found message
+ function hide_responsibility_errors() {
+ $("#js-roads-responsibility").addClass("hidden");
+ $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
+ }
+
+ // This shows the reporting form
+ function enable_report_form() {
+ $(".js-hide-if-invalid-category").show();
+ }
+
+ // This hides the reporting form, apart from the category selection
+ function disable_report_form() {
+ $(".js-hide-if-invalid-category").hide();
+ }
+
+ // This hides the responsibility message, and (unless a
+ // stopper message is shown) reenables the report form
+ function responsibility_off() {
+ hide_responsibility_errors();
+ if (!document.getElementById(stopperId)) {
+ enable_report_form();
+ }
+ }
+
+ // This disables the report form and (unless a stopper
+ // message is shown) shows a responsibility message
+ function responsibility_on(id, asset_item, asset_type) {
+ disable_report_form();
+ hide_responsibility_errors();
+ if (!document.getElementById(stopperId)) {
+ show_responsibility_error(id, asset_item, asset_type);
+ }
+ }
+
+ function is_only_body(body) {
+ if (fixmystreet.bodies && fixmystreet.bodies.length == 1 && fixmystreet.bodies[0] == body) {
+ return true;
+ }
+ return false;
+ }
+
+ // make sure we fire the code to check if an asset is selected if
+ // we change options in the Highways England message
+ $(fixmystreet).on('report_new:highways_change', function() {
+ if (fixmystreet.body_overrides.get_only_send() === 'Highways England') {
+ $('#' + stopperId).remove(); // Get rid of any stopper message
+ responsibility_off(); // Will also reenable form
+ } else {
+ $(fixmystreet).trigger('report_new:category_change', [ $('#form_category') ]);
+ }
+ });
+
+ $(fixmystreet).on('report_new:category_change', function() {
+ if (fixmystreet.body_overrides.get_only_send() == 'Highways England') {
+ // If we're sending to Highways England, this message doesn't matter
+ return;
+ }
+
+ var $id = $('#' + stopperId);
+ var body = $('#form_category').data('body');
+ var matching = $.grep(stoppers, function(stopper, i) {
+ if (stopper.staff_ignore && body) {
+ return false;
+ }
+
+ var relevant_body = OpenLayers.Util.indexOf(fixmystreet.bodies, stopper.body) > -1;
+ var relevant_cat;
+ if (typeof stopper.category === 'function') {
+ relevant_cat = stopper.category();
+ } else {
+ relevant_cat = $('#form_category').val() == stopper.category;
+ }
+ var relevant = relevant_body && relevant_cat;
+ return relevant;
+ });
+
+ if (!matching.length) {
+ $id.remove();
+ if ( !$('#js-roads-responsibility').is(':visible') ) {
+ enable_report_form();
+ }
+ return;
+ }
+
+ var stopper = matching[0]; // Assume only one match possible at present
+ var $msg;
+ if (typeof stopper.message === 'function') {
+ $msg = stopper.message();
+ $msg.attr('id', stopperId);
+ } else {
+ $msg = $('<p id="' + stopperId + '" class="box-warning">' + stopper.message + '</p>');
+ }
+
+ if ($id.length) {
+ $id.replaceWith($msg);
+ } else {
+ $msg.insertBefore('#js-post-category-messages');
+ }
+ disable_report_form();
+ });
+
+ return {
+ asset_found: function() {
+ responsibility_off();
+ return ($('#' + stopperId).length);
+ },
+
+ asset_not_found: function(layer) {
+ if (!layer.visibility) {
+ responsibility_off();
+ } else {
+ responsibility_on('#js-not-an-asset', layer.fixmystreet.asset_item, layer.fixmystreet.asset_type);
+ }
+ },
+
+ // A road was found; if some roads should still cause disabling/message,
+ // then you should pass in a criterion function to test the found feature,
+ // plus an ID of the message to be shown
+ road_found: function(layer, feature, criterion, msg_id) {
+ fixmystreet.body_overrides.allow_send(layer.fixmystreet.body);
+ fixmystreet.body_overrides.remove_only_send();
+ if (fixmystreet.assets.selectedFeature()) {
+ responsibility_off();
+ } else if (!criterion || criterion(feature)) {
+ responsibility_off();
+ } else {
+ fixmystreet.body_overrides.do_not_send(layer.fixmystreet.body);
+ if (is_only_body(layer.fixmystreet.body)) {
+ responsibility_on(msg_id);
+ }
+ }
+ },
+
+ road_not_found: function(layer) {
+ // If a feature wasn't found at the location they've clicked, it's
+ // probably a field or something. Show an error to that effect,
+ // unless an asset is selected.
+ fixmystreet.body_overrides.do_not_send(layer.fixmystreet.body);
+ fixmystreet.body_overrides.remove_only_send();
+ // don't show the message if clicking on a highways england road
+ if (fixmystreet.body_overrides.get_only_send() == 'Highways England' || !layer.visibility) {
+ responsibility_off();
+ } else if (fixmystreet.assets.selectedFeature()) {
+ fixmystreet.body_overrides.allow_send(layer.fixmystreet.body);
+ responsibility_off();
+ } else if (is_only_body(layer.fixmystreet.body)) {
+ responsibility_on(layer.fixmystreet.no_asset_msg_id, layer.fixmystreet.asset_item, layer.fixmystreet.asset_type);
+ }
+ },
+
+ register_category: function(params) {
+ stoppers.push(params);
+ }
+ };
+
+})();
diff --git a/web/cobrands/lincolnshire/assets.js b/web/cobrands/lincolnshire/assets.js
index 40187e188..f4b1861a9 100644
--- a/web/cobrands/lincolnshire/assets.js
+++ b/web/cobrands/lincolnshire/assets.js
@@ -140,7 +140,10 @@ fixmystreet.assets.add($.extend(true, {}, defaults, {
TYPENAME: "ST_All_Structures"
}
},
- asset_category: "Bridge",
+ asset_category: [
+ "Bridge",
+ "Bridge or Structure"
+ ],
asset_item: 'bridge',
filter_key: 'Type',
filter_value: [
diff --git a/web/cobrands/lincolnshire/roadworks.js b/web/cobrands/lincolnshire/roadworks.js
index 7b42a12f2..760e8f00e 100644
--- a/web/cobrands/lincolnshire/roadworks.js
+++ b/web/cobrands/lincolnshire/roadworks.js
@@ -11,4 +11,19 @@ fixmystreet.assets.add($.extend(true, {}, fixmystreet.roadworks.layer_future, {
// NB Lincs don't want forward planning works displayed, so
// fixmystreet.roadworks.layer_planned is deliberately missing here.
+
+// Lincs want to also display the responsible party in roadworks messages
+var original_display_message = fixmystreet.roadworks.display_message;
+fixmystreet.roadworks.display_message = function(feature) {
+ var retval = original_display_message.apply(this, arguments);
+
+ if (feature.attributes.promoter) {
+ var $dl = $(".js-roadworks-message-" + feature.layer.id + " dl");
+ $dl.append("<dt>Responsibility</dt>");
+ $dl.append($("<dd></dd>").text(feature.attributes.promoter));
+ }
+
+ return retval;
+};
+
})();
diff --git a/web/cobrands/northamptonshire/assets.js b/web/cobrands/northamptonshire/assets.js
index 36f354761..dda51407e 100644
--- a/web/cobrands/northamptonshire/assets.js
+++ b/web/cobrands/northamptonshire/assets.js
@@ -4,32 +4,6 @@ if (!fixmystreet.maps) {
return;
}
-/* utility functions */
-function show_responsibility_error(id, asset_item, asset_type) {
- hide_responsibility_errors();
- $("#js-roads-responsibility").removeClass("hidden");
- $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
- if (asset_item) {
- $('#js-roads-asset').html('a <b class="asset-' + asset_type + '">' + asset_item + '</b>');
- } else {
- $('#js-roads-asset').html('an item');
- }
- $(id).removeClass("hidden");
-}
-
-function hide_responsibility_errors() {
- $("#js-roads-responsibility").addClass("hidden");
- $("#js-roads-responsibility .js-responsibility-message").addClass("hidden");
-}
-
-function enable_report_form() {
- $(".js-hide-if-invalid-category").show();
-}
-
-function disable_report_form() {
- $(".js-hide-if-invalid-category").hide();
-}
-
var is_live = false;
if ( location.hostname === 'www.fixmystreet.com' || location.hostname == 'fixmystreet.northamptonshire.gov.uk' ) {
is_live = true;
@@ -340,18 +314,6 @@ var layers = [
},
];
-// make sure we fire the code to check if an asset is selected if
-// we change options in the Highways England message
-$(fixmystreet).on('report_new:highways_change', function() {
- if (fixmystreet.body_overrides.get_only_send() === 'Highways England') {
- hide_responsibility_errors();
- enable_report_form();
- $('#ncc_streetlights').remove();
- } else {
- $(fixmystreet).trigger('report_new:category_change', [ $('#form_category') ]);
- }
-});
-
// This is required so that the found/not found actions are fired on category
// select and pin move rather than just on asset select/not select.
OpenLayers.Layer.NCCVectorAsset = OpenLayers.Class(OpenLayers.Layer.VectorAsset, {
@@ -383,12 +345,9 @@ var northants_defaults = $.extend(true, {}, fixmystreet.assets.alloy_defaults, {
select_action: true,
actions: {
asset_found: function(asset) {
- var emergency_state = ncc_is_emergency_category();
- if (emergency_state.relevant && !emergency_state.body) {
+ if (fixmystreet.message_controller.asset_found()) {
return;
}
- hide_responsibility_errors();
- enable_report_form();
var lonlat = asset.geometry.getBounds().getCenterLonLat();
// Features considered overlapping if within 1M of each other
// TODO: Should zoom/marker size be considered when determining if markers overlap?
@@ -419,14 +378,7 @@ var northants_defaults = $.extend(true, {}, fixmystreet.assets.alloy_defaults, {
},
asset_not_found: function() {
$("#overlapping_features_msg").addClass('hidden');
- var emergency_state = ncc_is_emergency_category();
-
- disable_report_form();
- if ((!emergency_state.relevant || emergency_state.body) && this.visibility) {
- show_responsibility_error('#js-not-an-asset', this.fixmystreet.asset_item, this.fixmystreet.asset_type);
- } else {
- hide_responsibility_errors();
- }
+ fixmystreet.message_controller.asset_not_found(this);
}
}
});
@@ -465,30 +417,8 @@ var northants_road_defaults = $.extend(true, {}, fixmystreet.assets.alloy_defaul
return feature.fid;
},
actions: {
- found: function(layer, feature) {
- var emergency_state = ncc_is_emergency_category();
- if (!emergency_state.relevant || emergency_state.body) {
- enable_report_form();
- }
- hide_responsibility_errors();
- },
- not_found: function(layer) {
- // don't show the message if clicking on a highways england road
- var emergency_state = ncc_is_emergency_category();
- if (fixmystreet.body_overrides.get_only_send() == 'Highways England' || !layer.visibility) {
- if (!emergency_state.relevant || emergency_state.body) {
- enable_report_form();
- }
- hide_responsibility_errors();
- } else {
- disable_report_form();
- if (!emergency_state.relevant || emergency_state.body) {
- show_responsibility_error(layer.fixmystreet.no_asset_msg_id);
- } else {
- hide_responsibility_errors();
- }
- }
- },
+ found: fixmystreet.message_controller.road_found,
+ not_found: fixmystreet.message_controller.road_not_found
}
});
@@ -498,7 +428,8 @@ fixmystreet.assets.add($.extend(true, {}, northants_road_defaults, {
layerid: 221,
layerVersion: '221.4-',
},
- no_asset_msg_id: '#js-not-a-speedhump',
+ no_asset_msg_id: '#js-not-an-asset',
+ asset_item: 'speed hump',
asset_type: "area",
asset_category: [
"Damaged Speed Humps",
@@ -520,7 +451,9 @@ fixmystreet.assets.add($.extend(true, {}, northants_road_defaults, {
stylemap: new OpenLayers.StyleMap({
'default': barrier_style
}),
- no_asset_msg_id: '#js-not-a-ped-barrier',
+ no_asset_msg_id: '#js-not-an-asset',
+ asset_item: 'pedestrian barrier',
+ asset_type: 'area',
asset_category: [
"Pedestrian Barriers - Damaged / Missing",
]
@@ -589,66 +522,29 @@ fixmystreet.assets.add($.extend(true, {}, northants_road_defaults, {
stylemap: new OpenLayers.StyleMap({
'default': prow_style
}),
- no_asset_msg_id: "#js-not-a-prow",
+ no_asset_msg_id: "#js-not-a-road",
+ asset_item: 'right of way',
asset_category: [
"Livestock",
"Passage-Obstructed/Overgrown"
]
}));
-function ncc_is_emergency_category() {
- var relevant_body = OpenLayers.Util.indexOf(fixmystreet.bodies, northants_defaults.body) > -1;
- var relevant_cat = !!$('label[for=form_emergency]').length;
- var relevant = relevant_body && relevant_cat;
- var currently_shown = !!$('#northants-emergency-message').length;
- var body = $('#form_category').data('body');
-
- return {relevant: relevant, currently_shown: currently_shown, body: body};
-}
-
-// Hide form when emergency category used
-function check_emergency() {
- var state = ncc_is_emergency_category();
-
- if (state.relevant === state.currently_shown || state.body || fixmystreet.body_overrides.get_only_send() == 'Highways England') {
- // Either should be shown and already is, or shouldn't be shown and isn't
- return;
- }
-
- if (!state.relevant) {
- $('#northants-emergency-message').remove();
- if ( !$('#js-roads-responsibility').is(':visible') ) {
- $('.js-hide-if-invalid-category').show();
- }
- return;
- }
-
- var $msg = $('<div class="box-warning" id="northants-emergency-message"></div>');
- $msg.html($('label[for=form_emergency]').html());
- $msg.insertBefore('#js-post-category-messages');
- $('.js-hide-if-invalid-category').hide();
-}
-$(fixmystreet).on('report_new:category_change', check_emergency);
-
-function ncc_check_streetlights() {
- var relevant_body = OpenLayers.Util.indexOf(fixmystreet.bodies, northants_defaults.body) > -1;
- var relevant_cat = $('#form_category').val() == 'Street lighting';
- var relevant = relevant_body && relevant_cat;
- var currently_shown = !!$('#ncc_streetlights').length;
-
- if (relevant === currently_shown || fixmystreet.body_overrides.get_only_send() == 'Highways England') {
- return;
- }
-
- if (!relevant) {
- $('#ncc_streetlights').remove();
- return;
- }
+fixmystreet.message_controller.register_category({
+ body: northants_defaults.body,
+ category: function() {
+ return !!$('label[for=form_emergency]').length;
+ },
+ message: function() {
+ return $('<div class="box-warning">' + $('label[for=form_emergency]').html() + '</div>');
+ },
+ staff_ignore: true
+});
- var $msg = $('<p id="ncc_streetlights" class="box-warning">Street lighting in Northamptonshire is maintained by Balfour Beatty on behalf of the County Council under a Street Lighting Private Finance Initiative (PFI) contract. Please view our <b><a href="https://www3.northamptonshire.gov.uk/councilservices/northamptonshire-highways/roads-and-streets/Pages/street-lighting.aspx">Street Lighting</a></b> page to report any issues.</p>');
- $msg.insertBefore('#js-post-category-messages');
- disable_report_form();
-}
-$(fixmystreet).on('report_new:category_change', ncc_check_streetlights);
+fixmystreet.message_controller.register_category({
+ body: northants_defaults.body,
+ category: 'Street lighting',
+ message: 'Street lighting in Northamptonshire is maintained by Balfour Beatty on behalf of the County Council under a Street Lighting Private Finance Initiative (PFI) contract. Please view our <b><a href="https://www3.northamptonshire.gov.uk/councilservices/northamptonshire-highways/roads-and-streets/Pages/street-lighting.aspx">Street Lighting</a></b> page to report any issues.'
+});
})();
diff --git a/web/cobrands/oxfordshire/assets.js b/web/cobrands/oxfordshire/assets.js
index 46b555b02..df60b89c7 100644
--- a/web/cobrands/oxfordshire/assets.js
+++ b/web/cobrands/oxfordshire/assets.js
@@ -1,26 +1,5 @@
-(function(){
-
-function check_rights_of_way() {
- var relevant_body = OpenLayers.Util.indexOf(fixmystreet.bodies, 'Oxfordshire County Council') > -1;
- var relevant_cat = $('#form_category').val() == 'Countryside Paths / Public Rights of Way (usually not tarmac)';
- var relevant = relevant_body && relevant_cat;
- var currently_shown = !!$('#occ_prow').length;
-
- if (relevant === currently_shown) {
- // Either should be shown and already is, or shouldn't be shown and isn't
- return;
- }
-
- if (!relevant) {
- $('#occ_prow').remove();
- $('.js-hide-if-invalid-category').show();
- return;
- }
-
- var $msg = $('<p id="occ_prow" class="box-warning">Please report problems with rights of way using <a href="https://publicrightsofway.oxfordshire.gov.uk/web/standardmap.aspx">this page</a>.</p>');
- $msg.insertBefore('#js-post-category-messages');
- $('.js-hide-if-invalid-category').hide();
-}
-$(fixmystreet).on('report_new:category_change', check_rights_of_way);
-
-})();
+fixmystreet.message_controller.register_category({
+ body: 'Oxfordshire County Council',
+ category: 'Countryside Paths / Public Rights of Way (usually not tarmac)',
+ message: 'Please report problems with rights of way using <a href="https://publicrightsofway.oxfordshire.gov.uk/web/standardmap.aspx">this page</a>.'
+});
diff --git a/web/cobrands/sass/_admin.scss b/web/cobrands/sass/_admin.scss
index 1f55c62df..745c74fd7 100644
--- a/web/cobrands/sass/_admin.scss
+++ b/web/cobrands/sass/_admin.scss
@@ -240,3 +240,13 @@ $button_bg_col: #a1a1a1; // also search bar (tables)
font-weight: normal;
}
}
+
+.truncate_height {
+ max-height: 3em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ &:hover {
+ max-height: initial;
+ }
+}