aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.cypress/cypress/fixtures/iow_roadworks.json97
-rw-r--r--.cypress/cypress/integration/isleofwight.js35
-rwxr-xr-xbin/browser-tests4
-rwxr-xr-xbin/fixmystreet.com/fixture31
-rw-r--r--bin/fixmystreet.com/island_roads_setup_messages73
-rwxr-xr-xbin/fixmystreet.com/setup_island_roads_triage_cats133
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm3
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin/Triage.pm163
-rw-r--r--perllib/FixMyStreet/App/Controller/Around.pm14
-rw-r--r--perllib/FixMyStreet/App/Controller/Report.pm11
-rw-r--r--perllib/FixMyStreet/App/Controller/Report/New.pm19
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm5
-rw-r--r--perllib/FixMyStreet/Cobrand/FixMyStreet.pm112
-rw-r--r--perllib/FixMyStreet/Cobrand/IsleOfWight.pm236
-rw-r--r--perllib/FixMyStreet/Cobrand/UKCouncils.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/Comment.pm2
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm2
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm6
-rw-r--r--perllib/FixMyStreet/Map/IsleOfWight.pm63
-rw-r--r--perllib/FixMyStreet/SendReport/Triage.pm20
-rwxr-xr-xperllib/Open311/PostServiceRequestUpdates.pm10
-rw-r--r--t/Mock/MapIt.pm1
-rw-r--r--t/app/controller/admin/triage.t126
-rw-r--r--t/app/controller/report_new_open311.t2
-rw-r--r--t/cobrand/isleofwight.t567
-rw-r--r--t/map/tests.t1
-rw-r--r--t/open311/getservicerequestupdates.t46
-rw-r--r--templates/email/isleofwight/_council_reference.html4
-rw-r--r--templates/email/isleofwight/_council_reference.txt2
-rw-r--r--templates/email/isleofwight/_council_reference_alert_update.html4
-rw-r--r--templates/email/isleofwight/_council_reference_alert_update.txt2
-rw-r--r--templates/email/isleofwight/_email_color_overrides.html19
-rw-r--r--templates/email/isleofwight/confirm_report_sent.html42
-rw-r--r--templates/email/isleofwight/confirm_report_sent.txt43
-rw-r--r--templates/email/isleofwight/problem-confirm.html31
-rw-r--r--templates/email/isleofwight/problem-confirm.txt31
-rw-r--r--templates/email/isleofwight/signature.txt2
-rw-r--r--templates/web/base/admin/report-category.html5
-rw-r--r--templates/web/base/admin/triage/_inspect.html77
-rw-r--r--templates/web/base/admin/triage/_list-filters.html53
-rw-r--r--templates/web/base/admin/triage/index.html42
-rw-r--r--templates/web/base/report/_inspect.html67
-rw-r--r--templates/web/base/report/inspect/information.html56
-rw-r--r--templates/web/base/report/inspect/public_update.html14
-rw-r--r--templates/web/base/report/new/category_extras.html2
-rw-r--r--templates/web/base/report/new/councils_text_all.html2
-rw-r--r--templates/web/base/report/updates.html3
-rwxr-xr-xtemplates/web/base/reports/body.html2
-rw-r--r--templates/web/fixmystreet.com/footer_extra_js.html1
-rw-r--r--templates/web/hounslow/report/new/councils_text_all.html8
-rw-r--r--templates/web/isleofwight/about/mapterms.html24
-rw-r--r--templates/web/isleofwight/footer_extra_js.html10
-rw-r--r--templates/web/isleofwight/header_extra.html1
-rw-r--r--templates/web/isleofwight/header_logo.html2
-rw-r--r--templates/web/isleofwight/main_nav_items.html59
-rw-r--r--templates/web/isleofwight/report/_updates_disallowed_message.html8
-rw-r--r--templates/web/isleofwight/report/inspect.html10
-rw-r--r--templates/web/isleofwight/report/new/_form_labels.html3
-rw-r--r--templates/web/isleofwight/tokens/_confirm_problem_council_id.html2
-rw-r--r--templates/web/isleofwight/tracking_code.html16
-rw-r--r--web/cobrands/fixmystreet/assets.js26
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js9
-rw-r--r--web/cobrands/fixmystreet/staff.js29
-rw-r--r--web/cobrands/isleofwight/_colours.scss31
-rw-r--r--web/cobrands/isleofwight/assets.js311
-rw-r--r--web/cobrands/isleofwight/base.scss18
l---------web/cobrands/isleofwight/images/email-logo.gif1
-rw-r--r--web/cobrands/isleofwight/images/logo.gifbin0 -> 4924 bytes
-rw-r--r--web/cobrands/isleofwight/js.js33
-rw-r--r--web/cobrands/isleofwight/layout.scss26
-rw-r--r--web/js/map-OpenLayers.js2
-rw-r--r--web/js/map-wmts-isleofwight.js206
72 files changed, 2987 insertions, 140 deletions
diff --git a/.cypress/cypress/fixtures/iow_roadworks.json b/.cypress/cypress/fixtures/iow_roadworks.json
new file mode 100644
index 000000000..b20dd8514
--- /dev/null
+++ b/.cypress/cypress/fixtures/iow_roadworks.json
@@ -0,0 +1,97 @@
+{
+ "query": {
+ "recordcount": 38,
+ "columnlist": "se_id,phase_id,u_se_id,longitude,latitude,gsymbol_id,tooltip,swtype,org_name_disp,promoter,source,promoter_works_ref,originator_ref,swa_org_ref,promoter_org_ref,publisher_orgref,publisher_organisation_id,promoter_organisation_id,organisation_id,lha_id,start_date,end_date,works_state,impact,works_desc,geom_type,geojson_wgs84,tm_cat",
+ "data": {
+ "se_id": [
+ 114013162
+ ],
+ "phase_id": [
+ 1
+ ],
+ "u_se_id": [
+ "114013162:1"
+ ],
+ "longitude": [
+ -1.29574
+ ],
+ "latitude": [
+ 50.71086
+ ],
+ "gsymbol_id": [
+ "gcln01y"
+ ],
+ "tooltip": [
+ "B3401 Whitepit Lane, Newport, Isle of Wight\\n18 Jun 2019 - 23 Jul 2019\\ndelays unlikely"
+ ],
+ "swtype": [
+ "cw"
+ ],
+ "org_name_disp": [
+ "Island Roads on behalf of the Isle of Wight Council"
+ ],
+ "promoter": [
+ "Island Roads on behalf of the Isle of Wight Council"
+ ],
+ "source": [
+ "SW"
+ ],
+ "promoter_works_ref": [
+ "RF101BT0103000021728"
+ ],
+ "originator_ref": [
+ "RF101BT0103000021728"
+ ],
+ "swa_org_ref": [
+ 2114
+ ],
+ "promoter_org_ref": [
+ 2114
+ ],
+ "publisher_orgref": [
+ 2114
+ ],
+ "publisher_organisation_id": [
+ 1062
+ ],
+ "promoter_organisation_id": [
+ 1062
+ ],
+ "organisation_id": [
+ 1062
+ ],
+ "lha_id": [
+ 62
+ ],
+ "start_date": [
+ "{ts '2019-06-18 00:00:00'}"
+ ],
+ "end_date": [
+ "{ts '2030-07-23 23:59:59'}"
+ ],
+ "works_state": [
+ 4
+ ],
+ "impact": [
+ 1
+ ],
+ "works_desc": [
+ "Parapet improvement NEWPORT"
+ ],
+ "geom_type": [
+ 1
+ ],
+ "geojson_wgs84": [
+ "{\"type\":\"Point\",\"coordinates\":[-1.295784,50.71086]}"
+ ],
+ "tm_cat": [
+ ""
+ ]
+ }
+ },
+ "reqtoken": "",
+ "filterimpact": "1,2,3,4",
+ "filterenddate": "16/10/2019",
+ "filterstartdate": "16/07/2019",
+ "timeperiod": "cw"
+}
diff --git a/.cypress/cypress/integration/isleofwight.js b/.cypress/cypress/integration/isleofwight.js
new file mode 100644
index 000000000..daa69f36a
--- /dev/null
+++ b/.cypress/cypress/integration/isleofwight.js
@@ -0,0 +1,35 @@
+describe('When you look at the Island Roads site', function() {
+
+ beforeEach(function() {
+ cy.server();
+ cy.fixture('roads.xml');
+ cy.route('/report/new/ajax*').as('report-ajax');
+ cy.visit('http://isleofwight.localhost:3001/');
+ cy.contains('Island Roads');
+ cy.get('[name=pc]').type('PO30 5XJ');
+ cy.get('[name=pc]').parents('form').submit();
+ });
+
+ it('uses the correct name', function() {
+ cy.get('#map_box').click();
+ cy.wait('@report-ajax');
+ cy.get('select:eq(4)').select('Potholes');
+ cy.contains('sent to Island Roads');
+ cy.get('select:eq(4)').select('Private');
+ cy.contains('sent to Island Roads');
+ cy.get('select:eq(4)').select('Extra');
+ cy.contains('Help Island Roads');
+ });
+
+ it('displays nearby roadworks', function() {
+ cy.fixture('iow_roadworks.json');
+ cy.route('/data/**', 'fixture:iow_roadworks.json').as('roadworks');
+ cy.visit('http://isleofwight.localhost:3001/');
+ cy.get('[name=pc]').type('PO30 5XJ');
+ cy.get('[name=pc]').parents('form').submit();
+ cy.get('#map_box').click();
+ cy.wait('@report-ajax');
+ cy.wait('@roadworks');
+ cy.contains('Roadworks are scheduled near this location');
+ });
+});
diff --git a/bin/browser-tests b/bin/browser-tests
index 013c0d8d3..0180db0b5 100755
--- a/bin/browser-tests
+++ b/bin/browser-tests
@@ -11,7 +11,7 @@ my ($cobrand, $coords, $area_id, $name, $mapit_url);
BEGIN {
$config_file = 'conf/general.yml-example';
- $cobrand = [ 'borsetshire', 'fixmystreet', 'northamptonshire', 'bathnes', 'buckinghamshire', 'hounslow' ];
+ $cobrand = [ 'borsetshire', 'fixmystreet', 'northamptonshire', 'bathnes', 'buckinghamshire', 'hounslow', 'isleofwight' ];
$coords = '51.532851,-2.284277';
$area_id = 2608;
$name = 'Borsetshire';
@@ -150,7 +150,7 @@ browser-tests [running options] [fixture options] [cypress options]
--help this help message
Fixture option:
- --cobrand Cobrand(s) to use, default is fixmystreet,northamptonshire,bathnes,buckinghamshire
+ --cobrand Cobrand(s) to use, default is fixmystreet,northamptonshire,bathnes,buckinghamshire,isleofwight
--coords Default co-ordinates for created reports
--area_id Area ID to use for created body
--name Name to use for created body
diff --git a/bin/fixmystreet.com/fixture b/bin/fixmystreet.com/fixture
index 760c76414..1f6063a47 100755
--- a/bin/fixmystreet.com/fixture
+++ b/bin/fixmystreet.com/fixture
@@ -99,6 +99,7 @@ if ($opt->test_fixtures) {
{ area_id => 2257, categories => ['Flytipping', 'Graffiti'], name => 'Chiltern District Council' },
{ area_id => 2397, categories => [ 'Graffiti' ], name => 'Northampton Borough Council' },
{ area_id => 2483, categories => [ 'Potholes', 'Other' ], name => 'Hounslow Borough Council' },
+ { area_id => 2636, categories => [ 'Potholes', 'Private', 'Extra' ], name => 'Isle of Wight Council' },
) {
$bodies->{$_->{area_id}} = FixMyStreet::DB::Factory::Body->find_or_create($_);
my $cats = join(', ', @{$_->{categories}});
@@ -144,6 +145,36 @@ if ($opt->test_fixtures) {
$child_cat->update({
non_public => 1
});
+
+ $child_cat = FixMyStreet::DB->resultset("Contact")->find({
+ body => $bodies->{2636},
+ category => 'Potholes',
+ });
+ $child_cat->update({
+ send_method => 'Triage'
+ });
+ $child_cat = FixMyStreet::DB->resultset("Contact")->find({
+ body => $bodies->{2636},
+ category => 'Private',
+ });
+ $child_cat->update({
+ non_public => 1,
+ send_method => 'Triage'
+ });
+ $child_cat = FixMyStreet::DB->resultset("Contact")->find({
+ body => $bodies->{2636},
+ category => 'Extra',
+ });
+ $child_cat->update({
+ send_method => 'Triage'
+ });
+ $child_cat->set_extra_fields({
+ code => 'extra',
+ datatype => 'string',
+ order => 1,
+ variable => 'true',
+ });
+ $child_cat->update;
}
FixMyStreet::DB::Factory::ResponseTemplate->create({
diff --git a/bin/fixmystreet.com/island_roads_setup_messages b/bin/fixmystreet.com/island_roads_setup_messages
new file mode 100644
index 000000000..4969f18ba
--- /dev/null
+++ b/bin/fixmystreet.com/island_roads_setup_messages
@@ -0,0 +1,73 @@
+#!/usr/bin/env perl
+#
+# One off script to transfer the hardcoded JS messages to the database
+
+use strict;
+use warnings;
+use v5.14;
+
+BEGIN {
+ use File::Basename qw(dirname);
+ use File::Spec;
+ my $d = dirname(File::Spec->rel2abs($0));
+ require "$d/../../setenv.pl";
+}
+
+use FixMyStreet::DB;
+
+use Getopt::Long;
+
+my $commit;
+GetOptions(
+ 'commit' => \$commit,
+);
+
+if (!$commit) {
+ say "*** DRY RUN ***";
+}
+
+my $urgent = {
+ order => 0,
+ required => 'true',
+ protected => 'true',
+ code => 'urgent',
+ description => 'To ensure your report is dealt with effectively, please tell us the severity of the issue:-',
+ datatype_description => 'You have indicated that the issue requires an urgent response, please phone Island Roads on 01983 822440 so that we can respond to the issue appropriately.',
+ datatype => 'singlevaluelist',
+ variable => 'true',
+ values => [
+ {
+ key => 'urgent',
+ name => 'The issue requires an urgent response/action',
+ disable => 1,
+ },
+ {
+ key => 'not_urgent',
+ name => 'The issue requires a routine/non-urgent response/action',
+ }
+ ],
+};
+
+my $iow = FixMyStreet::DB->resultset("Body")->find({ name => 'Isle of Wight Council' });
+if ($iow) {
+ my @iow_contacts = $iow->contacts->search({ send_method => 'Triage' })->all;
+ foreach my $category (@iow_contacts) {
+ my $extra_fields = $category->get_extra_fields;
+ my $found = 0;
+ foreach (@$extra_fields) {
+ next unless $_->{code} eq 'urgent';
+ $_ = $urgent;
+ $found = 1;
+ }
+ if (!$found) {
+ push @$extra_fields, $urgent;
+ }
+ $category->set_extra_fields(@$extra_fields);
+ say "Making emergency message disable form on " . $category->category . ", Isle of Wight";
+ if ($commit) {
+ $category->update;
+ }
+ }
+} else {
+ say STDERR "Could not find IoW";
+}
diff --git a/bin/fixmystreet.com/setup_island_roads_triage_cats b/bin/fixmystreet.com/setup_island_roads_triage_cats
new file mode 100755
index 000000000..b747fb99b
--- /dev/null
+++ b/bin/fixmystreet.com/setup_island_roads_triage_cats
@@ -0,0 +1,133 @@
+#!/usr/bin/env perl
+
+=head1 NAME
+
+setup_island_roads_triage_cats - create/update triage contacts for Island Roads cobrand
+
+=head1 DESCRIPTION
+
+This script creates a set of contacts for Island Road to be used as part of their triage
+system. The contacts created all have the `Triage` send_method and so will be displayed
+to non staff users.
+
+It also adds the relevant extra fields to the contacts to enable asset details to be
+added to a report created in the category.
+
+If a contact with the same category already exists that does not have a send_method of
+`Triage` then the script will emit a warning. Any existing contacts with the `Triage`
+send_method will have their state reset to `confirmed`.
+
+=cut
+
+use v5.14;
+use warnings;
+
+BEGIN {
+ use File::Basename qw(dirname);
+ use File::Spec;
+ my $d = dirname(File::Spec->rel2abs($0));
+ require "$d/../../setenv.pl";
+}
+
+
+my @cat_list = (
+ "Dog Fouling",
+ "Manholes",
+ "Trees & Hedges",
+ "Pavements/footpaths",
+ "Drainage",
+ "Car Parking",
+ "Street Lighting",
+ "Bus Stops",
+ "Flyposting",
+ "Potholes",
+ "Street Cleaning",
+ "Bridges & Walls",
+ "Traffic Lights",
+ "Street Furniture",
+ "Roads/Highways",
+ "Road Traffic Signs & Markings",
+ "Grass Verges & Weeds",
+ "Flytipping",
+ "Graffiti",
+ "Street Nameplates",
+ "Abandoned Vehicles"
+);
+
+use FixMyStreet::DB;
+use FixMyStreet::Cobrand::IsleOfWight;
+
+my $iow = FixMyStreet::DB->resultset("Body")->search({
+ name => "Isle of Wight Council"
+});
+
+my $cobrand = FixMyStreet::Cobrand::IsleOfWight->new;
+
+if ($iow->count != 1) {
+ die "Could not find IoW body\n";
+}
+
+$iow = $iow->first;
+
+for my $cat (@cat_list) {
+
+ my $existing = FixMyStreet::DB->resultset("Contact")->search({
+ category => $cat, body_id => $iow->id
+ })->first;
+
+ if ( $existing ) {
+ if (!$existing->send_method || $existing->send_method ne 'Triage') {
+ warn "$cat is not a Triage category\n";
+ next;
+ }
+ # make sure category is not deleted
+ $existing->state('confirmed');
+ } else {
+ $existing = FixMyStreet::DB->resultset('Contact')->create({
+ name => $cat,
+ body => $iow,
+ send_method => 'Triage',
+ state => 'confirmed',
+ editor => $0,
+ note => 'created automatically by script',
+ });
+ }
+
+ my $extra_fields = $existing->get_extra_fields;
+ my @meta = grep { $_->{code} ne 'central_asset_id' && $_->{code} ne 'site_code'} @$extra_fields;
+
+ push @meta,
+ {
+ code => 'central_asset_id',
+ datatype => 'string',
+ description => 'central asset id',
+ order => 100,
+ required => 'false',
+ variable => 'true',
+ automated => 'hidden_field',
+ },
+ {
+ code => 'asset_details',
+ datatype => 'string',
+ description => 'asset details',
+ order => 100,
+ required => 'false',
+ variable => 'true',
+ automated => 'hidden_field',
+ },
+ {
+ code => 'site_code',
+ datatype => 'string',
+ description => 'site code',
+ order => 100,
+ required => 'false',
+ variable => 'true',
+ automated => 'hidden_field',
+ };
+
+ $cobrand->call_hook(
+ open311_contact_meta_override => {}, $existing, \@meta);
+
+ $existing->set_extra_fields(@meta);
+ $existing->update;
+}
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 &copy; 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);
diff --git a/t/Mock/MapIt.pm b/t/Mock/MapIt.pm
index b5cc694df..8b8bb5978 100644
--- a/t/Mock/MapIt.pm
+++ b/t/Mock/MapIt.pm
@@ -49,6 +49,7 @@ my @PLACES = (
[ 'TA1 1QP', 51.023569, -3.099055, 2239, 'Somerset County Council', 'CTY', 2429, 'Taunton Deane Borough Council', 'DIS' ],
[ 'GU51 4AE', 51.279456, -0.846216, 2333, 'Hart District Council', 'DIS', 2227, 'Hampshire County Council', 'CTY' ],
[ 'WS1 4NH', 52.563074, -1.991032, 2535, 'Sandwell Borough Council', 'MTD' ],
+ [ 'PO30 5XJ', 50.71086, -1.29573, 2636, 'Isle of Wight Council', 'UTA' ],
[ 'OX28 4DS', 51.784721, -1.494453 ],
[ 'E14 2DN', 51.508536, '0.000001' ],
# Norway
diff --git a/t/app/controller/admin/triage.t b/t/app/controller/admin/triage.t
new file mode 100644
index 000000000..6c84d1ff4
--- /dev/null
+++ b/t/app/controller/admin/triage.t
@@ -0,0 +1,126 @@
+use FixMyStreet::TestMech;
+use FixMyStreet::Script::Alerts;
+
+my $mech = FixMyStreet::TestMech->new;
+
+my $user = $mech->create_user_ok('test@example.com', name => 'Test User');
+my $user2 = $mech->create_user_ok('test2@example.com', name => 'Test User 2');
+my $superuser = $mech->create_user_ok(
+ 'superuser@example.com',
+ name => 'Super User',
+ is_superuser => 1
+);
+
+my $iow = $mech->create_body_ok(2636, 'Isle of Wight Council', { can_be_devolved => 1 } );
+my $iow_contact = $mech->create_contact_ok(
+ body_id => $iow->id,
+ category => 'Potholes',
+ email => 'potholes@example.com',
+ send_method => 'Triage'
+);
+$mech->create_contact_ok(
+ body_id => $iow->id,
+ category => 'Traffic lights',
+ email => 'lights@example.com'
+);
+
+my $dt = DateTime->now();
+
+my ($report) = $mech->create_problems_for_body(
+ 1,
+ $iow->id,
+ 'TITLE',
+ {
+ areas => 2636,
+ category => 'Potholes',
+ whensent => $dt,
+ latitude => 50.71086,
+ longitude => -1.29573,
+ send_method_used => 'Triage',
+ }
+);
+
+FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+}, sub {
+ subtest "user can access triage page with triage permission" => sub {
+ $user->update({ from_body => $iow });
+ $mech->log_out_ok;
+ $mech->get_ok('/admin/triage');
+
+ $mech->log_in_ok($user->email);
+ $mech->get('/admin/triage');
+ is $mech->res->code, 403, 'permission denied';
+
+ $user->user_body_permissions->create( { body => $iow, permission_type => 'triage' } );
+ $mech->get_ok('/admin/triage');
+ };
+
+ subtest "reports marked for triage show triage interface" => sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok( $user->email );
+
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('CONFIRM Subject');
+
+ $report->update( { state => 'for triage' } );
+
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_contains('CONFIRM Subject');
+ };
+
+ subtest "changing report category marks report as confirmed" => sub {
+ my $report_url = '/report/' . $report->id;
+ $mech->get_ok($report_url);
+
+ my $alert = FixMyStreet::App->model('DB::Alert')->create(
+ {
+ user => $user2,
+ alert_type => 'new_updates',
+ parameter => $report->id,
+ parameter2 => '',
+ confirmed => 1,
+ }
+ );
+
+ $mech->content_contains('Traffic lights');
+
+ $mech->submit_form_ok( {
+ with_fields => {
+ category => 'Traffic lights',
+ include_update => 0,
+ }
+ },
+ 'triage form submitted'
+ );
+
+ $mech->content_contains('Potholes');
+
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'report marked as confirmed';
+ ok !$report->whensent, 'report marked to resend';
+
+ my @comments = $report->comments;
+ my $comment = $comments[0];
+ my $extra = $comment->get_extra_metadata();
+ is $extra->{triage_report}, 1, 'comment indicates it is for triage in extra';
+ is $extra->{holding_category}, 'Potholes', 'comment extra has previous category';
+ is $extra->{new_category}, 'Traffic lights', 'comment extra has new category';
+ ok $comment->whensent, 'comment is marked as sent';
+
+ $mech->get_ok($report_url);
+ $mech->content_contains('Report triaged from Potholes to Traffic lights');
+
+ $mech->log_out_ok;
+ $mech->get_ok($report_url);
+ $mech->content_lacks('Report triaged from Potholes to Traffic lights');
+
+ $mech->clear_emails_ok;
+ FixMyStreet::Script::Alerts::send();
+ $mech->email_count_is(0);
+ };
+};
+
+done_testing();
diff --git a/t/app/controller/report_new_open311.t b/t/app/controller/report_new_open311.t
index 52f1ddc6e..a0d122a7b 100644
--- a/t/app/controller/report_new_open311.t
+++ b/t/app/controller/report_new_open311.t
@@ -203,6 +203,8 @@ foreach my $test (
# check that we got the errors expected
is_deeply $mech->page_errors, $test->{errors}, "check errors";
+ $mech->content_contains('Help <strong>Borsetshire Council</strong> resolve your problem quicker');
+
# check that fields have changed as expected
my $new_values = {
%{ $test->{fields} }, # values added to form
diff --git a/t/cobrand/isleofwight.t b/t/cobrand/isleofwight.t
new file mode 100644
index 000000000..67088bc54
--- /dev/null
+++ b/t/cobrand/isleofwight.t
@@ -0,0 +1,567 @@
+use CGI::Simple;
+use DateTime;
+use FixMyStreet::TestMech;
+use Open311;
+use Open311::GetServiceRequests;
+use Open311::GetServiceRequestUpdates;
+use Open311::PostServiceRequestUpdates;
+use FixMyStreet::Script::Alerts;
+use FixMyStreet::Script::Reports;
+
+ok( my $mech = FixMyStreet::TestMech->new, 'Created mech object' );
+
+my $params = {
+ send_method => 'Open311',
+ send_comments => 1,
+ api_key => 'KEY',
+ endpoint => 'endpoint',
+ jurisdiction => 'home',
+ can_be_devolved => 1,
+};
+my $isleofwight = $mech->create_body_ok(2636, 'Isle of Wight Council', $params);
+my $contact = $mech->create_contact_ok(
+ body_id => $isleofwight->id,
+ category => 'Potholes',
+ email => 'pothole@example.org',
+);
+$contact->set_extra_fields( ( {
+ code => 'urgent',
+ datatype => 'string',
+ description => 'question',
+ variable => 'true',
+ required => 'false',
+ order => 1,
+ datatype_description => 'datatype',
+} ) );
+$contact->update;
+
+my $user = $mech->create_user_ok('user@example.org', name => 'Test User');
+my $iow_user = $mech->create_user_ok('iow_user@example.org', name => 'IoW User', from_body => $isleofwight);
+$iow_user->user_body_permissions->create({
+ body => $isleofwight,
+ permission_type => 'moderate',
+});
+
+my $contact2 = $mech->create_contact_ok(
+ body_id => $isleofwight->id,
+ category => 'Roads',
+ email => 'roads@example.org',
+ send_method => 'Triage',
+);
+
+my $admin_user = $mech->create_user_ok('admin-user@example.org', name => 'Admin User', from_body => $isleofwight);
+
+$admin_user->user_body_permissions->create({
+ body => $isleofwight,
+ permission_type => 'triage'
+});
+
+my @reports = $mech->create_problems_for_body(1, $isleofwight->id, 'An Isle of wight report', {
+ confirmed => '2019-05-25 09:00',
+ lastupdate => '2019-05-25 09:00',
+ latitude => 50.7108,
+ longitude => -1.29573,
+ user => $user,
+ external_id => 101202303
+});
+
+subtest "check clicking all reports link" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $mech->get_ok('/');
+ $mech->follow_link_ok({ text => 'All reports' });
+ };
+
+ $mech->content_contains("An Isle of wight report", "Isle of Wight report there");
+ $mech->content_contains("Island Roads", "is still on cobrand");
+};
+
+subtest "use external id for reference number" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $mech->get_ok('/report/' . $reports[0]->id);
+ };
+
+ $mech->content_contains("101202303", "Display external id as reference number");
+};
+
+subtest "only original reporter can comment" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $mech->get_ok('/report/' . $reports[0]->id);
+ $mech->content_contains('Only the original reporter may leave updates');
+
+ $mech->log_in_ok('user@example.org');
+ $mech->get_ok('/report/' . $reports[0]->id);
+ $mech->content_lacks('Only the original reporter may leave updates');
+ };
+};
+
+subtest "check moderation label uses correct name" => sub {
+ my $REPORT_URL = '/report/' . $reports[0]->id;
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight'],
+ }, sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok( $iow_user->email );
+ $mech->get_ok($REPORT_URL);
+ $mech->content_lacks('show-moderation');
+ $mech->follow_link_ok({ text_regex => qr/^Moderate$/ });
+ $mech->content_contains('show-moderation');
+ $mech->submit_form_ok({ with_fields => {
+ problem_title => 'Good good',
+ problem_detail => 'Good good improved',
+ }});
+ $mech->base_like( qr{\Q$REPORT_URL\E} );
+ $mech->content_like(qr/Moderated by Island Roads/);
+ };
+};
+
+$_->delete for @reports;
+
+my $system_user = $mech->create_user_ok('system_user@example.org');
+
+for my $status ( qw/ CLOSED FIXED DUPLICATE NOT_COUNCILS_RESPONSIBILITY NO_FURTHER_ACTION / ) {
+ subtest "updates which mark report as $status close it to comments" => sub {
+ my $dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new)->add( minutes => -5 );
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, '', { lastupdate => $dt });
+ $p->update({ external_id => $p->id });
+
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests_updates>
+ <request_update>
+ <update_id>UPDATE_ID</update_id>
+ <service_request_id>SERVICE_ID</service_request_id>
+ <service_request_id_ext>ID_EXTERNAL</service_request_id_ext>
+ <status>STATUS</status>
+ <description>This is a note</description>
+ <updated_datetime>UPDATED_DATETIME</updated_datetime>
+ </request_update>
+ </service_requests_updates>
+ };
+
+ my $update_dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new);
+
+ $requests_xml =~ s/STATUS/$status/;
+ $requests_xml =~ s/UPDATE_ID/@{[$p->id]}/;
+ $requests_xml =~ s/SERVICE_ID/@{[$p->id]}/;
+ $requests_xml =~ s/ID_EXTERNAL/@{[$p->id]}/;
+ $requests_xml =~ s/UPDATED_DATETIME/$update_dt/;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $system_user,
+ current_open311 => $o,
+ current_body => $isleofwight,
+ );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $update->process_body;
+ };
+
+ $mech->log_in_ok('user@example.org');
+ $mech->get_ok('/report/' . $p->id);
+ $mech->content_lacks('Provide an update', "No update form on report");
+
+ $p->discard_changes;
+ is $p->get_extra_metadata('closed_updates'), 1, "report closed to updates";
+ $p->comments->delete;
+ $p->delete;
+ };
+}
+
+subtest "fetched requests do not use the description text" => sub {
+ my $requests_xml = qq{<?xml version="1.0" encoding="utf-8"?>
+ <service_requests>
+ <request>
+ <service_request_id>638344</service_request_id>
+ <status>open</status>
+ <status_notes>This is a note.</status_notes>
+ <service_name>Potholes</service_name>
+ <service_code>potholes\@example.org</service_code>
+ <description>This the description of a pothole problem</description>
+ <agency_responsible></agency_responsible>
+ <service_notice></service_notice>
+ <requested_datetime>DATETIME</requested_datetime>
+ <updated_datetime>DATETIME</updated_datetime>
+ <expected_datetime>DATETIME</expected_datetime>
+ <lat>50.71086</lat>
+ <long>-1.29573</long>
+ </request>
+ </service_requests>
+ };
+
+ my $dt = DateTime->now(formatter => DateTime::Format::W3CDTF->new)->add( minutes => -5 );
+ $requests_xml =~ s/DATETIME/$dt/gm;
+
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'requests.xml' => $requests_xml } );
+
+ my $update = Open311::GetServiceRequests->new(
+ system_user => $iow_user,
+ );
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ $update->create_problems( $o, $isleofwight );
+ };
+
+ my $p = FixMyStreet::DB->resultset('Problem')->search(
+ { external_id => 638344 }
+ )->first;
+
+ ok $p, 'Found problem';
+ is $p->title, 'Potholes problem', 'correct problem title';
+ is $p->detail, 'Potholes problem', 'correct problem description';
+ $p->delete;
+};
+
+subtest "fixing passes along the correct message" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => 'isleofwight',
+ }, sub {
+ my $test_res = HTTP::Response->new();
+ $test_res->code(200);
+ $test_res->message('OK');
+ $test_res->content('<?xml version="1.0" encoding="utf-8"?><service_request_updates><request_update><update_id>248</update_id></request_update></service_request_updates>');
+
+ my $o = Open311->new(
+ fixmystreet_body => $isleofwight,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, 'Title', { external_id => 1 });
+
+ my $c = FixMyStreet::App->model('DB::Comment')->create({
+ problem => $p, user => $p->user, anonymous => 't', text => 'Update text',
+ problem_state => 'fixed - council', state => 'confirmed', mark_fixed => 0,
+ confirmed => DateTime->now(),
+ });
+
+ my $id = $o->post_service_request_update($c);
+ is $id, 248, 'correct update ID returned';
+ my $cgi = CGI::Simple->new($o->test_req_used->content);
+ like $cgi->param('description'), qr/^FMS-Update:/, 'FMS update prefix included';
+ unlike $cgi->param('description'), qr/The customer indicated that this issue had been fixed/, 'No fixed message included';
+
+ $c = $mech->create_comment_for_problem($p, $p->user, 'Name', 'Update text', 'f', 'confirmed', 'fixed - user', { confirmed => \'current_timestamp' });
+ $c->discard_changes; # Otherwise cannot set_nanosecond
+
+ $id = $o->post_service_request_update($c);
+ is $id, 248, 'correct update ID returned';
+ $cgi = CGI::Simple->new($o->test_req_used->content);
+ like $cgi->param('description'), qr/^FMS-Update: \[The customer indicated that this issue had been fixed/, 'Fixed message included';
+ $p->comments->delete;
+ $p->delete;
+ };
+};
+
+subtest 'Check special Open311 request handling', sub {
+ $mech->clear_emails_ok;
+ my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, 'Title', { category => 'Potholes', latitude => 50.7108, longitude => -1.29573, cobrand => 'isleofwight' });
+ $p->set_extra_fields({ name => 'urgent', value => 'no'});
+ $p->update;
+
+ my $test_data;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => ['isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $test_data = FixMyStreet::Script::Reports::send();
+ };
+
+ $p->discard_changes;
+ ok $p->whensent, 'Report marked as sent';
+ is $p->send_method_used, 'Open311', 'Report sent via Open311';
+ is $p->external_id, 248, 'Report has right external ID';
+
+ my $req = $test_data->{test_req_used};
+ my $c = CGI::Simple->new($req->content);
+ is $c->param('attribute[urgent]'), undef, 'no urgent param sent';
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email),
+ qr/your enquiry has been received by Island Roads/, "correct report send email text";
+};
+
+subtest "comment recording triage details is not sent" => sub {
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ }, sub {
+ my $test_res = HTTP::Response->new();
+ $test_res->code(200);
+ $test_res->message('OK');
+ $test_res->content('<?xml version="1.0" encoding="utf-8"?><service_request_updates></service_request_updates>');
+
+ my $o = Open311->new(
+ fixmystreet_body => $isleofwight,
+ test_mode => 1,
+ test_get_returns => { 'servicerequestupdates.xml' => $test_res },
+ );
+
+ my ($p) = $mech->create_problems_for_body(
+ 1, $isleofwight->id, 'Title',
+ {
+ category => 'Roads',
+ areas => 2636,
+ latitude => 50.71086,
+ longitude => -1.29573,
+ whensent => DateTime->now->add( minutes => -5 ),
+ send_method_used => 'Triage',
+ state => 'for triage',
+ external_id => 1,
+ });
+
+ $mech->log_out_ok;
+ $mech->log_in_ok($admin_user->email);
+ my $report_url = '/report/' . $p->id;
+ $mech->get_ok($report_url);
+ $mech->submit_form_ok( {
+ with_fields => {
+ category => 'Potholes',
+ include_update => 0,
+ }
+ },
+ 'triage form submitted'
+ );
+
+ ok $p->comments->first, 'comment created for problem';
+
+ $p->update({
+ send_method_used => 'Open311',
+ whensent => DateTime->now->add( minutes => -5 ),
+ });
+
+ my $updates = Open311::PostServiceRequestUpdates->new(
+ current_open311 => $o,
+ );
+ my $id = $updates->process_body($isleofwight);
+ ok !$o->test_req_used, 'no open311 update sent';
+
+ $p->comments->delete;
+ $p->delete;
+ };
+};
+
+my ($p) = $mech->create_problems_for_body(1, $isleofwight->id, '', { cobrand => 'isleofwight' });
+my $alert = FixMyStreet::App->model('DB::Alert')->create( {
+ parameter => $p->id,
+ alert_type => 'new_updates',
+ user => $user,
+ cobrand => 'isleofwight',
+} )->confirm;
+
+subtest "sends branded alert emails" => sub {
+ $mech->create_comment_for_problem($p, $system_user, 'Other User', 'This is some update text', 'f', 'confirmed', undef, { confirmed => DateTime->now->add( minutes => 5 ) });
+ $mech->clear_emails_ok;
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight','fixmystreet'],
+ }, sub {
+ FixMyStreet::Script::Alerts::send();
+ };
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "emails are branded";
+};
+
+$p->comments->delete;
+$p->delete;
+
+subtest "sends branded confirmation emails" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ $mech->submit_form_ok(
+ {
+ button => 'submit_register',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo1 => '',
+ name => 'Joe Bloggs',
+ username => 'test-1@example.com',
+ category => 'Roads',
+ }
+ },
+ "submit good details"
+ );
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "emails are branded";
+
+ my $url = $mech->get_link_from_email($email);
+ $mech->get_ok($url);
+ $mech->clear_emails_ok;
+ };
+};
+
+subtest "sends branded report sent emails" => sub {
+ $mech->clear_emails_ok;
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1 },
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight','fixmystreet'],
+ }, sub {
+ FixMyStreet::Script::Reports::send();
+ };
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ ok $email, "got an email";
+ like $mech->get_text_body_from_email($email), qr/Island Roads/, "emails are branded";
+};
+
+subtest "check category extra uses correct name" => sub {
+ my @extras = ( {
+ code => 'test',
+ datatype => 'string',
+ description => 'question',
+ variable => 'true',
+ required => 'false',
+ order => 1,
+ datatype_description => 'datatype',
+ } );
+ $contact2->set_extra_fields( @extras );
+ $contact2->update;
+
+ my $extra_details;
+
+ FixMyStreet::override_config {
+ MAPIT_URL => 'http://mapit.uk/',
+ ALLOWED_COBRANDS => ['isleofwight','fixmystreet'],
+ }, sub {
+ $extra_details = $mech->get_ok_json('/report/new/category_extras?category=Roads&latitude=50.71086&longitude=-1.29573');
+ };
+
+ like $extra_details->{category_extra}, qr/Island Roads/, 'correct name in category extras';
+};
+
+subtest "reports are marked for triage upon submission" => sub {
+ $mech->log_out_ok;
+ $mech->clear_emails_ok;
+ $mech->log_in_ok($user->email);
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ STAGING_FLAGS => { send_reports => 1, skip_checks => 0 },
+ ALLOWED_COBRANDS => [ 'isleofwight' ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ $mech->submit_form_ok(
+ {
+ button => 'submit_register',
+ with_fields => {
+ title => 'Test Report',
+ detail => 'Test report details.',
+ photo1 => '',
+ category => 'Roads',
+ }
+ },
+ "submit good details"
+ );
+
+ my $report = $user->problems->first;
+ ok $report, "Found the report";
+ is $report->state, 'confirmed', 'report confirmed';
+
+ $mech->clear_emails_ok;
+
+ FixMyStreet::Script::Reports::send();
+ $report->discard_changes;
+ is $report->state, 'for triage', 'report marked as for triage';
+ ok $report->whensent, 'report marked as sent';
+
+ $mech->email_count_is(1);
+ my $email = $mech->get_email;
+ like $mech->get_text_body_from_email($email),
+ qr/submitted to Island Roads for review/, 'correct text for email sent for Triage';
+ };
+};
+
+for my $cobrand ( 'fixmystreet', 'isleofwight' ) {
+ subtest "only categories for Triage are displayed on " . $cobrand => sub {
+ $mech->log_out_ok;
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ $cobrand ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ my $f = $mech->form_name('mapSkippedForm');
+ ok $f, 'found form';
+ my $cats = $f->find_input('category');
+ ok $cats, 'found category element';
+ my @values = $cats->possible_values;
+ is_deeply \@values, [ '-- Pick a category --', 'Roads' ], 'correct category list';
+ };
+ };
+
+ subtest "staff user can see non Triage categories on " . $cobrand => sub {
+ $mech->log_out_ok;
+ $mech->log_in_ok($admin_user->email);
+ $mech->get_ok('/around');
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ $cobrand ],
+ MAPIT_URL => 'http://mapit.uk/',
+ }, sub {
+ $mech->submit_form_ok( { with_fields => { pc => 'PO30 5XJ', } },
+ "submit location" );
+
+ # click through to the report page
+ $mech->follow_link_ok( { text_regex => qr/skip this step/i, },
+ "follow 'skip this step' link" );
+
+ my $f = $mech->form_name('mapSkippedForm');
+ ok $f, 'found form';
+ my $cats = $f->find_input('category');
+ ok $cats, 'found category element';
+ my @values = $cats->possible_values;
+ is_deeply \@values, [ '-- Pick a category --', 'Potholes' ], 'correct category list';
+ };
+ };
+}
+
+done_testing();
diff --git a/t/map/tests.t b/t/map/tests.t
index 1b152620e..f1f29dc06 100644
--- a/t/map/tests.t
+++ b/t/map/tests.t
@@ -12,6 +12,7 @@ my $requires = {
'Google' => 'map-google.js',
'GoogleOL' => 'map-google-ol.js',
'Hounslow' => 'map-wmts-hounslow.js',
+ 'IsleOfWight' => 'map-wmts-isleofwight.js',
'OSM' => 'OpenStreetMap.js',
'CycleMap' => 'OpenStreetMap.js',
'MapQuest' => 'OpenStreetMap.js',
diff --git a/t/open311/getservicerequestupdates.t b/t/open311/getservicerequestupdates.t
index 809fd3a19..6ed1d44fd 100644
--- a/t/open311/getservicerequestupdates.t
+++ b/t/open311/getservicerequestupdates.t
@@ -24,6 +24,7 @@ my $user = FixMyStreet::DB->resultset('User')->find_or_create(
my %bodies = (
2237 => FixMyStreet::DB->resultset("Body")->create({ name => 'Oxfordshire' }),
2494 => FixMyStreet::DB->resultset("Body")->create({ name => 'Bexley' }),
+ 2636 => FixMyStreet::DB->resultset("Body")->create({ name => 'Isle of Wight' }),
2482 => FixMyStreet::DB->resultset("Body")->create({
name => 'Bromley',
send_method => 'Open311',
@@ -36,6 +37,7 @@ my %bodies = (
);
$bodies{2237}->body_areas->create({ area_id => 2237 });
$bodies{2494}->body_areas->create({ area_id => 2494 });
+$bodies{2636}->body_areas->create({ area_id => 2636 });
my $response_template = $bodies{2482}->response_templates->create({
title => "investigating template",
@@ -529,29 +531,33 @@ for my $test (
};
}
-subtest 'Marking report as fixed closes it for updates (Bexley)' => sub {
- my $local_requests_xml = setup_xml($problemB->external_id, $problemB->id, 'CLOSED');
- my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
+for (
+ { id => 2494, cobrand => 'bexley' },
+ { id => 2636, cobrand => 'isleofwight' }
+) {
+ subtest "Marking report as fixed closes it for updates ($_->{cobrand})" => sub {
+ my $local_requests_xml = setup_xml($problemB->external_id, $problemB->id, 'CLOSED');
+ my $o = Open311->new( jurisdiction => 'mysociety', endpoint => 'http://example.com', test_mode => 1, test_get_returns => { 'servicerequestupdates.xml' => $local_requests_xml } );
- $problemB->update( { bodies_str => $bodies{2494}->id } );
+ $problemB->update( { bodies_str => $bodies{$_->{id}}->id } );
- my $update = Open311::GetServiceRequestUpdates->new(
- system_user => $user,
- current_open311 => $o,
- current_body => $bodies{2494},
- current_cobrand => $bodies{2494}->get_cobrand_handler,
- );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => 'bexley',
- }, sub {
- $update->process_body;
- };
+ my $update = Open311::GetServiceRequestUpdates->new(
+ system_user => $user,
+ current_open311 => $o,
+ current_body => $bodies{$_->{id}},
+ );
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => $_->{cobrand},
+ }, sub {
+ $update->process_body;
+ };
- $problemB->discard_changes;
- is $problemB->comments->count, 1, 'comment count';
- is $problemB->get_extra_metadata('closed_updates'), 1;
- $problemB->comments->delete;
-};
+ $problemB->discard_changes;
+ is $problemB->comments->count, 1, 'comment count';
+ is $problemB->get_extra_metadata('closed_updates'), 1;
+ $problemB->comments->delete;
+ };
+}
subtest 'Update with media_url includes image in update' => sub {
my $UPLOAD_DIR = tempdir( CLEANUP => 1 );
diff --git a/templates/email/isleofwight/_council_reference.html b/templates/email/isleofwight/_council_reference.html
new file mode 100644
index 000000000..5b73ee7e7
--- /dev/null
+++ b/templates/email/isleofwight/_council_reference.html
@@ -0,0 +1,4 @@
+[% IF problem.external_id ~%]
+<p style="[% p_style %]">The report's reference number is <strong>[% problem.external_id %]</strong>.
+ Please quote this if you need to contact Island Roads about this report.</p>
+[%~ END %]
diff --git a/templates/email/isleofwight/_council_reference.txt b/templates/email/isleofwight/_council_reference.txt
new file mode 100644
index 000000000..d6922217d
--- /dev/null
+++ b/templates/email/isleofwight/_council_reference.txt
@@ -0,0 +1,2 @@
+[% IF problem.external_id %]The report's reference number is [% problem.external_id %]. Please quote this if
+you need to contact Island Roads about this report.[% END %]
diff --git a/templates/email/isleofwight/_council_reference_alert_update.html b/templates/email/isleofwight/_council_reference_alert_update.html
new file mode 100644
index 000000000..5b73ee7e7
--- /dev/null
+++ b/templates/email/isleofwight/_council_reference_alert_update.html
@@ -0,0 +1,4 @@
+[% IF problem.external_id ~%]
+<p style="[% p_style %]">The report's reference number is <strong>[% problem.external_id %]</strong>.
+ Please quote this if you need to contact Island Roads about this report.</p>
+[%~ END %]
diff --git a/templates/email/isleofwight/_council_reference_alert_update.txt b/templates/email/isleofwight/_council_reference_alert_update.txt
new file mode 100644
index 000000000..d6922217d
--- /dev/null
+++ b/templates/email/isleofwight/_council_reference_alert_update.txt
@@ -0,0 +1,2 @@
+[% IF problem.external_id %]The report's reference number is [% problem.external_id %]. Please quote this if
+you need to contact Island Roads about this report.[% END %]
diff --git a/templates/email/isleofwight/_email_color_overrides.html b/templates/email/isleofwight/_email_color_overrides.html
new file mode 100644
index 000000000..3d6218ca4
--- /dev/null
+++ b/templates/email/isleofwight/_email_color_overrides.html
@@ -0,0 +1,19 @@
+[%
+
+color_cyan = '#00aeef'
+color_blue = '#00478c'
+color_green = '#75c044'
+color_white = '#fff'
+
+header_background_color = color_white
+header_text_color = color_blue
+
+secondary_column_background_color = color_white
+
+button_background_color = color_green
+button_text_color = color_white
+
+logo_width = "282" # pixel measurement, but without 'px' suffix
+logo_height = "76" # pixel measurement, but without 'px' suffix
+
+%]
diff --git a/templates/email/isleofwight/confirm_report_sent.html b/templates/email/isleofwight/confirm_report_sent.html
new file mode 100644
index 000000000..8e85c5729
--- /dev/null
+++ b/templates/email/isleofwight/confirm_report_sent.html
@@ -0,0 +1,42 @@
+[%
+
+email_summary = "Thanks for logging your report";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Your report has been&nbsp;logged</h1>
+ [% IF report.state == 'for triage' %]
+ <p style="[% p_style %]">Thank you for submitting your report to FixMyStreet, it will be submitted to Island Roads for review.</p>
+ [% ELSE %]
+ <p style="[% p_style %]">Thank you, your enquiry has been received by Island Roads and appropriate action will be taken.</p>
+
+ <p style="[% p_style %]">We don't routinely contact customers regarding their enquiries, unless we have a specific query about
+ the issue. Any status updates for the issue can be tracked via FixMyStreet, if you contact us again about this issue,
+ please quote your 8-digit reference number.</p>
+
+ <p style="[% p_style %]">Thank you for submitting your enquiry to us via FixMyStreet.</p>
+ [% END %]
+
+[% IF cobrand.is_council && !cobrand.owns_problem( report ) %]
+<p style="[% p_style %]">Please note that [% cobrand.council_name %] is not responsible for this type
+of report, so it will instead be sent to [% report.body %].</p>
+[% ELSE %]
+[% TRY %][% INCLUDE '_council_reference.html' problem=report %][% CATCH file %][% END %]
+[% END %]
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% cobrand.base_url_for_report(report) %][% report.url %]">View my report</a>
+ </p>
+ [% end_padded_box %]
+</th>
+[% WRAPPER '_email_sidebar.html' object = report %]
+ <h2 style="[% h2_style %]">[% report.title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% report.detail | html %]</p>
+[% END %]
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/isleofwight/confirm_report_sent.txt b/templates/email/isleofwight/confirm_report_sent.txt
new file mode 100644
index 000000000..a368bd95e
--- /dev/null
+++ b/templates/email/isleofwight/confirm_report_sent.txt
@@ -0,0 +1,43 @@
+Subject: Your report has been logged: [% report.title %]
+
+Hello [% report.name %],
+
+[% IF report.state == 'for triage' %]
+Thank you for submitting your report to FixMyStreet, it will be
+submitted to Island Roads for review.
+[% ELSE %]
+Thank you, your enquiry has been received by Island Roads and
+appropriate action will be taken.
+
+We don't routinely contact customers regarding their enquiries,
+unless we have a specific query about the issue. Any status
+updates for the issue can be tracked via FixMyStreet, if you
+contact us again about this issue, please quote your 8-digit
+reference number.
+
+Thank you for submitting your enquiry to us via FixMyStreet.
+[% END %]
+
+[% IF cobrand.is_council && !cobrand.owns_problem( report ) %]
+Please note that [% cobrand.council_name %] is not responsible for this type
+of report, so it will instead be sent to [% report.body %].
+[% ELSE %]
+[% TRY %][% INCLUDE '_council_reference.txt' problem=report %][% CATCH file %][% END %]
+[% END %]
+
+It is available to view at:
+
+[% cobrand.base_url_for_report(report) %][% report.url %]
+
+Your report has the title:
+
+[% report.title %]
+
+And details:
+
+[% report.detail %]
+
+[% signature %]
+
+This email was sent automatically, from an unmonitored email account - so
+please do not reply to it.
diff --git a/templates/email/isleofwight/problem-confirm.html b/templates/email/isleofwight/problem-confirm.html
new file mode 100644
index 000000000..ccdefc7aa
--- /dev/null
+++ b/templates/email/isleofwight/problem-confirm.html
@@ -0,0 +1,31 @@
+[%
+
+email_summary = "You need to confirm your " _ site_name _ " report before it can be sent to Island Roads.";
+email_columns = 2;
+
+PROCESS '_email_settings.html';
+
+INCLUDE '_email_top.html';
+
+%]
+
+<th style="[% td_style %][% primary_column_style %]" id="primary_column">
+ [% start_padded_box %]
+ <h1 style="[% h1_style %]">Please confirm your&nbsp;report</h1>
+ <p style="[% p_style %]">Please click on the link below to confirm that you want to send your report to Island Roads.
+
+[% TRY %][% INCLUDE '_problem-confirm_extra.html' %][% CATCH file %][% END %]
+ </p>
+ [% UNLESS report.non_public %]<p style="[% p_style %]">Your report will also appear on the [% site_name %] website.</p>[% END %]
+ <p style="margin: 20px auto; text-align: center">
+ <a style="[% button_style %]" href="[% token_url %]">Yes, send my report</a>
+ </p>
+ <p style="[% p_style %]">If you no longer wish to send this report, please take no further action.</p>
+ [% end_padded_box %]
+</th>
+[% WRAPPER '_email_sidebar.html' object = report, url = token_url %]
+ <h2 style="[% h2_style %]">[% report.title | html %]</h2>
+ <p style="[% secondary_p_style %]">[% report.detail | html %]</p>
+[% END %]
+
+[% INCLUDE '_email_bottom.html' %]
diff --git a/templates/email/isleofwight/problem-confirm.txt b/templates/email/isleofwight/problem-confirm.txt
new file mode 100644
index 000000000..20a871453
--- /dev/null
+++ b/templates/email/isleofwight/problem-confirm.txt
@@ -0,0 +1,31 @@
+Subject: Confirm your report on [% site_name %]
+
+Hello [% report.name %],
+
+Please click on the link below to confirm that you want to send your report to
+Island Roads.[% UNLESS report.non_public %] Note that your report will also
+appear on the [% site_name %] website.[% END %]
+
+[% token_url %]
+
+If your email program does not let you click on this link, copy and paste it
+into your web browser and press return.
+[% TRY %][% INCLUDE '_problem-confirm_extra.txt' %][% CATCH file %][% END %]
+Your problem had the title:
+
+[% report.title %]
+
+And details:
+
+[% report.detail %]
+
+If you no longer wish to send this report, please take no further action.
+
+Thank you for submitting a report through [% site_name %].
+
+
+
+[% signature %]
+
+This email was sent automatically, from an unmonitored email account - so
+please do not reply to it.
diff --git a/templates/email/isleofwight/signature.txt b/templates/email/isleofwight/signature.txt
new file mode 100644
index 000000000..e375a0402
--- /dev/null
+++ b/templates/email/isleofwight/signature.txt
@@ -0,0 +1,2 @@
+
+Island Roads
diff --git a/templates/web/base/admin/report-category.html b/templates/web/base/admin/report-category.html
index 0416d71c0..64aa474b9 100644
--- a/templates/web/base/admin/report-category.html
+++ b/templates/web/base/admin/report-category.html
@@ -1,4 +1,7 @@
-<select class="form-control" name="category" id="category">
+[%~ IF NOT select_name %]
+ [%~ select_name = 'category' %]
+[%~ END %]
+<select class="form-control" name="[% select_name %]" id="[% select_name %]">
[% IF NOT problem.category OR NOT categories_hash.${problem.category} %]
<optgroup label="[% loc('Existing category') %]">
<option selected value="[% problem.category | html %]">[% (problem.category_display OR '-') | html %]</option>
diff --git a/templates/web/base/admin/triage/_inspect.html b/templates/web/base/admin/triage/_inspect.html
new file mode 100644
index 000000000..926197ceb
--- /dev/null
+++ b/templates/web/base/admin/triage/_inspect.html
@@ -0,0 +1,77 @@
+[% BLOCK category_list %]
+<select class="form-control" name="[% field_name %]" id="[% field_name %]">
+ [% IF category_options.size %]
+ [%~ IF category_groups.size ~%]
+ [%~ FOREACH group IN category_groups ~%]
+ [% IF group.name %]<optgroup label="[% group.name %]">[% END %]
+ [% group_select = 0 %]
+ [% selected = 0 %]
+ [%~ FOREACH cat_op IN group.categories ~%]
+ [% IF group_select == 0 AND problem.category == group.name %]
+ [% selected = 1; group_select = 1 %]
+ [% END %]
+ <option value="[% cat_op.category | html %]"[% ' selected' IF selected OR problem.category == cat_op.category %]>[% cat_op.category_display | html %] ([% cat_op.email | html %])</option>
+ [% selected = 0 %]
+ [%~ END ~%]
+ [% IF group.name %]</optgroup>[% END %]
+ [%~ END =%]
+ [% ELSE %]
+ [% FOREACH cat IN category_options %]
+ <option value="[% cat.category | html %]"[% ' selected' IF problem.category == cat.category %]>[% cat.category_display | html %]</option>
+ [% END %]
+ [% END %]
+ [% END %]
+</select>
+[% END %]
+
+[% permissions = c.user.permissions(problem) %]
+[% second_column = BLOCK -%]
+ <div id="side-inspect">
+
+ <h2 class="inspect-form-heading">[% loc('Inspect report') %]</h2>
+
+ [% INCLUDE 'errors.html' %]
+
+ <form name="report_inspect_form" id="report_inspect_form" method="post" action="[% c.uri_for( '/report', problem.id ) %]" class="validate">
+
+ [% INCLUDE 'report/inspect/information.html' no_relocate=1 %]
+
+ [% IF permissions.report_edit_category OR permissions.report_inspect OR permissions.triage %]
+ <div class="inspect-section">
+ <p>
+ <strong>Holding category:</strong> [% problem.category %]
+ </p>
+
+ <p>
+ <label for="category">CONFIRM Subject</label>
+ [% PROCESS category_list category_groups=end_groups field_name="category" categories_hash=end_categories category_options=end_options %]
+ </p>
+
+ </div>
+ [% END %]
+
+ <div class="inspect-section">
+ [%- extra_fields = problem.get_extra_fields -%]
+ [% FOR field IN extra_fields %]
+ [% NEXT IF field.name == 'urgent' %]
+ <p>
+ <label for="[% field.name %]">[% field.description %]</label>
+ <input class="form-control" name="[% field.name %]" type="text" value="[% field.value | html %]" disabled>
+ </p>
+ [% END %]
+
+ [% IF permissions.report_inspect OR permissions.triage %]
+ [% INCLUDE 'report/inspect/public_update.html' public_update_defaulted=0 %]
+ [% END %]
+
+ <p>
+ <input type="hidden" name="token" value="[% csrf_token %]" />
+ <input class="btn btn-primary" type="submit" value="[% loc('Save changes') %]" data-value-original="[% loc('Save changes') %]" data-value-duplicate="[% loc('Save + close as duplicate') %]" name="save" />
+ </p>
+ </div>
+
+ <input type="hidden" name="js" value="">
+ <input type="hidden" name="triage" value="1">
+ </form>
+ </div>
+[%- END %]
diff --git a/templates/web/base/admin/triage/_list-filters.html b/templates/web/base/admin/triage/_list-filters.html
new file mode 100644
index 000000000..f6bedcb80
--- /dev/null
+++ b/templates/web/base/admin/triage/_list-filters.html
@@ -0,0 +1,53 @@
+[% select_category = BLOCK %]
+ [% IF filter_categories.size %]
+ <select class="form-control js-multiple" name="filter_category" id="filter_categories" multiple data-all="[% loc('Everything') %]">
+ [% FOR cat IN filter_categories %]
+ <option value="[% cat.category | html %]"[% ' selected' IF filter_category.${cat.category} %]>
+ [% cat.category_display | html %]
+ [%~ IF cat.get_extra_metadata('help_text') %] ([% cat.get_extra_metadata('help_text') %])[% END ~%]
+ </option>
+ [% END %]
+ </select>
+ [% ELSE %]
+ [% loc('Everything') %]
+ [% END %]
+[% END %]
+
+<div class="report-list-filters-wrapper">
+
+[% IF use_form_wrapper %]
+ <form method="get" action="">
+[% END %]
+
+ <p class="report-list-filters">
+ [% tprintf(loc('<label for="statuses">Show</label> %s reports <label for="filter_categories">about</label> %s', "The first %s is a dropdown of all/fixed/etc, the second is a dropdown of categories"), 'untriaged', select_category) %]
+ <input type="submit" name="filter_update" value="[% loc('Go') %]">
+ </p>
+
+ <p class="report-list-filters">
+ <label for="sort">[% loc('Sort by') %]</label>
+ <select class="form-control" name="sort" id="sort">
+ [% IF shortlist %]
+ <option value="shortlist"[% ' selected' IF sort_key == 'shortlist' %]>[% loc('Manual order') %]</option>
+ [% END %]
+ <option value="created-desc"[% ' selected' IF sort_key == 'created-desc' %]>[% loc('Newest') %]</option>
+ <option value="created-asc"[% ' selected' IF sort_key == 'created-asc' %]>[% loc('Oldest') %]</option>
+ <option value="updated-desc"[% ' selected' IF sort_key == 'updated-desc' %]>[% loc('Recently updated') %]</option>
+ <option value="updated-asc"[% ' selected' IF sort_key == 'updated-asc' %]>[% loc('Least recently updated') %]</option>
+ <option value="comments-desc"[% ' selected' IF sort_key == 'comments-desc' %]>[% loc('Most commented') %]</option>
+ </select>
+ <input type="submit" name="filter_update" value="[% loc('Go') %]">
+ </p>
+ [% IF page == 'around' %]
+ <p id="show_old_reports_wrapper" class="report-list-filters[% ' hidden' UNLESS num_old_reports > 0 %]">
+ <label for="show_old_reports">[% loc('Show older reports') %]</label>
+ <input type="checkbox" name="show_old_reports" id="show_old_reports" value="1"[% ' checked' IF show_old_reports %]>
+ <input type="submit" name="filter_update" value="[% loc('Go') %]">
+ </p>
+ [% END %]
+
+[% IF use_form_wrapper %]
+ </form>
+[% END %]
+
+</div>
diff --git a/templates/web/base/admin/triage/index.html b/templates/web/base/admin/triage/index.html
new file mode 100644
index 000000000..f00bbc1fa
--- /dev/null
+++ b/templates/web/base/admin/triage/index.html
@@ -0,0 +1,42 @@
+[% SET body_name = body.name %]
+[% IF c.cobrand.moniker == 'hounslow' %]
+ [% SET body_name = 'Hounslow Highways' %]
+[% ELSIF c.cobrand.moniker == 'isleofwight' %]
+ [% SET body_name = 'Island Roads' %]
+[% END %]
+
+[%
+ PROCESS "report/photo-js.html";
+ PROCESS "maps/${map.type}.html";
+ SET bodyclass = 'mappage';
+ INCLUDE 'header.html',
+ title = 'Awaiting triage'
+ rss = [ tprintf(loc('Problems within %s, %s', "First %s is the body name, second %s the site name"), name, site_name), rss_url ]
+%]
+
+[% map_html %]
+
+</div>
+<div id="map_sidebar">
+ <div id="side">
+
+ <h1 id="reports_heading">
+ Awaiting triage
+ </h1>
+
+<section class="full-width">
+[% INCLUDE "admin/triage/_list-filters.html", use_form_wrapper = 1 %]
+<div class="js-pagination">
+[% INCLUDE 'pagination.html', param = 'p' %]
+</div>
+<div id="js-reports-list">
+ [% INCLUDE 'reports/_problem-list.html' %]
+</div>
+<div class="js-pagination">
+[% INCLUDE 'pagination.html', param = 'p' %]
+</div>
+</section>
+
+ </div>
+</div>
+[% INCLUDE 'footer.html' %]
diff --git a/templates/web/base/report/_inspect.html b/templates/web/base/report/_inspect.html
index fa79d9912..10f3b6b84 100644
--- a/templates/web/base/report/_inspect.html
+++ b/templates/web/base/report/_inspect.html
@@ -11,60 +11,7 @@
<form name="report_inspect_form" id="report_inspect_form" method="post" action="[% c.uri_for( '/report', problem.id ) %]" class="validate">
- <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>
- [% IF c.user_exists AND c.cobrand.admin_allow_user(c.user) AND c.user.has_permission_to('report_edit', problem.bodies_str_ids) %]
- (<a href="[% c.uri_for_action( "admin/report_edit", problem.id ) %]">[% loc('admin') %]</a>)
- [% END %]
- </p>
- [% IF permissions.report_inspect AND problem.user.phone %]
- <p>
- <strong>[% loc('Phone Reporter:') %]</strong>
- <a href="tel:[% problem.user.phone | html %]">[% problem.user.phone_display | html %]</a>
- </p>
- [% END %]
- <p>
- [% SET local_coords = problem.local_coords; %]
- [% IF local_coords %]
- <strong>[% loc('Easting/Northing:') %]</strong>
- <span id="problem_easting">[% local_coords.0 %]</span>,
- <span id="problem_northing">[% local_coords.1 %]</span>
- [% ELSE %]
- <strong>[% loc('Latitude/Longitude:') %]</strong>
- <span id="problem_latitude">[% problem.latitude %]</span>,
- <span id="problem_longitude">[% problem.longitude %]</span>
- [% END %]
- <input type="hidden" name="longitude" value="[% problem.longitude %]">
- <input type="hidden" name="latitude" value="[% problem.latitude %]">
- </p>
- [% IF problem.nearest_address() %]
- <p>
- <strong>[% loc('Nearest calculated address:') %]</strong>
- [% problem.nearest_address() %]
- </p>
- [% END %]
- <p>
- <a target="_blank" href="https://www.google.com/maps/dir/?api=1&destination=[% problem.latitude %],[% problem.longitude %]" class="btn btn--block btn--navigate">[% loc('Navigate to this problem') %]</a>
- </p>
- <p>
- <a href="#" class="btn btn--block btn--geolocate">[% loc('Set to my current location') %]</a>
- </p>
- [% IF permissions.report_reject %]
- [% TRY %]
- [% INCLUDE 'report/_inspect_reject_button.html' %]
- [% CATCH file %]
- <p>
- <a href="[% c.uri_for( '/contact', { id => problem.id, reject => 1 } ) %]" class="btn btn--block">[% loc('Reject report') %]</a>
- </p>
- [% END %]
- [% END %]
- </div>
+ [% INCLUDE 'report/inspect/information.html' %]
[% IF permissions.report_edit_category OR permissions.report_inspect %]
<div class="inspect-section">
@@ -182,17 +129,7 @@
<div class="inspect-section">
[% IF permissions.report_inspect %]
- <p>
- <label class="label-containing-checkbox">
- <input type="checkbox" name="include_update" value="1" class="js-toggle-public-update" checked>
- [% loc('Save with a public update') %]
- </label>
- </p>
- <p>
- <label for="public_update">[% loc('Public update:') %]</label>
- [% INCLUDE 'admin/response_templates_select.html' for='public_update' %]
- <textarea rows="2" name="public_update" id="public_update" class="form-control">[% public_update | html %]</textarea>
- </p>
+ [% INCLUDE 'report/inspect/public_update.html' %]
[% END %]
[% IF problem.get_extra_metadata('inspected') %]
diff --git a/templates/web/base/report/inspect/information.html b/templates/web/base/report/inspect/information.html
new file mode 100644
index 000000000..cc8989522
--- /dev/null
+++ b/templates/web/base/report/inspect/information.html
@@ -0,0 +1,56 @@
+ <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>
+ [% IF c.user_exists AND c.cobrand.admin_allow_user(c.user) AND c.user.has_permission_to('report_edit', problem.bodies_str_ids) %]
+ (<a href="[% c.uri_for_action( "admin/report_edit", problem.id ) %]">[% loc('admin') %]</a>)
+ [% END %]
+ </p>
+ [% IF permissions.report_inspect AND problem.user.phone %]
+ <p>
+ <strong>[% loc('Phone Reporter:') %]</strong>
+ <a href="tel:[% problem.user.phone | html %]">[% problem.user.phone_display | html %]</a>
+ </p>
+ [% END %]
+ <p>
+ [% SET local_coords = problem.local_coords; %]
+ [% IF local_coords %]
+ <strong>[% loc('Easting/Northing:') %]</strong>
+ <span id="problem_easting">[% local_coords.0 %]</span>,
+ <span id="problem_northing">[% local_coords.1 %]</span>
+ [% ELSE %]
+ <strong>[% loc('Latitude/Longitude:') %]</strong>
+ <span id="problem_latitude">[% problem.latitude %]</span>,
+ <span id="problem_longitude">[% problem.longitude %]</span>
+ [% END %]
+ <input type="hidden" name="longitude" value="[% problem.longitude %]">
+ <input type="hidden" name="latitude" value="[% problem.latitude %]">
+ </p>
+ [% IF problem.nearest_address() %]
+ <p>
+ <strong>[% loc('Nearest calculated address:') %]</strong>
+ [% problem.nearest_address() %]
+ </p>
+ [% END %]
+ <p>
+ <a target="_blank" href="https://www.google.com/maps/dir/?api=1&destination=[% problem.latitude %],[% problem.longitude %]" class="btn btn--block btn--navigate">[% loc('Navigate to this problem') %]</a>
+ </p>
+ [% UNLESS no_relocate %]
+ <p>
+ <a href="#" class="btn btn--block btn--geolocate">[% loc('Set to my current location') %]</a>
+ </p>
+ [% END %]
+ [% IF permissions.report_reject %]
+ [% TRY %]
+ [% INCLUDE 'report/_inspect_reject_button.html' %]
+ [% CATCH file %]
+ <p>
+ <a href="[% c.uri_for( '/contact', { id => problem.id, reject => 1 } ) %]" class="btn btn--block">[% loc('Reject report') %]</a>
+ </p>
+ [% END %]
+ [% END %]
+ </div>
diff --git a/templates/web/base/report/inspect/public_update.html b/templates/web/base/report/inspect/public_update.html
new file mode 100644
index 000000000..be07d7b89
--- /dev/null
+++ b/templates/web/base/report/inspect/public_update.html
@@ -0,0 +1,14 @@
+[% IF NOT public_update_defaulted.defined %]
+ [% public_update_defaulted = 1 %]
+[% END %]
+ <p>
+ <label class="label-containing-checkbox">
+ <input type="checkbox" name="include_update" value="1" class="js-toggle-public-update"[% ' checked' IF public_update_defaulted %]>
+ [% loc('Save with a public update') %]
+ </label>
+ </p>
+ <p>
+ <label for="public_update">[% loc('Public update:') %]</label>
+ [% INCLUDE 'admin/response_templates_select.html' for='public_update' %]
+ <textarea rows="2" name="public_update" id="public_update" class="form-control">[% public_update | html %]</textarea>
+ </p>
diff --git a/templates/web/base/report/new/category_extras.html b/templates/web/base/report/new/category_extras.html
index c7bdad94d..8e5b02952 100644
--- a/templates/web/base/report/new/category_extras.html
+++ b/templates/web/base/report/new/category_extras.html
@@ -1,4 +1,4 @@
-[% SET default_list = [] %][% FOR b IN bodies_to_list.values %][% default_list.push(b.name) %][% END %]
+[% SET default_list = [] %][% FOR b IN bodies_to_list.values %][% default_list.push(b.cobrand_name) %][% END %]
[% DEFAULT list_of_names = default_list %]
<div id="category_meta">
diff --git a/templates/web/base/report/new/councils_text_all.html b/templates/web/base/report/new/councils_text_all.html
index 8b9abf1f3..63f4125f4 100644
--- a/templates/web/base/report/new/councils_text_all.html
+++ b/templates/web/base/report/new/councils_text_all.html
@@ -1,4 +1,4 @@
-[% SET default_list = [] %][% FOR b IN bodies_to_list.values %][% default_list.push(b.name) %][% END %]
+[% SET default_list = [] %][% FOR b IN bodies_to_list.values %][% default_list.push(b.cobrand_name) %][% END %]
[% DEFAULT list_of_names = default_list %]
<p>
diff --git a/templates/web/base/report/updates.html b/templates/web/base/report/updates.html
index 817cc7eb4..93bae4d64 100644
--- a/templates/web/base/report/updates.html
+++ b/templates/web/base/report/updates.html
@@ -6,6 +6,9 @@
[%- END %]
[%- NEXT %]
[%- END %]
+[%- IF update.get_extra_metadata('triage_report') == 1 AND ( NOT c.user OR ( NOT c.user.from_body AND NOT c.user.is_superuser ) ) %]
+ [%- NEXT %]
+[%- END %]
[% INCLUDE 'report/update.html' %]
[% END %]
diff --git a/templates/web/base/reports/body.html b/templates/web/base/reports/body.html
index 02791ba3b..23540104b 100755
--- a/templates/web/base/reports/body.html
+++ b/templates/web/base/reports/body.html
@@ -1,6 +1,8 @@
[% SET body_name = body.name %]
[% IF c.cobrand.moniker == 'hounslow' %]
[% SET body_name = 'Hounslow Highways' %]
+[% ELSIF c.cobrand.moniker == 'isleofwight' %]
+ [% SET body_name = 'Island Roads' %]
[% END %]
[% IF ward %]
diff --git a/templates/web/fixmystreet.com/footer_extra_js.html b/templates/web/fixmystreet.com/footer_extra_js.html
index 3f3e61c52..6fcb5d59c 100644
--- a/templates/web/fixmystreet.com/footer_extra_js.html
+++ b/templates/web/fixmystreet.com/footer_extra_js.html
@@ -10,6 +10,7 @@ IF bodyclass.match('mappage');
scripts.push( version('/cobrands/bristol/assets.js') );
scripts.push( version('/cobrands/bromley/assets.js') );
scripts.push( version('/cobrands/buckinghamshire/assets.js') );
+ scripts.push( version('/cobrands/isleofwight/assets.js') );
scripts.push( version('/cobrands/lincolnshire/assets.js') );
scripts.push( version('/cobrands/northamptonshire/assets.js') );
scripts.push( version('/cobrands/hounslow/assets.js') );
diff --git a/templates/web/hounslow/report/new/councils_text_all.html b/templates/web/hounslow/report/new/councils_text_all.html
deleted file mode 100644
index c434813f8..000000000
--- a/templates/web/hounslow/report/new/councils_text_all.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<p>
- [% UNLESS non_public_categories.$category %]
- These will be sent to <strong>Hounslow Highways</strong> and also published online for others to see, in accordance with our
- <a href="[% c.cobrand.privacy_policy_url %]">privacy policy</a>.
- [% ELSE %]
- These will be sent to <strong>Hounslow Highways</strong> but not published online.
- [% END %]
-</p>
diff --git a/templates/web/isleofwight/about/mapterms.html b/templates/web/isleofwight/about/mapterms.html
new file mode 100644
index 000000000..04c0aeb09
--- /dev/null
+++ b/templates/web/isleofwight/about/mapterms.html
@@ -0,0 +1,24 @@
+[% INCLUDE header.html
+ title = 'Map Terms and Conditions'
+%]
+
+<h1>Map Terms and Conditions</h1>
+
+<ul>
+ <li>
+ I. You are granted a non-exclusive, royalty free revocable licence
+ solely to view the licensed data for non-commercial purposes for the
+ period during which mySociety Ltd. makes it available;
+ </li>
+ <li>
+ II. You are not permitted to copy, sub-license, distribute, sell or
+ otherwise make available the Licensed Data to third parties in any form;
+ and
+ </li>
+ <li>
+ III. Third party rights to enforce the terms of this licence shall be
+ reserved to OS.
+ </li>
+</ul>
+[% INCLUDE footer.html %]
+
diff --git a/templates/web/isleofwight/footer_extra_js.html b/templates/web/isleofwight/footer_extra_js.html
new file mode 100644
index 000000000..0ad3525e6
--- /dev/null
+++ b/templates/web/isleofwight/footer_extra_js.html
@@ -0,0 +1,10 @@
+[% IF bodyclass.match('mappage');
+ scripts.push(
+ version('/vendor/OpenLayers.Projection.OrdnanceSurvey.js'),
+ version('/cobrands/fixmystreet/assets.js'),
+ version('/cobrands/fixmystreet-uk-councils/roadworks.js'),
+ version('/cobrands/fixmystreet-uk-councils/js.js'),
+ version('/cobrands/isleofwight/js.js'),
+ version('/cobrands/isleofwight/assets.js'),
+ );
+END %]
diff --git a/templates/web/isleofwight/header_extra.html b/templates/web/isleofwight/header_extra.html
new file mode 100644
index 000000000..8a977495f
--- /dev/null
+++ b/templates/web/isleofwight/header_extra.html
@@ -0,0 +1 @@
+[% INCLUDE 'tracking_code.html' %]
diff --git a/templates/web/isleofwight/header_logo.html b/templates/web/isleofwight/header_logo.html
new file mode 100644
index 000000000..e563007a7
--- /dev/null
+++ b/templates/web/isleofwight/header_logo.html
@@ -0,0 +1,2 @@
+<a href="http://www.islandroads.com" id="site-logo">Island Roads</a>
+<a href="/" id="report-cta" title="[%- loc('Report a problem') -%]">[%- loc('Report') -%]</a>
diff --git a/templates/web/isleofwight/main_nav_items.html b/templates/web/isleofwight/main_nav_items.html
new file mode 100644
index 000000000..5b794a99d
--- /dev/null
+++ b/templates/web/isleofwight/main_nav_items.html
@@ -0,0 +1,59 @@
+[%~ IF problem ~%]
+ [%~ INCLUDE navitem uri='/report/new?longitude=' _ problem.longitude _ '&amp;latitude=' _ problem.latitude label=loc('Report another problem here') attrs='class="report-a-problem-btn"' ~%]
+[%~ ELSIF latitude AND longitude ~%]
+ [%~ INCLUDE navitem uri='/report/new?longitude=' _ longitude _ '&amp;latitude=' _ latitude label=loc('Report a problem here') attrs='class="report-a-problem-btn"' ~%]
+[%~ ELSIF homepage_template ~%]
+ [%~ INCLUDE navitem uri='/report' label=loc('Report a problem') attrs='class="report-a-problem-btn"' ~%]
+[%~ ELSE ~%]
+ [%~ INCLUDE navitem uri='/' label=loc('Report a problem') attrs='class="report-a-problem-btn"' ~%]
+[%~ END ~%]
+
+[%~ IF c.user_exists ~%]
+ [%~ INCLUDE navitem uri='/my' label=loc('Your account') ~%]
+[%~ ELSE ~%]
+ [%~ INCLUDE navitem uri='/auth' label=loc('Sign in') ~%]
+[%~ END ~%]
+
+[%~ IF c.user_exists AND c.user.has_body_permission_to('planned_reports') ~%]
+ [%~ INCLUDE navitem always_url=1 uri='/my/planned' label=loc('Shortlist') ~%]
+[%~ END ~%]
+
+[%~ IF c.user_exists AND c.user.has_body_permission_to('triage') ~%]
+ [%~ INCLUDE navitem always_url=1 uri='/admin/triage' label=loc('Awaiting triage') ~%]
+[%~ END ~%]
+
+[%~ UNLESS hide_all_reports_link ~%]
+ [%~
+ IF c.user_exists AND c.user.categories.size;
+ categories = c.user.categories_string | uri;
+ cat_suffix = "?filter_category=" _ categories;
+ END;
+
+ reports_uri = '/reports';
+ IF c.cobrand.council_area;
+ body_name = c.cobrand.council_area | uri;
+ reports_uri = "${reports_uri}/${body_name}";
+ END;
+
+ INCLUDE navitem uri=reports_uri label=loc('All reports') suffix=cat_suffix;
+ ~%]
+[%~ END ~%]
+
+[%~
+ IF pc;
+ pc_uri = pc | uri;
+ pc_suffix = "/list?pc=" _ pc_uri;
+ END;
+
+ INCLUDE navitem uri='/alert' label=loc('Local alerts') suffix=pc_suffix;
+~%]
+
+[%~ INCLUDE navitem uri='/faq' label=loc('Help') ~%]
+
+[%~ UNLESS hide_privacy_link ~%]
+ [%~ INCLUDE navitem uri=c.cobrand.privacy_policy_url label=loc('Privacy') liattrs='class="nav-menu__item--privacy"' ~%]
+[%~ END ~%]
+
+[%~ IF c.user_exists AND c.cobrand.admin_allow_user(c.user) ~%]
+ [%~ INCLUDE navitem uri='/admin' label=loc('Admin') ~%]
+[%~ END ~%]
diff --git a/templates/web/isleofwight/report/_updates_disallowed_message.html b/templates/web/isleofwight/report/_updates_disallowed_message.html
new file mode 100644
index 000000000..af56f73b1
--- /dev/null
+++ b/templates/web/isleofwight/report/_updates_disallowed_message.html
@@ -0,0 +1,8 @@
+<p>
+ Only the original reporter may leave updates.
+ [% IF NOT c.user_exists %]
+ If you made the original report please
+ <a href="/auth?r=report/[% problem.id %]">log in</a>
+ to leave an update.
+ [% END %]
+</p>
diff --git a/templates/web/isleofwight/report/inspect.html b/templates/web/isleofwight/report/inspect.html
new file mode 100644
index 000000000..6cecff926
--- /dev/null
+++ b/templates/web/isleofwight/report/inspect.html
@@ -0,0 +1,10 @@
+[%
+ SET bodyclass = 'mappage with-actions';
+ SET two_column_sidebar = 1;
+ IF problem.state == 'for triage';
+ PROCESS 'admin/triage/_inspect.html';
+ ELSE;
+ PROCESS 'report/_inspect.html';
+ END;
+ INCLUDE 'report/display.html'
+%]
diff --git a/templates/web/isleofwight/report/new/_form_labels.html b/templates/web/isleofwight/report/new/_form_labels.html
new file mode 100644
index 000000000..a666ab0a3
--- /dev/null
+++ b/templates/web/isleofwight/report/new/_form_labels.html
@@ -0,0 +1,3 @@
+[%
+SET form_title = 'Summarise the problem and location';
+%]
diff --git a/templates/web/isleofwight/tokens/_confirm_problem_council_id.html b/templates/web/isleofwight/tokens/_confirm_problem_council_id.html
new file mode 100644
index 000000000..703fbd1b6
--- /dev/null
+++ b/templates/web/isleofwight/tokens/_confirm_problem_council_id.html
@@ -0,0 +1,2 @@
+<h2>Your issue has been sent.</h2>
+<p>You will receive an email with a reference number for this report soon, please quote it in any enquiries.</p>
diff --git a/templates/web/isleofwight/tracking_code.html b/templates/web/isleofwight/tracking_code.html
new file mode 100644
index 000000000..26358b589
--- /dev/null
+++ b/templates/web/isleofwight/tracking_code.html
@@ -0,0 +1,16 @@
+[% IF c.config.BASE_URL == "https://www.fixmystreet.com" %]
+
+<script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+ ga('create', 'UA-136557400-2', 'auto');
+ ga('send', 'pageview');
+
+</script>
+
+[% ELSE %]
+<!-- Tracking code not inserted as "[% c.config.BASE_URL %]" not "https://www.fixmystreet.com" -->
+[% END %]
diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js
index fd18bb34a..0b2205076 100644
--- a/web/cobrands/fixmystreet/assets.js
+++ b/web/cobrands/fixmystreet/assets.js
@@ -71,7 +71,7 @@ OpenLayers.Layer.VectorAsset = OpenLayers.Class(OpenLayers.Layer.Vector, {
if (!fixmystreet.markers.getVisibility() || !(this.getVisibility() && this.inRange)) {
return;
}
- var threshold = 50; // metres
+ var threshold = this.fixmystreet.snap_threshold || 50; // metres
var marker = fixmystreet.markers.features[0];
if (marker === undefined) {
// No marker to be found so bail out
@@ -375,7 +375,7 @@ function clear_fields_for_attributes(attributes) {
}
function check_zoom_message_visibility() {
- if (this.fixmystreet.non_interactive) {
+ if (this.fixmystreet.non_interactive && !this.fixmystreet.display_zoom_message) {
return;
}
var select = this.fixmystreet.asset_group ? 'category_group' : 'form_category';
@@ -419,6 +419,9 @@ function layer_visibilitychanged() {
if (!this.getVisibility()) {
this.road_not_found();
}
+ if (this.fixmystreet.display_zoom_message) {
+ check_zoom_message_visibility.call(this);
+ }
return;
} else if (!this.getVisibility()) {
asset_unselected.call(this);
@@ -1021,6 +1024,7 @@ fixmystreet.message_controller = (function() {
var stopperId = 'js-category-stopper',
stoppers = [],
ignored_bodies = [];
+ msg_after_bodies = [];
// 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) {
@@ -1119,6 +1123,14 @@ fixmystreet.message_controller = (function() {
}
}
+ function stopper_after(stopper) {
+ var body = fixmystreet.bodies[0];
+ if (OpenLayers.Util.indexOf( msg_after_bodies, body) > -1 ) {
+ return true;
+ }
+ return false;
+ }
+
function check_for_stopper() {
var only_send = fixmystreet.body_overrides.get_only_send();
if (only_send == 'Highways England') {
@@ -1150,7 +1162,11 @@ fixmystreet.message_controller = (function() {
if ($id.length) {
$id.replaceWith($msg);
} else {
- $msg.insertBefore('#js-post-category-messages');
+ if (stopper_after(stopper)) {
+ $msg.insertAfter('#js-post-category-messages');
+ } else {
+ $msg.insertBefore('#js-post-category-messages');
+ }
}
disable_report_form(stopper.keep_category_extras);
}
@@ -1225,6 +1241,10 @@ fixmystreet.message_controller = (function() {
add_ignored_body: function(body) {
ignored_bodies.push(body);
+ },
+
+ add_msg_after_bodies: function(body) {
+ msg_after_bodies.push(body);
}
};
diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js
index 24b8a6d0f..cda196864 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -1510,7 +1510,12 @@ fixmystreet.display = {
window.selected_problem_id = reportId;
var marker = fixmystreet.maps.get_marker_by_id(reportId);
- if (fixmystreet.map.panTo && ($('html').hasClass('mobile') || !marker.onScreen())) {
+ var el = document.querySelector('input[name=triage]');
+ if (el) {
+ fixmystreet.map.setCenter(
+ marker.geometry.getBounds().getCenterLonLat(),
+ fixmystreet.map.getNumZoomLevels() - 1 );
+ } else if (fixmystreet.map.panTo && ($('html').hasClass('mobile') || !marker.onScreen())) {
fixmystreet.map.panTo(
marker.geometry.getBounds().getCenterLonLat()
);
@@ -1526,8 +1531,10 @@ fixmystreet.display = {
if (fixmystreet.maps.setup_inspector) {
fixmystreet.maps.setup_inspector();
+ fixmystreet.map.updateSize();
}
+
if (typeof callback === 'function') {
callback();
}
diff --git a/web/cobrands/fixmystreet/staff.js b/web/cobrands/fixmystreet/staff.js
index b074a49f3..17bd54b8b 100644
--- a/web/cobrands/fixmystreet/staff.js
+++ b/web/cobrands/fixmystreet/staff.js
@@ -261,19 +261,22 @@ fixmystreet.staff_set_up = {
if ('geolocation' in navigator) {
var el = document.querySelector('.btn--geolocate');
- fixmystreet.geolocate(el, function(pos) {
- var latlon = new OpenLayers.LonLat(pos.coords.longitude, pos.coords.latitude);
- var bng = latlon.clone().transform(
- new OpenLayers.Projection("EPSG:4326"),
- new OpenLayers.Projection("EPSG:27700") // TODO: Handle other projections
- );
- $("#problem_northing").text(bng.lat.toFixed(1));
- $("#problem_easting").text(bng.lon.toFixed(1));
- $("#problem_latitude").text(latlon.lat.toFixed(6));
- $("#problem_longitude").text(latlon.lon.toFixed(6));
- $inspect_form.find("input[name=latitude]").val(latlon.lat);
- $inspect_form.find("input[name=longitude]").val(latlon.lon);
- });
+ // triage pages may not show geolocation button
+ if (el) {
+ fixmystreet.geolocate(el, function(pos) {
+ var latlon = new OpenLayers.LonLat(pos.coords.longitude, pos.coords.latitude);
+ var bng = latlon.clone().transform(
+ new OpenLayers.Projection("EPSG:4326"),
+ new OpenLayers.Projection("EPSG:27700") // TODO: Handle other projections
+ );
+ $("#problem_northing").text(bng.lat.toFixed(1));
+ $("#problem_easting").text(bng.lon.toFixed(1));
+ $("#problem_latitude").text(latlon.lat.toFixed(6));
+ $("#problem_longitude").text(latlon.lon.toFixed(6));
+ $inspect_form.find("input[name=latitude]").val(latlon.lat);
+ $inspect_form.find("input[name=longitude]").val(latlon.lon);
+ });
+ }
}
// Make the "Provide an update" form toggleable, hidden by default.
diff --git a/web/cobrands/isleofwight/_colours.scss b/web/cobrands/isleofwight/_colours.scss
new file mode 100644
index 000000000..688eb66e0
--- /dev/null
+++ b/web/cobrands/isleofwight/_colours.scss
@@ -0,0 +1,31 @@
+/* COLOURS */
+
+$menu-image: 'menu-black';
+
+$mappage-header-height: 124px;
+
+$blue: #00478c;
+$cyan: #00aeef; // + 60 25
+$orange: #fcaf17;
+$green: #75c044;
+
+//Any 20% tint of the above
+
+$primary_text: #fff;
+$primary: $cyan;
+$primary_b: #222;
+
+$base_bg: #fff;
+$base_fg: #222;
+
+$nav_background_colour: #fff;
+$nav_colour: $blue;
+$nav_hover_background_colour: $cyan;
+
+$col_click_map: $green;
+
+$header-top-border: false;
+
+$body-font: Helvetica, Arial, sans-serif;
+$heading-font: $body-font;
+$meta-font: $body-font;
diff --git a/web/cobrands/isleofwight/assets.js b/web/cobrands/isleofwight/assets.js
new file mode 100644
index 000000000..a68b0418b
--- /dev/null
+++ b/web/cobrands/isleofwight/assets.js
@@ -0,0 +1,311 @@
+(function(){
+
+if (!fixmystreet.maps) {
+ return;
+}
+
+var defaults = {
+ http_options: {
+ url: "https://tilma.staging.mysociety.org/mapserver/iow",
+ params: {
+ SERVICE: "WFS",
+ VERSION: "1.1.0",
+ REQUEST: "GetFeature",
+ SRSNAME: "urn:ogc:def:crs:EPSG::27700"
+ }
+ },
+ format_class: OpenLayers.Format.GML.v3.MultiCurveFix,
+ max_resolution: {
+ 'isleofwight': 0.5291677250021167,
+ 'fixmystreet': 1.194328566789627
+ },
+ attributes: {
+ central_asset_id: 'central_asset_id',
+ site_code: 'site_code'
+ },
+ min_resolution: 0.00001,
+ asset_id_field: 'asset_id',
+ geometryName: 'msGeometry',
+ srsName: "EPSG:27700",
+ strategy_class: OpenLayers.Strategy.FixMyStreet,
+ body: "Isle of Wight Council"
+};
+
+var pin_prefix = fixmystreet.pin_prefix || document.getElementById('js-map-data').getAttribute('data-pin_prefix');
+
+var labeled_default = {
+ fillColor: "#FFFF00",
+ fillOpacity: 0.6,
+ strokeColor: "#000000",
+ strokeOpacity: 0.8,
+ strokeWidth: 2,
+ pointRadius: 6
+};
+
+var labeled_select = {
+ externalGraphic: pin_prefix + "pin-spot.png",
+ fillColor: "#55BB00",
+ graphicWidth: 48,
+ graphicHeight: 64,
+ graphicXOffset: -24,
+ graphicYOffset: -56,
+ backgroundGraphic: pin_prefix + "pin-shadow.png",
+ backgroundWidth: 60,
+ backgroundHeight: 30,
+ backgroundXOffset: -7,
+ backgroundYOffset: -22,
+ popupYOffset: -40,
+ graphicOpacity: 1.0,
+
+ label: "${asset_id}",
+ labelOutlineColor: "white",
+ labelOutlineWidth: 3,
+ labelYOffset: 65,
+ fontSize: '15px',
+ fontWeight: 'bold'
+};
+
+var labeled_stylemap = new OpenLayers.StyleMap({
+ 'default': new OpenLayers.Style(labeled_default),
+ 'select': new OpenLayers.Style(labeled_select)
+});
+
+fixmystreet.assets.add($.extend(true, {}, defaults, {
+ http_options: {
+ params: {
+ TYPENAME: "streets"
+ }
+ },
+ always_visible: true,
+ non_interactive: true,
+ asset_type: 'area',
+ max_resolution: {
+ 'isleofwight': 6.614596562526458,
+ 'fixmystreet': 4.777314267158508
+ },
+ usrn: {
+ attribute: 'SITE_CODE',
+ field: 'site_code'
+ },
+ stylemap: new OpenLayers.StyleMap({
+ 'default': new OpenLayers.Style({
+ fill: false,
+ strokeColor: "#5555FF",
+ strokeOpacity: 0.1,
+ strokeWidth: 7
+ })
+ })
+}));
+
+function not_found_msg_update() {
+ $('.category_meta_message').html('Please select an item or a road/pavement/path on the map &raquo;');
+ $('.category_meta_message').removeClass('meta-highlight');
+ $("input[name=asset_details]").val('');
+}
+
+function found_item(layer, asset) {
+ var id = asset.attributes.central_asset_id || '';
+ if (id !== '') {
+ var attrib = asset.attributes;
+ var asset_name = attrib.feature_type_name + '; ' + attrib.site_name + '; ' + attrib.feature_location;
+ $('.category_meta_message').html('You have selected ' + asset_name);
+ $('.category_meta_message').addClass('meta-highlight');
+ $("input[name=asset_details]").val(asset_name);
+ } else {
+ not_found_msg_update();
+ }
+}
+
+
+var point_asset_defaults = $.extend(true, {}, defaults, {
+ snap_threshold: 5,
+ select_action: true,
+ asset_type: 'spot',
+ asset_item: "item",
+ actions: {
+ asset_found: function(asset) {
+ found_item(this, asset);
+ },
+ asset_not_found: function() {
+ not_found_msg_update();
+ }
+ }
+
+});
+
+var line_asset_defaults = $.extend(true, {}, defaults, {
+ display_zoom_message: true,
+ non_interactive: true,
+ road: true,
+ stylemap: fixmystreet.assets.stylemap_invisible,
+ usrn: {
+ attribute: 'site_code',
+ field: 'site_code'
+ },
+ asset_item: 'road',
+ actions: {
+ found: function(layer, feature) {
+ if ( fixmystreet.assets.selectedFeature() ) {
+ return;
+ }
+ found_item(layer, feature);
+ },
+ not_found: function(layer) {
+ if ( fixmystreet.assets.selectedFeature() ) {
+ return;
+ }
+ not_found_msg_update();
+ }
+ }
+});
+
+
+var point_category_list = [
+ //"Dog Fouling",
+ "Manholes",
+ "Trees & Hedges",
+ //"Pavements/footpaths",
+ //"Drainage",
+ //"Car Parking",
+ "Street Lighting",
+ "Bus Stops",
+ //"Flyposting",
+ //"Potholes",
+ //"Street Cleaning",
+ "Bridges & Walls",
+ "Traffic Lights",
+ "Street Furniture",
+ //"Roads/Highways",
+ "Road Traffic Signs & Markings",
+ "Grass Verges & Weeds",
+ //"Flytipping",
+ //"Graffiti",
+ "Street Nameplates",
+ //"Abandoned Vehicles"
+];
+
+var line_category_list = [
+ "Dog Fouling",
+ "Drainage",
+ "Car Parking",
+ "Pavements/footpaths",
+ "Potholes",
+ "Street Cleaning",
+ "Roads/Highways",
+ "Flytipping",
+ "Abandoned Vehicles"
+];
+
+var layer_map = {
+ "Dog Fouling": "Dog_Fouling",
+ "Drainage": "Drainage_line",
+ "Car Parking": "Car_Parks",
+ "Trees & Hedges": "Trees_Hedges",
+ "Pavements/footpaths": "Pavements_footpaths",
+ "Street Lighting": "Street_Lighting",
+ "Bus Stops": "Bus_Stops",
+ "Street Cleaning": "Street_Cleaning",
+ "Bridges & Walls": "Bridges_Walls",
+ "Traffic Lights": "Traffic_Lights",
+ "Street Furniture": "Street_Furniture",
+ "Roads/Highways": "Roads_Highways",
+ "Road Traffic Signs & Markings": "Road_Traffic_Signs_Markings",
+ "Grass Verges & Weeds": "Grass_Verges_Weeds",
+ "Street Nameplates": "Street_Nameplates",
+ "Abandoned Vehicles": "Abandoned_Vehicles"
+};
+
+for (i = 0; i < point_category_list.length; i++) {
+ cat = point_category_list[i];
+ layer = layer_map[cat] || cat;
+
+ fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: cat,
+ http_options: {
+ params: {
+ TYPENAME: layer
+ }
+ }
+ }));
+}
+
+for (i = 0; i < line_category_list.length; i++) {
+ cat = line_category_list[i];
+ layer = layer_map[cat] || cat;
+
+ fixmystreet.assets.add($.extend(true, {}, line_asset_defaults, {
+ asset_group: cat,
+ asset_category: [
+ cat
+ ],
+ http_options: {
+ params: {
+ TYPENAME: layer
+ }
+ }
+ }));
+}
+
+// non union layers
+fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: "Roads/Highways",
+ http_options: {
+ params: {
+ TYPENAME: "Fords"
+ }
+ }
+}));
+
+fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: "Roads/Highways",
+ http_options: {
+ params: {
+ TYPENAME: "Furn-Grid_and_Stones"
+ }
+ }
+}));
+
+
+fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: "Drainage",
+ http_options: {
+ params: {
+ TYPENAME: "Drainage_spot"
+ }
+ }
+}));
+
+fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: "Car Parking",
+ http_options: {
+ params: {
+ TYPENAME: "Car_Parking"
+ }
+ }
+}));
+
+fixmystreet.assets.add($.extend(true, {}, line_asset_defaults, {
+ asset_group: "Grass Verges & Weeds",
+ asset_category: [
+ "Grass Verges & Weeds"
+ ],
+ http_options: {
+ params: {
+ TYPENAME: "Verges-Natural"
+ }
+ }
+}));
+
+fixmystreet.assets.add($.extend(true, {}, point_asset_defaults, {
+ asset_group: "Dog Fouling",
+ http_options: {
+ params: {
+ TYPENAME: "Furn-Bins"
+ }
+ }
+}));
+
+fixmystreet.message_controller.add_msg_after_bodies(defaults.body);
+
+
+})();
diff --git a/web/cobrands/isleofwight/base.scss b/web/cobrands/isleofwight/base.scss
new file mode 100644
index 000000000..aae8e9f7c
--- /dev/null
+++ b/web/cobrands/isleofwight/base.scss
@@ -0,0 +1,18 @@
+@import "../sass/h5bp";
+@import "./_colours";
+@import "../sass/mixins";
+@import "../sass/base";
+
+/* Header */
+
+#site-logo {
+ width: 141px;
+ height: 38px;
+ padding: 1em 0;
+ background: url(/cobrands/isleofwight/images/logo.gif) 0 50% no-repeat;
+ background-size: 141px 38px;
+}
+
+#map_box #map {
+ background-color: white;
+}
diff --git a/web/cobrands/isleofwight/images/email-logo.gif b/web/cobrands/isleofwight/images/email-logo.gif
new file mode 120000
index 000000000..94a12010e
--- /dev/null
+++ b/web/cobrands/isleofwight/images/email-logo.gif
@@ -0,0 +1 @@
+logo.gif \ No newline at end of file
diff --git a/web/cobrands/isleofwight/images/logo.gif b/web/cobrands/isleofwight/images/logo.gif
new file mode 100644
index 000000000..7238ca8a3
--- /dev/null
+++ b/web/cobrands/isleofwight/images/logo.gif
Binary files differ
diff --git a/web/cobrands/isleofwight/js.js b/web/cobrands/isleofwight/js.js
new file mode 100644
index 000000000..d43006fd5
--- /dev/null
+++ b/web/cobrands/isleofwight/js.js
@@ -0,0 +1,33 @@
+(function(){
+
+if (!fixmystreet.maps) {
+ return;
+}
+
+if (fixmystreet.cobrand == 'isleofwight') {
+ // We want the cobranded site to always display "Island Roads"
+ // as the destination for reports in the "Public details" section.
+ // This is OK because the cobranded site only shows categories which
+ // Island Roads actually handle.
+ // To achieve this we ignore the passed list of bodies and always
+ // use "Island Roads" when calling the original function.
+ // NB calling the original function is required so that private categories
+ // cause the correct text to be shown in the UI.
+ var original_update_public_councils_text = fixmystreet.update_public_councils_text;
+ fixmystreet.update_public_councils_text = function(text, bodies) {
+ original_update_public_councils_text.call(this, text, ['Island Roads']);
+ };
+}
+
+var org_id = '1062';
+var body = "Isle of Wight Council";
+fixmystreet.assets.add(fixmystreet.roadworks.layer_future, {
+ http_options: { params: { organisation_id: org_id } },
+ body: body
+});
+fixmystreet.assets.add(fixmystreet.roadworks.layer_planned, {
+ http_options: { params: { organisation_id: org_id } },
+ body: body
+});
+
+})();
diff --git a/web/cobrands/isleofwight/layout.scss b/web/cobrands/isleofwight/layout.scss
new file mode 100644
index 000000000..924092a86
--- /dev/null
+++ b/web/cobrands/isleofwight/layout.scss
@@ -0,0 +1,26 @@
+@import "_colours";
+
+@import "../sass/layout";
+
+body.twothirdswidthpage .content .sticky-sidebar aside {
+ top: 10em;
+}
+
+#site-logo {
+ width: 282px;
+ height: 76px;
+ padding: 24px 0;
+ background-position: 0px 50%;
+ background-size: 282px 76px;
+}
+
+.mappage #site-header {
+ box-sizing: border-box;
+ border-bottom: solid 5px $cyan;
+}
+
+.meta-highlight {
+ margin: 1em -1em;
+ padding: 2em 2em;
+ background-color: mix(#fff, $primary, 70%);
+}
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index 4e4201d3a..1588bda2e 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -676,7 +676,7 @@ $.extend(fixmystreet.utils, {
styleMap: pin_layer_style_map
};
if (fixmystreet.page == 'around') {
- fixmystreet.bbox_strategy = fixmystreet.bbox_strategy || new OpenLayers.Strategy.FixMyStreet();
+ fixmystreet.bbox_strategy = fixmystreet.map_bbox_strategy || new OpenLayers.Strategy.FixMyStreet();
pin_layer_options.strategies = [ fixmystreet.bbox_strategy ];
}
if (fixmystreet.page == 'reports') {
diff --git a/web/js/map-wmts-isleofwight.js b/web/js/map-wmts-isleofwight.js
new file mode 100644
index 000000000..464bee913
--- /dev/null
+++ b/web/js/map-wmts-isleofwight.js
@@ -0,0 +1,206 @@
+/*
+ * Maps for FMS using Island Roads' WMTS tile server
+ */
+
+fixmystreet.maps.layer_bounds = new OpenLayers.Bounds(
+ 428576.1131782566,
+ 70608.46901095579,
+ 468137.51522498735,
+ 101069.6062942903
+);
+
+fixmystreet.maps.matrix_ids = [
+ // The first 5 levels don't load and are really zoomed-out, so
+ // they're not included here.
+ //{
+ //"identifier": 0,
+ //"scaleDenominator": 566965.4196450538,
+ //"supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ //"tileWidth": 256,
+ //"tileHeight": 256,
+ //"matrixWidth": 140,
+ //"matrixHeight": 109
+ //},
+ //{
+ //"identifier": 1,
+ //"scaleDenominator": 472471.18303754483,
+ //"supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ //"tileWidth": 256,
+ //"tileHeight": 256,
+ //"matrixWidth": 168,
+ //"matrixHeight": 130
+ //},
+ //{
+ //"identifier": 2,
+ //"scaleDenominator": 377976.9464300358,
+ //"supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ //"tileWidth": 256,
+ //"tileHeight": 256,
+ //"matrixWidth": 210,
+ //"matrixHeight": 163
+ //},
+ //{
+ //"identifier": 3,
+ //"scaleDenominator": 283482.7098225269,
+ //"supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ //"tileWidth": 256,
+ //"tileHeight": 256,
+ //"matrixWidth": 280,
+ //"matrixHeight": 217
+ //},
+ //{
+ //"identifier": 4,
+ //"scaleDenominator": 188988.4732150179,
+ //"supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ //"tileWidth": 256,
+ //"tileHeight": 256,
+ //"matrixWidth": 420,
+ //"matrixHeight": 325
+ //},
+ {
+ "identifier": 5,
+ "scaleDenominator": 94494.23660750895,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 840,
+ "matrixHeight": 650
+ },
+ {
+ "identifier": 6,
+ "scaleDenominator": 70870.67745563173,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 1120,
+ "matrixHeight": 867
+ },
+ {
+ "identifier": 7,
+ "scaleDenominator": 47247.118303754476,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 1680,
+ "matrixHeight": 1300
+ },
+ {
+ "identifier": 8,
+ "scaleDenominator": 23623.559151877238,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 3360,
+ "matrixHeight": 2599
+ },
+ {
+ "identifier": 9,
+ "scaleDenominator": 9449.423660750896,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 8399,
+ "matrixHeight": 6496
+ },
+ {
+ "identifier": 10,
+ "scaleDenominator": 7559.538928600717,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 10499,
+ "matrixHeight": 8120
+ },
+ {
+ "identifier": 11,
+ "scaleDenominator": 5669.654196450538,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 13998,
+ "matrixHeight": 10826
+ },
+ {
+ "identifier": 12,
+ "scaleDenominator": 3779.7694643003583,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 20997,
+ "matrixHeight": 16239
+ },
+ {
+ "identifier": 13,
+ "scaleDenominator": 1889.8847321501792,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 41993,
+ "matrixHeight": 32478
+ },
+ {
+ "identifier": 14,
+ "scaleDenominator": 944.9423660750896,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 83985,
+ "matrixHeight": 64955
+ },
+ {
+ "identifier": 15,
+ "scaleDenominator": 377.9769464300358,
+ "supportedCRS": "urn:ogc:def:crs:EPSG:27700",
+ "tileWidth": 256,
+ "tileHeight": 256,
+ "matrixWidth": 209961,
+ "matrixHeight": 162387
+ }
+];
+
+/*
+ * maps.config() is called on dom ready in map-OpenLayers.js
+ * to setup the way the map should operate.
+ */
+fixmystreet.maps.config = function() {
+ var permalink_id;
+ if ($('#map_permalink').length) {
+ permalink_id = 'map_permalink';
+ }
+
+ fixmystreet.controls = [
+ new OpenLayers.Control.ArgParserFMS(),
+ new OpenLayers.Control.Navigation(),
+ new OpenLayers.Control.PermalinkFMS(permalink_id),
+ new OpenLayers.Control.PanZoomFMS({id: 'fms_pan_zoom' })
+ ];
+
+ /* Linking back to around from report page, keeping track of map moves */
+ if ( fixmystreet.page == 'report' ) {
+ fixmystreet.controls.push( new OpenLayers.Control.PermalinkFMS('key-tool-problems-nearby', '/around') );
+ }
+
+ this.setup_wmts_base_map();
+};
+
+fixmystreet.maps.marker_size = function() {
+ var zoom = fixmystreet.map.getZoom() + fixmystreet.zoomOffset;
+ if (zoom >= 7) {
+ return 'normal';
+ } else if (zoom >= 4) {
+ return 'small';
+ } else {
+ return 'mini';
+ }
+};
+
+fixmystreet.maps.selected_marker_size = function() {
+ var zoom = fixmystreet.map.getZoom() + fixmystreet.zoomOffset;
+ if (zoom >= 7) {
+ return 'big';
+ } else if (zoom >= 4) {
+ return 'normal';
+ } else {
+ return 'small';
+ }
+};