aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm42
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm27
-rw-r--r--perllib/FixMyStreet/Cobrand/Bristol.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/Oxfordshire.pm6
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Nearby.pm3
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm37
-rw-r--r--t/app/controller/report_inspect.t26
-rw-r--r--t/app/controller/report_new.t16
-rw-r--r--t/cobrand/oxfordshire.t51
-rw-r--r--templates/web/base/report/_inspect.html6
-rw-r--r--templates/web/base/report/new/form_user_loggedin.html7
-rw-r--r--templates/web/bristol/maps/noscript_map.html32
-rw-r--r--templates/web/oxfordshire/header.html10
-rw-r--r--web/cobrands/angus/js.js4
-rw-r--r--web/cobrands/bristol/js.js16
-rw-r--r--web/cobrands/fixmystreet/assets.js271
-rw-r--r--web/cobrands/fixmystreet/staff.js4
-rw-r--r--web/vendor/OpenLayers.Projection.OrdnanceSurvey.js12
20 files changed, 366 insertions, 211 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 45267a57e..e05f8c4fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,8 @@
* Unreleased
- Front end improvements:
- Improve questionnaire process. #1939 #1998
+ - Admin improvements:
+ - Inspectors can set non_public status of reports. #1992
* v2.3.1 (12th February 2018)
- Front end improvements:
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm
index 8708c6128..ec0e6f886 100644
--- a/perllib/FixMyStreet/App/Controller/Report.pm
+++ b/perllib/FixMyStreet/App/Controller/Report.pm
@@ -76,7 +76,7 @@ sub _display : Private {
$c->forward( 'load_updates' );
$c->forward( 'format_problem_for_display' );
- my $permissions = $c->stash->{_permissions} = $c->forward( 'check_has_permission_to',
+ my $permissions = $c->stash->{_permissions} ||= $c->forward( 'check_has_permission_to',
[ qw/report_inspect report_edit_category report_edit_priority/ ] );
if (any { $_ } values %$permissions) {
$c->stash->{template} = 'report/inspect.html';
@@ -128,7 +128,11 @@ sub load_problem_or_display_error : Private {
[ _('That report has been removed from FixMyStreet.') ] #
);
} elsif ( $problem->non_public ) {
- if ( !$c->user || $c->user->id != $problem->user->id ) {
+ # Creator, and inspection users can see non_public reports
+ $c->stash->{problem} = $problem;
+ my $permissions = $c->stash->{_permissions} = $c->forward( 'check_has_permission_to',
+ [ qw/report_inspect report_edit_category report_edit_priority/ ] );
+ if ( !$c->user || ($c->user->id != $problem->user->id && !$permissions->{report_inspect}) ) {
$c->detach(
'/page_error_403_access_denied',
[ sprintf(_('That report cannot be viewed on %s.'), $c->stash->{site_name}) ]
@@ -348,6 +352,8 @@ sub inspect : Private {
my %update_params = ();
if ($permissions->{report_inspect}) {
+ $problem->non_public($c->get_param('non_public') ? 1 : 0);
+
$problem->set_extra_metadata( traffic_information => $c->get_param('traffic_information') );
if ( my $info = $c->get_param('detailed_information') ) {
@@ -461,22 +467,24 @@ sub inspect : Private {
}
$problem->lastupdate( \'current_timestamp' );
$problem->update;
- my $timestamp = \'current_timestamp';
- if (my $saved_at = $c->get_param('saved_at')) {
- $timestamp = DateTime->from_epoch( epoch => $saved_at );
+ if ($update_text || %update_params) {
+ my $timestamp = \'current_timestamp';
+ if (my $saved_at = $c->get_param('saved_at')) {
+ $timestamp = DateTime->from_epoch( epoch => $saved_at );
+ }
+ my $name = $c->user->from_body ? $c->user->from_body->name : $c->user->name;
+ $problem->add_to_comments( {
+ text => $update_text,
+ created => $timestamp,
+ confirmed => $timestamp,
+ user_id => $c->user->id,
+ name => $name,
+ state => 'confirmed',
+ mark_fixed => 0,
+ anonymous => 0,
+ %update_params,
+ } );
}
- my $name = $c->user->from_body ? $c->user->from_body->name : $c->user->name;
- $problem->add_to_comments( {
- text => $update_text,
- created => $timestamp,
- confirmed => $timestamp,
- user_id => $c->user->id,
- name => $name,
- state => 'confirmed',
- mark_fixed => 0,
- anonymous => 0,
- %update_params,
- } );
my $redirect_uri;
$problem->discard_changes;
diff --git a/perllib/FixMyStreet/App/Controller/Report/New.pm b/perllib/FixMyStreet/App/Controller/Report/New.pm
index f9e07dd41..888110429 100644
--- a/perllib/FixMyStreet/App/Controller/Report/New.pm
+++ b/perllib/FixMyStreet/App/Controller/Report/New.pm
@@ -870,6 +870,7 @@ sub process_report : Private {
'subcategory', #
'partial', #
'service', #
+ 'non_public',
);
# load the report
@@ -897,6 +898,8 @@ sub process_report : Private {
$report->anonymous( $params{may_show_name} ? 0 : 1 );
}
+ $report->non_public($params{non_public} ? 1 : 0);
+
# clean up text before setting
$report->title( Utils::cleanup_text( $params{title} ) );
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index 7c3796c42..15a220644 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -544,20 +544,27 @@ sub load_and_group_problems : Private {
my $states = $c->stash->{filter_problem_states};
my $where = {
- non_public => 0,
state => [ keys %$states ]
};
+
+ my $body = $c->stash->{body}; # Might be undef
+
+ if ($c->user_exists && ($c->user->is_superuser || ($body && $c->user->has_permission_to('report_inspect', $body->id)))) {
+ # See all reports, no restriction
+ } else {
+ $where->{non_public} = 0;
+ }
+
my $filter = {
order_by => $c->stash->{sort_order},
rows => $c->cobrand->reports_per_page,
};
- if ($c->user_exists && $c->stash->{body}) {
- my $bid = $c->stash->{body}->id;
+ if ($c->user_exists && $body) {
my $prefetch = [];
- if ($c->user->has_permission_to('planned_reports', $bid)) {
+ if ($c->user->has_permission_to('planned_reports', $body->id)) {
push @$prefetch, 'user_planned_reports';
}
- if ($c->user->has_permission_to('report_edit_priority', $bid) || $c->user->has_permission_to('report_inspect', $bid)) {
+ if ($c->user->has_permission_to('report_edit_priority', $body->id) || $c->user->has_permission_to('report_inspect', $body->id)) {
push @$prefetch, 'response_priority';
}
$prefetch = $prefetch->[0] if @$prefetch == 1;
@@ -589,9 +596,9 @@ sub load_and_group_problems : Private {
$where->{areas} = [
map { { 'like', '%,' . $_->{id} . ',%' } } @{$c->stash->{wards}}
];
- $problems = $problems->to_body($c->stash->{body});
- } elsif ($c->stash->{body}) {
- $problems = $problems->to_body($c->stash->{body});
+ $problems = $problems->to_body($body);
+ } elsif ($body) {
+ $problems = $problems->to_body($body);
}
if (my $bbox = $c->get_param('bbox')) {
@@ -609,7 +616,7 @@ sub load_and_group_problems : Private {
my ( %problems, @pins );
while ( my $problem = $problems->next ) {
- if ( !$c->stash->{body} ) {
+ if ( !$body ) {
add_row( $c, $problem, 0, \%problems, \@pins );
next;
}
@@ -623,7 +630,7 @@ sub load_and_group_problems : Private {
# Add to bodies it was sent to
my $bodies = $problem->bodies_str_ids;
foreach ( @$bodies ) {
- next if $_ != $c->stash->{body}->id;
+ next if $_ != $body->id;
add_row( $c, $problem, $_, \%problems, \@pins );
}
}
diff --git a/perllib/FixMyStreet/Cobrand/Bristol.pm b/perllib/FixMyStreet/Cobrand/Bristol.pm
index 4648802bd..b11a52643 100644
--- a/perllib/FixMyStreet/Cobrand/Bristol.pm
+++ b/perllib/FixMyStreet/Cobrand/Bristol.pm
@@ -20,7 +20,7 @@ sub example_places {
}
sub map_type {
- 'OSM';
+ 'Bristol';
}
sub default_link_zoom { 6 }
diff --git a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
index 00f099278..4b1dbc32c 100644
--- a/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
+++ b/perllib/FixMyStreet/Cobrand/Oxfordshire.pm
@@ -67,6 +67,11 @@ sub problem_response_days {
my $self = shift;
my $p = shift;
+ return 'emergency' if $p->category eq 'Street lighting';
+
+ # Temporary, see https://github.com/mysociety/fixmystreetforcouncils/issues/291
+ return 0;
+
return 10 if $p->category eq 'Bridges';
return 10 if $p->category eq 'Carriageway Defect'; # phone if urgent
return 10 if $p->category eq 'Debris/Spillage';
@@ -87,7 +92,6 @@ sub problem_response_days {
return 10 if $p->category eq 'Road traffic signs';
return 10 if $p->category eq 'Roads/highways';
return 10 if $p->category eq 'Skips and scaffolding';
- return 'emergency' if $p->category eq 'Street lighting';
return 10 if $p->category eq 'Traffic lights'; # phone if urgent
return 10 if $p->category eq 'Traffic';
return 10 if $p->category eq 'Trees';
diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
index 6e5e0220f..ab554eb9d 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm
@@ -17,13 +17,14 @@ sub nearby {
}
my $params = {
- non_public => 0,
state => [ keys %$states ],
};
$params->{id} = { -not_in => $ids }
if $ids;
$params->{category} = $categories if $categories && @$categories;
+ FixMyStreet::DB::ResultSet::Problem->non_public_if_possible($params, $c);
+
$rs = $c->cobrand->problems_restriction($rs);
my $attrs = {
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index 3f083c073..458efa179 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -15,15 +15,41 @@ sub set_restriction {
$site_key = $key;
}
-sub to_body {
- my ($rs, $bodies, $join) = @_;
- return $rs unless $bodies;
+sub body_query {
+ my ($rs, $bodies) = @_;
unless (ref $bodies eq 'ARRAY') {
$bodies = [ map { ref $_ ? $_->id : $_ } $bodies ];
}
+ \[ "regexp_split_to_array(bodies_str, ',') && ?", [ {} => $bodies ] ]
+}
+
+# Edits PARAMS in place to either hide non_public reports, or show them
+# if user is superuser (all) or inspector (correct body)
+sub non_public_if_possible {
+ my ($rs, $params, $c) = @_;
+ if ($c->user_exists) {
+ if ($c->user->is_superuser) {
+ # See all reports, no restriction
+ } elsif ($c->user->has_body_permission_to('report_inspect')) {
+ $params->{'-or'} = [
+ non_public => 0,
+ $rs->body_query($c->user->from_body->id),
+ ];
+ } else {
+ $params->{non_public} = 0;
+ }
+ } else {
+ $params->{non_public} = 0;
+ }
+}
+
+sub to_body {
+ my ($rs, $bodies, $join) = @_;
+ return $rs unless $bodies;
$join = { join => 'problem' } if $join;
$rs = $rs->search(
- \[ "regexp_split_to_array(bodies_str, ',') && ?", [ {} => $bodies ] ],
+ # This isn't using $rs->body_query because $rs might be Problem, Comment, or Nearby
+ FixMyStreet::DB::ResultSet::Problem->body_query($bodies),
$join
);
return $rs;
@@ -151,13 +177,14 @@ sub around_map {
}
my $q = {
- non_public => 0,
state => [ keys %{$p{states}} ],
latitude => { '>=', $p{min_lat}, '<', $p{max_lat} },
longitude => { '>=', $p{min_lon}, '<', $p{max_lon} },
};
$q->{category} = $p{categories} if $p{categories} && @{$p{categories}};
+ $rs->non_public_if_possible($q, $c);
+
my $problems = mySociety::Locale::in_gb_locale {
$rs->search( $q, $attr )->include_comment_counts->page($p{page});
};
diff --git a/t/app/controller/report_inspect.t b/t/app/controller/report_inspect.t
index 239cc408b..39dd57444 100644
--- a/t/app/controller/report_inspect.t
+++ b/t/app/controller/report_inspect.t
@@ -559,6 +559,7 @@ FixMyStreet::override_config {
my $expected_fields = {
state => 'action scheduled',
category => 'Cows',
+ non_public => undef,
public_update => '',
priority => $rp->id,
include_update => '1',
@@ -594,6 +595,31 @@ FixMyStreet::override_config {
is $report->comments->count, 1, "Only leaves one update";
like $report->comments->first->text, qr/Category changed.*Badgers/, 'update text included category change';
};
+
+ subtest "test non-public changing" => sub {
+ $report->comments->delete;
+ is $report->non_public, 0, 'Not set to non-public';
+ $mech->get_ok("/report/$report_id");
+ $mech->submit_form(button => 'save', with_fields => { include_update => 0, non_public => 1 });
+ is $report->comments->count, 0, "No updates left";
+ $report->discard_changes;
+ is $report->non_public, 1, 'Now set to non-public';
+ $mech->submit_form(button => 'save', with_fields => { include_update => 0, non_public => 0 });
+ is $report->comments->count, 0, "No updates left";
+ $report->discard_changes;
+ is $report->non_public, 0, 'Not set to non-public';
+ };
+
+ subtest "test saved-at setting" => sub {
+ $report->comments->delete;
+ $mech->get_ok("/report/$report_id");
+ my $now = DateTime->now->subtract(days => 1);
+ $mech->submit_form(button => 'save', form_id => 'report_inspect_form',
+ fields => { include_update => 1, public_update => 'An update', saved_at => $now->epoch });
+ $report->discard_changes;
+ is $report->comments->count, 1, "One update";
+ is $report->comments->first->confirmed, $now;
+ };
};
FixMyStreet::override_config {
diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t
index 3c120b0b0..32d86d803 100644
--- a/t/app/controller/report_new.t
+++ b/t/app/controller/report_new.t
@@ -1733,7 +1733,11 @@ subtest "extra google analytics code displayed on email confirmation problem cre
};
};
-subtest "inspectors get redirected directly to the report page" => sub {
+foreach my $test (
+ { non_public => 0 },
+ { non_public => 1 },
+) {
+ subtest "inspectors get redirected directly to the report page, non_public=$test->{non_public}" => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => [ { fixmystreet => '.' } ],
BASE_URL => 'https://www.fixmystreet.com',
@@ -1746,10 +1750,14 @@ subtest "inspectors get redirected directly to the report page" => sub {
body => $bodies[0],
permission_type => 'planned_reports',
});
+ $user->user_body_permissions->find_or_create({
+ body => $bodies[0],
+ permission_type => 'report_inspect',
+ });
$mech->log_in_ok('inspector@example.org');
$mech->get_ok('/');
- $mech->submit_form_ok( { with_fields => { pc => 'GL50 2PR' } },
+ $mech->submit_form_ok( { with_fields => { pc => 'EH1 1BB' } },
"submit location" );
$mech->follow_link_ok(
{ text_regex => qr/skip this step/i, },
@@ -1766,6 +1774,7 @@ subtest "inspectors get redirected directly to the report page" => sub {
may_show_name => '1',
phone => '07903 123 456',
category => 'Trees',
+ non_public => $test->{non_public},
}
},
"submit good details"
@@ -1773,6 +1782,7 @@ subtest "inspectors get redirected directly to the report page" => sub {
like $mech->uri->path, qr/\/report\/[0-9]+/, 'Redirects directly to report';
}
-};
+ };
+}
done_testing();
diff --git a/t/cobrand/oxfordshire.t b/t/cobrand/oxfordshire.t
index ee30e7e0b..54c6e32ea 100644
--- a/t/cobrand/oxfordshire.t
+++ b/t/cobrand/oxfordshire.t
@@ -185,57 +185,6 @@ subtest 'Reports are marked as inspected correctly' => sub {
};
};
-subtest 'response times messages displayed' => sub {
- my $oxfordshire = $mech->create_body_ok(
- 2237, 'Oxfordshire County Council'
- );
- my $contact = $mech->create_contact_ok(
- body_id => $oxfordshire->id,
- category => 'Pothole',
- email => 'pothole@example.com',
- );
-
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'oxfordshire' ],
- MAPIT_URL => 'http://mapit.uk/',
- }, sub {
- $mech->log_out_ok;
- $mech->clear_emails_ok;
-
- $mech->get_ok('/around');
- $mech->submit_form_ok( {
- with_fields => { pc => 'OX20 1SZ' }
- },
- "submit_location"
- );
-
- $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
- "follow 'skip this step' link" );
-
- $mech->submit_form_ok(
- {
- with_fields => {
- title => 'Test Report',
- detail => 'Test report details.',
- photo1 => '',
- username => 'test-2@example.com',
- name => 'Test User',
- category => 'Pothole',
- }
- },
- "submit details"
- );
-
- $mech->text_contains('Problems in the Pothole category are generally responded');
- my $email = $mech->get_email;
- ok $email, 'got and email';
- like $mech->get_text_body_from_email, qr/Problems in the Pothole category/, 'emails contains response time message';
- my $url = $mech->get_link_from_email($email);
- $mech->get_ok($url);
- $mech->text_contains('Problems in the Pothole category are generally responded')
- };
-};
-
END {
done_testing();
}
diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html
index 1893826de..eef85c06e 100644
--- a/templates/web/base/report/_inspect.html
+++ b/templates/web/base/report/_inspect.html
@@ -7,9 +7,12 @@
[% INCLUDE 'errors.html' %]
<form name="report_inspect_form" id="report_inspect_form" method="post" action="[% c.uri_for( '/report', problem.id ) %]" class="validate">
- <input type="hidden" name="js" value="">
<div class="inspect-section">
+ <p style="float: right">
+ <label for="non_public">[% loc('Private') %]</label>
+ <input type="checkbox" id="non_public" name="non_public" value="1"[% ' checked' IF problem.non_public %]>
+ </p>
<p>
<strong>[% loc('Report ID:') %]</strong>
<span class="js-report-id">[% problem.id %]</span>
@@ -190,6 +193,7 @@
</p>
</div>
+ <input type="hidden" name="js" value="">
</form>
</div>
[%- END %]
diff --git a/templates/web/base/report/new/form_user_loggedin.html b/templates/web/base/report/new/form_user_loggedin.html
index ad74a5654..6257a8346 100644
--- a/templates/web/base/report/new/form_user_loggedin.html
+++ b/templates/web/base/report/new/form_user_loggedin.html
@@ -72,6 +72,13 @@
<input class="form-control" type="text" value="[% report.user.email | html %]" name="email" id="form_email">
[% END %]
+[% IF c.user.has_permission_to("report_inspect", bodies.keys) %]
+ <div class="checkbox-group">
+ <input type="checkbox" name="non_public" id="form_non_public" value="1"[% ' checked' IF report.non_public %]>
+ <label class="inline" for="form_non_public">[% loc('Private') %] </label>
+ </div>
+[% END %]
+
<div class="form-txt-submit-box">
<input class="green-btn js-submit_register" type="submit" name="submit_register" value="[% loc('Submit') %]">
</div>
diff --git a/templates/web/bristol/maps/noscript_map.html b/templates/web/bristol/maps/noscript_map.html
new file mode 100644
index 000000000..987aa76a6
--- /dev/null
+++ b/templates/web/bristol/maps/noscript_map.html
@@ -0,0 +1,32 @@
+<div class="noscript square-map__outer">
+ <div class="square-map__inner">
+ <div id="[% nsm_prefix %]drag">
+ [%- FOR row IN map.tiles -%]
+ [%- FOR tile IN row -%]
+ [%- top_px = tile.row_offset * map.tile_size -%]
+ [%- left_px = tile.col_offset * map.tile_size %]
+ <[% map.img_type %]
+ class="square-map__tile"
+ alt="[% tile.alt %]"
+ id="[% nsm_prefix %]t[% tile.dotted_id %]"
+ name="tile_[% tile.dotted_id %]"
+ src="[% tile.src %]"
+ style="width: [% 100 / map.cols %]%; height: auto; float: left;">
+ [%- END -%]
+ [% END %]
+ </div>
+ <div id="[% nsm_prefix %]pins">[% FOR pin IN map.pins %][% INCLUDE pin %][% END %]</div>
+ [% INCLUDE 'maps/_compass.html' %]
+ </div>
+</div>
+
+[% BLOCK pin %]
+[%
+ SET pin_top = pin.py / ( map.tile_size * map.rows ) * 100;
+ SET pin_left = pin.px / ( map.tile_size * map.cols ) * 100;
+ # -24px half of 48px wide image, -64px all of 64px tall image
+ INCLUDE 'maps/pin.html'
+ pin_style = 'top:' _ pin_top _ '%; left:' _ pin_left _ '%; position:absolute; margin-left:-24px; margin-top:-64px;'
+%]
+[% END %]
+
diff --git a/templates/web/oxfordshire/header.html b/templates/web/oxfordshire/header.html
index a1d42a777..0d3476195 100644
--- a/templates/web/oxfordshire/header.html
+++ b/templates/web/oxfordshire/header.html
@@ -54,6 +54,16 @@ height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
</div>
</header>
+[% IF c.req.uri.path == '/' %]
+<p class="oxfordshire-preamble">
+Winter weather over the past few weeks has caused widespread damage to
+Oxfordshire’s roads. We are of course dealing with the most dangerous issues
+first but please do carry on alerting us to new ones so that we can continue to
+prioritise this work efficiently and so keep the whole county moving about its
+business as quickly as possible.
+</p>
+[% END %]
+
[% pre_container_extra %]
<div class="container">
diff --git a/web/cobrands/angus/js.js b/web/cobrands/angus/js.js
index f3e7bf211..566b3a842 100644
--- a/web/cobrands/angus/js.js
+++ b/web/cobrands/angus/js.js
@@ -4,7 +4,7 @@ if (!fixmystreet.maps) {
return;
}
-$(fixmystreet.add_assets({
+fixmystreet.assets.add({
wfs_url: "https://data.angus.gov.uk/geoserver/services/wfs",
wfs_feature: "lighting_column_v",
wfs_fault_feature: "lighting_faults_v",
@@ -18,6 +18,6 @@ $(fixmystreet.add_assets({
column_id: 'n'
},
geometryName: 'g'
-}));
+});
})();
diff --git a/web/cobrands/bristol/js.js b/web/cobrands/bristol/js.js
index 1fc23d61a..9a4d1ec46 100644
--- a/web/cobrands/bristol/js.js
+++ b/web/cobrands/bristol/js.js
@@ -19,32 +19,32 @@ var options = {
geometryName: 'SHAPE'
};
-$(fixmystreet.add_assets($.extend({}, options, {
+fixmystreet.assets.add($.extend({}, options, {
wfs_feature: "COD_ASSETS_AREA",
asset_type: 'area',
asset_category: "Bridges/Subways",
asset_item: 'bridge/subway'
-})));
+}));
-$(fixmystreet.add_assets($.extend({}, options, {
+fixmystreet.assets.add($.extend({}, options, {
asset_category: "Gully/Drainage",
asset_item: 'gully',
filter_key: 'COD_ASSET_TYPE',
filter_value: 'GULLY'
-})));
+}));
-$(fixmystreet.add_assets($.extend({}, options, {
+fixmystreet.assets.add($.extend({}, options, {
asset_category: "Grit Bins",
asset_item: 'grit bin',
filter_key: 'COD_ASSET_TYPE',
filter_value: 'GRITBIN'
-})));
+}));
-$(fixmystreet.add_assets($.extend({}, options, {
+fixmystreet.assets.add($.extend({}, options, {
asset_category: "Street Lighting",
asset_item: 'street light',
filter_key: 'COD_ASSET_TYPE',
filter_value: 'SL'
-})));
+}));
})();
diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js
index e24e76495..a6ecbadb2 100644
--- a/web/cobrands/fixmystreet/assets.js
+++ b/web/cobrands/fixmystreet/assets.js
@@ -17,7 +17,7 @@ function asset_selected(e) {
close_fault_popup();
var lonlat = e.feature.geometry.getBounds().getCenterLonLat();
- // Check if there is a known fault with the light that's been clicked,
+ // Check if there is a known fault with the asset that's been clicked,
// and disallow selection if so.
var fault_feature = find_matching_feature(e.feature, this.fixmystreet.fault_layer, this.fixmystreet.asset_id_field);
if (!!fault_feature) {
@@ -34,13 +34,18 @@ function asset_selected(e) {
// Set the extra field to the value of the selected feature
$.each(this.fixmystreet.attributes, function (field_name, attribute_name) {
- var id = e.feature.attributes[attribute_name];
- $("#form_" + field_name).val(id);
+ var field_value;
+ if (typeof attribute_name === 'function') {
+ field_value = attribute_name.apply(e.feature);
+ } else {
+ field_value = e.feature.attributes[attribute_name];
+ }
+ $("#form_" + field_name).val(field_value);
});
// Hide the normal markers layer to keep things simple, but
// move the green marker to the point of the click to stop
- // it jumping around unexpectedly if the user deselects street light.
+ // it jumping around unexpectedly if the user deselects the asset.
fixmystreet.markers.setVisibility(false);
fixmystreet.markers.features[0].move(lonlat);
@@ -108,7 +113,7 @@ function check_zoom_message_visibility() {
function layer_visibilitychanged() {
check_zoom_message_visibility.call(this);
- var layers = fixmystreet.map.getLayersByName('WFS');
+ var layers = fixmystreet.map.getLayersBy('assets', true);
var visible = 0;
for (var i = 0; i<layers.length; i++) {
if (layers[i].getVisibility()) {
@@ -121,7 +126,9 @@ function layer_visibilitychanged() {
// to show the marker again.
fixmystreet.markers.setVisibility(true);
}
- select_nearest_asset.call(this);
+ if (!this.fixmystreet.non_interactive) {
+ select_nearest_asset.call(this);
+ }
}
function zoom_to_assets(layer) {
@@ -184,6 +191,10 @@ function layer_loadend() {
}
function get_asset_stylemap() {
+ // fixmystreet.pin_prefix isn't always available here (e.g. on /report/new),
+ // so get it from the DOM directly
+ var pin_prefix = fixmystreet.pin_prefix || document.getElementById('js-map-data').getAttribute('data-pin_prefix');
+
return new OpenLayers.StyleMap({
'default': new OpenLayers.Style({
fillColor: "#FFFF00",
@@ -194,13 +205,13 @@ function get_asset_stylemap() {
pointRadius: 6
}),
'select': new OpenLayers.Style({
- externalGraphic: fixmystreet.pin_prefix + "pin-spot.png",
+ externalGraphic: pin_prefix + "pin-spot.png",
fillColor: "#55BB00",
graphicWidth: 48,
graphicHeight: 64,
graphicXOffset: -24,
graphicYOffset: -56,
- backgroundGraphic: fixmystreet.pin_prefix + "pin-shadow.png",
+ backgroundGraphic: pin_prefix + "pin-shadow.png",
backgroundWidth: 60,
backgroundHeight: 30,
backgroundXOffset: -7,
@@ -208,7 +219,7 @@ function get_asset_stylemap() {
popupYOffset: -40,
graphicOpacity: 1.0
}),
- 'temporary': new OpenLayers.Style({
+ 'hover': new OpenLayers.Style({
fillColor: "#55BB00",
fillOpacity: 0.8,
strokeColor: "#000000",
@@ -233,54 +244,57 @@ function get_fault_stylemap() {
});
}
-fixmystreet.add_assets = function(options) {
- var asset_layer = null;
- var asset_fault_layer = null;
+fixmystreet.assets = {
+ layers: [],
+ controls: [],
- function add_assets() {
- if (asset_layer !== null) {
- // Layer has already been added
- return;
- }
- if (window.fixmystreet === undefined) {
- // We're on a page without a map, yet somehow still got called...
- // Nothing to do.
- return;
- }
- if (fixmystreet.map === undefined) {
- // Map's not loaded yet, let's try again soon...
- setTimeout(add_assets, 250);
- return;
- }
- if (fixmystreet.page != 'new' && fixmystreet.page != 'around') {
- // We only want to show light markers when making a new report
- return;
- }
+ add: function(options) {
+ var asset_fault_layer = null;
- // An interactive layer for selecting a street light
- var protocol_options = {
- version: "1.1.0",
- url: options.wfs_url,
- featureType: options.wfs_feature,
- geometryName: options.geometryName
- };
- if (fixmystreet.wmts_config) {
- protocol_options.srsName = fixmystreet.wmts_config.map_projection;
- }
- if (options.propertyNames) {
- protocol_options.propertyNames = options.propertyNames;
+ // An interactive layer for selecting an asset (e.g. street light)
+ var protocol_options;
+ var protocol;
+ if (options.http_options !== undefined) {
+ protocol_options = OpenLayers.Util.extend(options.http_options, {});
+ if (protocol_options.format_class) {
+ protocol_options.format = new protocol_options.format_class(protocol_options.format_options);
+ } else {
+ protocol_options.format = new OpenLayers.Format.GML({
+ geometryName: options.geometryName
+ });
+ }
+ protocol = new OpenLayers.Protocol.HTTP(protocol_options);
+ } else {
+ protocol_options = {
+ version: "1.1.0",
+ url: options.wfs_url,
+ featureType: options.wfs_feature,
+ geometryName: options.geometryName
+ };
+ if (options.srsName !== undefined) {
+ protocol_options.srsName = options.srsName;
+ } else if (fixmystreet.wmts_config) {
+ protocol_options.srsName = fixmystreet.wmts_config.map_projection;
+ }
+ if (options.propertyNames) {
+ protocol_options.propertyNames = options.propertyNames;
+ }
+ protocol = new OpenLayers.Protocol.WFS(protocol_options);
}
- var protocol = new OpenLayers.Protocol.WFS(protocol_options);
+ var StrategyClass = options.strategy_class || OpenLayers.Strategy.BBOX;
var layer_options = {
fixmystreet: options,
- strategies: [new OpenLayers.Strategy.BBOX()],
+ strategies: [new StrategyClass()],
protocol: protocol,
visibility: false,
maxResolution: options.max_resolution,
minResolution: options.min_resolution,
- styleMap: get_asset_stylemap()
+ styleMap: options.stylemap || get_asset_stylemap(),
+ assets: true
};
- if (fixmystreet.wmts_config) {
+ if (options.srsName !== undefined) {
+ layer_options.projection = new OpenLayers.Projection(options.srsName);
+ } else if (fixmystreet.wmts_config) {
layer_options.projection = new OpenLayers.Projection(fixmystreet.wmts_config.map_projection);
}
if (options.filter_key) {
@@ -290,9 +304,10 @@ fixmystreet.add_assets = function(options) {
value: options.filter_value
});
}
- asset_layer = new OpenLayers.Layer.Vector("WFS", layer_options);
- // A non-interactive layer to display existing street light faults
+ var asset_layer = new OpenLayers.Layer.Vector(options.name || "WFS", layer_options);
+
+ // A non-interactive layer to display existing asset faults
if (options.wfs_fault_feature) {
var po = {
featureType: options.wfs_fault_feature
@@ -302,7 +317,8 @@ fixmystreet.add_assets = function(options) {
var lo = {
strategies: [new OpenLayers.Strategy.BBOX()],
protocol: fault_protocol,
- styleMap: get_fault_stylemap()
+ styleMap: get_fault_stylemap(),
+ assets: true
};
OpenLayers.Util.applyDefaults(lo, layer_options);
asset_fault_layer = new OpenLayers.Layer.Vector("WFS", lo);
@@ -311,81 +327,122 @@ fixmystreet.add_assets = function(options) {
asset_layer.fixmystreet.fault_layer = asset_fault_layer;
}
- // Set up handlers for selecting/unselecting markers and panning/zooming the map
- var select_feature_control = new OpenLayers.Control.SelectFeature( asset_layer );
- asset_layer.events.register( 'featureselected', asset_layer, asset_selected);
- asset_layer.events.register( 'featureunselected', asset_layer, asset_unselected);
- asset_layer.events.register( 'loadend', asset_layer, layer_loadend);
- asset_layer.events.register( 'visibilitychanged', asset_layer, layer_visibilitychanged);
- fixmystreet.map.events.register( 'zoomend', asset_layer, check_zoom_message_visibility);
+ var hover_feature_control, select_feature_control;
+ if (!options.non_interactive) {
+ // Set up handlers for selecting/unselecting markers
+ select_feature_control = new OpenLayers.Control.SelectFeature( asset_layer );
+ asset_layer.events.register( 'featureselected', asset_layer, asset_selected);
+ asset_layer.events.register( 'featureunselected', asset_layer, asset_unselected);
+ // When panning/zooming the map check that this layer is still correctly shown
+ // and any selected marker is preserved
+ asset_layer.events.register( 'loadend', asset_layer, layer_loadend);
+ }
+
+ // Even if an asset layer is marked as non-interactive it can still have
+ // a hover style which we'll need to set up.
+ if (!options.non_interactive || (options.stylemap && options.stylemap.styles.hover)) {
+ // Set up handlers for simply hovering over an asset marker
+ hover_feature_control = new OpenLayers.Control.SelectFeature(
+ asset_layer,
+ {
+ hover: true,
+ highlightOnly: true,
+ renderIntent: 'hover'
+ }
+ );
+ hover_feature_control.events.register('beforefeaturehighlighted', null, function(e) {
+ // Don't let marker go from selected->hover state,
+ // as it causes some mad flickering effect.
+ if (e.feature.renderIntent == 'select') {
+ return false;
+ }
+ });
+ }
+ if (!options.always_visible) {
+ asset_layer.events.register( 'visibilitychanged', asset_layer, layer_visibilitychanged);
+ }
// Make sure the user knows something is happening (some asset layers can be sllooowwww)
asset_layer.events.register( 'loadstart', null, fixmystreet.maps.loading_spinner.show);
asset_layer.events.register( 'loadend', null, fixmystreet.maps.loading_spinner.hide);
- // Set up handlers for simply hovering over a street light marker
- var hover_feature_control = new OpenLayers.Control.SelectFeature(
- asset_layer,
- {
- hover: true,
- highlightOnly: true,
- renderIntent: 'temporary'
- }
- );
- hover_feature_control.events.register('beforefeaturehighlighted', null, function(e) {
- // Don't let marker go from selected->hover state,
- // as it causes some mad flickering effect.
- if (e.feature.renderIntent == 'select') {
- return false;
- }
- });
-
- fixmystreet.map.addLayer(asset_layer);
+ fixmystreet.assets.layers.push(asset_layer);
+ if (options.always_visible) {
+ asset_layer.setVisibility(true);
+ }
if (asset_fault_layer) {
- fixmystreet.map.addLayer(asset_fault_layer);
+ fixmystreet.assets.layers.push(asset_fault_layer);
+ }
+ if (hover_feature_control) {
+ fixmystreet.assets.controls.push(hover_feature_control);
+ }
+ if (select_feature_control) {
+ fixmystreet.assets.controls.push(select_feature_control);
}
- fixmystreet.map.addControl( hover_feature_control );
- hover_feature_control.activate();
- fixmystreet.map.addControl( select_feature_control );
- select_feature_control.activate();
- // Make sure the fault markers always appear beneath the street lights
+ // Make sure the fault markers always appear beneath the linked assets
if (asset_fault_layer) {
asset_fault_layer.setZIndex(asset_layer.getZIndex()-1);
}
- // Show/hide the asset layer when the category is chosen
- $("#problem_form").on("change.category", "select#form_category", function(){
- var category = $(this).val();
- if (category == options.asset_category) {
- asset_layer.setVisibility(true);
- if (asset_fault_layer) {
- asset_fault_layer.setVisibility(true);
+ if (!asset_layer.fixmystreet.always_visible) {
+ // Show/hide the asset layer when the category is chosen
+ $("#problem_form").on("change.category", "select#form_category", function(){
+ var category = $(this).val();
+ if (category == options.asset_category) {
+ asset_layer.setVisibility(true);
+ if (asset_fault_layer) {
+ asset_fault_layer.setVisibility(true);
+ }
+ zoom_to_assets(asset_layer);
+ } else {
+ asset_layer.setVisibility(false);
+ if (asset_fault_layer) {
+ asset_fault_layer.setVisibility(false);
+ }
}
- zoom_to_assets(asset_layer);
- } else {
- asset_layer.setVisibility(false);
- if (asset_fault_layer) {
- asset_fault_layer.setVisibility(false);
+ });
+ }
+ },
+
+ init: function() {
+ if (fixmystreet.page != 'new' && fixmystreet.page != 'around') {
+ // We only want to show asset markers when making a new report
+ return;
+ }
+
+ // Make sure the assets get hidden if the back button is pressed
+ fixmystreet.maps.display_around = (function(original) {
+ function hide_assets() {
+ for (var i = 0; i < fixmystreet.assets.layers.length; i++) {
+ var layer = fixmystreet.assets.layers[i];
+ if (!layer.fixmystreet.always_visible) {
+ layer.setVisibility(false);
+ }
}
+ fixmystreet.markers.setVisibility(true);
+ original.apply(fixmystreet.maps);
}
- });
- }
-
- // Make sure the assets get hidden if the back button is pressed
- fixmystreet.maps.display_around = (function(original) {
- function hide_assets() {
- asset_layer.setVisibility(false);
- if (asset_fault_layer) {
- asset_fault_layer.setVisibility(false);
+ return hide_assets;
+ })(fixmystreet.maps.display_around);
+
+ for (var i = 0; i < fixmystreet.assets.layers.length; i++) {
+ var layer = fixmystreet.assets.layers[i];
+ fixmystreet.map.addLayer(layer);
+ if (layer.fixmystreet.asset_category) {
+ fixmystreet.map.events.register( 'zoomend', layer, check_zoom_message_visibility);
}
- fixmystreet.markers.setVisibility(true);
- original.apply(fixmystreet.maps);
}
- return hide_assets;
- })(fixmystreet.maps.display_around);
- return add_assets;
+ for (i = 0; i < fixmystreet.assets.controls.length; i++) {
+ fixmystreet.map.addControl(fixmystreet.assets.controls[i]);
+ fixmystreet.assets.controls[i].activate();
+ }
+ }
};
+$(function() {
+ fixmystreet.assets.init();
+});
+
})();
diff --git a/web/cobrands/fixmystreet/staff.js b/web/cobrands/fixmystreet/staff.js
index f2b98744b..37bfeabaf 100644
--- a/web/cobrands/fixmystreet/staff.js
+++ b/web/cobrands/fixmystreet/staff.js
@@ -432,8 +432,8 @@ $.extend(fixmystreet.set_up, {
$.extend(fixmystreet.hooks, {
update_problem_fields: function(args) {
if (args.prefill_reports && args.role == 'inspector') {
- var title = args.category + ' problem has been scheduled for fixing';
- var description = args.category + ' problem found - scheduled for fixing by ' + args.body;
+ var title = 'A ' + args.category + ' problem has been found';
+ var description = 'A ' + args.category + ' problem has been found by ' + args.body;
var $title_field = $('#form_title');
var $description_field = $('#form_detail');
diff --git a/web/vendor/OpenLayers.Projection.OrdnanceSurvey.js b/web/vendor/OpenLayers.Projection.OrdnanceSurvey.js
index 85574d8e0..339f57a93 100644
--- a/web/vendor/OpenLayers.Projection.OrdnanceSurvey.js
+++ b/web/vendor/OpenLayers.Projection.OrdnanceSurvey.js
@@ -107,11 +107,19 @@ OpenLayers.Projection.OS = {
},
goog2osgb: function(point) {
- return OpenLayers.Projection.OS.projectForwardBritish(OpenLayers.Layer.SphericalMercator.projectInverse(point));
+ var p1 = OpenLayers.Layer.SphericalMercator.inverseMercator(point.x, point.y);
+ var p2 = OpenLayers.Projection.OS.projectForwardBritish({x: p1.lon, y: p1.lat});
+ point.x = p2.x;
+ point.y = p2.y;
+ return point;
},
osgb2goog: function(point) {
- return OpenLayers.Layer.SphericalMercator.projectForward(OpenLayers.Projection.OS.projectInverseBritish(point));
+ var p1 = OpenLayers.Projection.OS.projectInverseBritish(point);
+ var p2 = OpenLayers.Layer.SphericalMercator.forwardMercator(p1.x, p1.y);
+ point.x = p2.lon;
+ point.y = p2.lat;
+ return point;
},
/*****