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/Bodies.pm6
-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.pm8
-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/Cobrand/Zurich.pm72
-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/Geocode/Zurich.pm30
-rw-r--r--perllib/FixMyStreet/Map/IsleOfWight.pm63
-rw-r--r--perllib/FixMyStreet/SendReport/Email.pm13
-rw-r--r--perllib/FixMyStreet/SendReport/Triage.pm20
-rw-r--r--perllib/FixMyStreet/TestMech.pm11
-rwxr-xr-xperllib/Open311/PostServiceRequestUpdates.pm10
-rw-r--r--t/Mock/MapIt.pm1
-rw-r--r--t/app/controller/admin/bodies.t4
-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/cobrand/zurich.t1078
-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/bodies/open311-form-fields.html2
-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/common_header_tags.html5
-rw-r--r--templates/web/base/header/title.html4
-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
-rw-r--r--templates/web/base/reports/_list-filter-status.html45
-rw-r--r--templates/web/base/reports/_list-filters.html47
-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--templates/web/westminster/footer_extra_js.html2
-rw-r--r--templates/web/zurich/admin/bodies/contact-form.html10
-rw-r--r--templates/web/zurich/admin/bodies/form.html12
-rw-r--r--templates/web/zurich/admin/index-dm.html4
-rw-r--r--templates/web/zurich/admin/report_edit-sdm.html29
-rw-r--r--templates/web/zurich/admin/report_edit.html25
-rw-r--r--templates/web/zurich/header.html1
-rw-r--r--templates/web/zurich/header/title.html4
-rw-r--r--templates/web/zurich/header_opengraph.html8
-rw-r--r--templates/web/zurich/reports/_list-filter-status.html7
-rw-r--r--web/cobrands/fixmystreet-uk-councils/roadworks.js12
-rw-r--r--web/cobrands/fixmystreet/assets.js36
-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/cobrands/westminster/roadworks.js32
-rw-r--r--web/cobrands/zurich/layout.scss3
-rw-r--r--web/js/map-OpenLayers.js17
-rw-r--r--web/js/map-wmts-base.js23
-rw-r--r--web/js/map-wmts-isleofwight.js206
98 files changed, 3745 insertions, 899 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/Bodies.pm b/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm
index 3d5f1084d..fa5a55213 100644
--- a/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm
@@ -396,9 +396,13 @@ sub body_params : Private {
);
my %params = map { $_ => $c->get_param($_) || $defaults{$_} } keys %defaults;
$c->forward('check_body_params', [ \%params ]);
+
my @extras = qw/fetch_all_problems/;
+ my $cobrand_extras = $c->cobrand->call_hook('body_extra_fields');
+ push @extras, @$cobrand_extras if $cobrand_extras;
+
%defaults = map { $_ => '' } @extras;
- my %extras = map { $_ => $c->get_param($_) || $defaults{$_} } @extras;
+ my %extras = map { $_ => $c->get_param("extra[$_]") || $defaults{$_} } @extras;
return { params => \%params, extras => \%extras };
}
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 9b33b42b4..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) };
@@ -702,8 +705,9 @@ sub stash_report_filter_status : Private {
my @status = $c->get_param_list('status', 1);
@status = ($c->stash->{page} eq 'my' ? 'all' : $c->cobrand->on_map_default_status) unless @status;
- my %status = map { $_ => 1 } @status;
+ $c->cobrand->call_hook(hook_report_filter_status => \@status);
+ my %status = map { $_ => 1 } @status;
my %filter_problem_states;
my %filter_status;
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/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index 5fea9a03f..9cf1030f0 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -9,6 +9,8 @@ use Scalar::Util 'blessed';
use DateTime::Format::Pg;
use Try::Tiny;
+use FixMyStreet::Geocode::Zurich;
+
use strict;
use warnings;
use utf8;
@@ -141,7 +143,7 @@ sub problem_as_hashref {
$hashref->{title} = _('This report is awaiting moderation.');
$hashref->{banner_id} = 'closed';
} else {
- if ( $problem->state eq 'confirmed' || $problem->state eq 'external' ) {
+ if ( $problem->state eq 'confirmed' ) {
$hashref->{banner_id} = 'closed';
} elsif ( $problem->is_fixed || $problem->is_closed ) {
$hashref->{banner_id} = 'fixed';
@@ -152,7 +154,7 @@ sub problem_as_hashref {
if ( $problem->state eq 'confirmed' ) {
$hashref->{state} = 'open';
$hashref->{state_t} = _('Open');
- } elsif ( $problem->state eq 'wish' ) {
+ } elsif ( $problem->state eq 'wish' || $problem->state eq 'external' ) {
$hashref->{state_t} = _('Closed');
} elsif ( $problem->is_fixed ) {
$hashref->{state} = 'closed';
@@ -329,6 +331,14 @@ sub report_page_data {
$c->detach('ajax', [ 'reports/_problem-list.html' ]);
}
+ my @categories = $c->model('DB::Contact')->not_deleted->search(undef, {
+ columns => [ 'category', 'extra' ],
+ order_by => [ 'category' ],
+ distinct => 1
+ })->all;
+ $c->stash->{filter_categories} = \@categories;
+ $c->stash->{filter_category} = { map { $_ => 1 } $c->get_param_list('filter_category', 1) };
+
my $pins = $c->stash->{pins};
FixMyStreet::Map::display_map(
$c,
@@ -522,12 +532,16 @@ sub admin {
}
sub category_options {
- my ($self, $c) = @_;
+ my $self = shift;
+ my $c = $self->{c};
my @categories = $c->model('DB::Contact')->not_deleted->all;
- $c->stash->{category_options} = [ map { {
- category => $_->category, category_display => $_->category,
+ @categories = map { {
+ category => $_->category,
+ category_display => $_->get_extra_metadata('admin_label') || $_->category,
abbreviation => $_->get_extra_metadata('abbreviation'),
- } } @categories ];
+ } } @categories;
+ @categories = sort { $a->{category_display} cmp $b->{category_display} } @categories;
+ $c->stash->{category_options} = \@categories;
}
sub admin_report_edit {
@@ -553,21 +567,39 @@ sub admin_report_edit {
$c->stash->{bodies} = \@bodies;
# Can change category to any other
- $self->category_options($c);
+ $self->category_options;
} elsif ($type eq 'dm') {
# Can assign to:
my @bodies = $c->model('DB::Body')->search( [
- { 'me.parent' => $body->parent->id }, # Other DMs on the same level
{ 'me.parent' => $body->id }, # Their subdivisions
{ 'me.parent' => undef, 'bodies.id' => undef }, # External bodies
- ], { join => 'bodies', distinct => 1 } );
- @bodies = sort { strcoll($a->name, $b->name) } @bodies;
+ ], { join => 'bodies', distinct => 1 } )->all;
+ @bodies = grep {
+ my $cat = $_->get_extra_metadata('category');
+ if ($cat) {
+ $cat = $c->model('DB::Contact')->not_deleted->search({ category => $cat })->first;
+ }
+ !$cat || $cat->body_id == $body->id;
+ } @bodies;
+ @bodies = sort {
+ my $a_cat = $a->get_extra_metadata('category');
+ my $b_cat = $b->get_extra_metadata('category');
+ if ($a_cat && $b_cat) {
+ strcoll($a->name, $b->name)
+ } elsif ($a_cat) {
+ -1;
+ } elsif ($b_cat) {
+ 1;
+ } else {
+ strcoll($a->name, $b->name)
+ }
+ } @bodies;
$c->stash->{bodies} = \@bodies;
# Can change category to any other
- $self->category_options($c);
+ $self->category_options;
}
@@ -927,6 +959,11 @@ sub admin_report_edit {
}
+sub admin_district_lookup {
+ my ($self, $row) = @_;
+ FixMyStreet::Geocode::Zurich::admin_district($row->local_coords);
+}
+
sub stash_states {
my ($self, $problem) = @_;
my $c = $self->{c};
@@ -1135,7 +1172,7 @@ sub admin_stats {
}
# Can change category to any other
- $self->category_options($c);
+ $self->category_options;
# Total reports (non-hidden)
my $total = $c->model('DB::Problem')->search( \%params )->count;
@@ -1305,7 +1342,9 @@ sub reports_per_page { return 20; }
sub singleton_bodies_str { 1 }
-sub contact_extra_fields { [ 'abbreviation' ] };
+sub body_extra_fields { [ 'category' ] };
+
+sub contact_extra_fields { [ 'abbreviation', 'admin_label' ] };
sub default_problem_state { 'submitted' }
@@ -1343,4 +1382,11 @@ sub db_state_migration {
}
}
+sub hook_report_filter_status {
+ my ($self, $status) = @_;
+ @$status = map {
+ $_ eq 'closed' ? ('closed', 'fixed') : $_
+ } @$status;
+}
+
1;
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/Geocode/Zurich.pm b/perllib/FixMyStreet/Geocode/Zurich.pm
index 38df431c9..0b85ab7b2 100644
--- a/perllib/FixMyStreet/Geocode/Zurich.pm
+++ b/perllib/FixMyStreet/Geocode/Zurich.pm
@@ -24,6 +24,8 @@ sub setup_soap {
# Variables for the SOAP web service
my $geocoder = FixMyStreet->config('GEOCODER');
+ return unless ref $geocoder eq 'HASH';
+
my $url = $geocoder->{url};
my $username = $geocoder->{username};
my $password = $geocoder->{password};
@@ -49,6 +51,34 @@ sub setup_soap {
$method = SOAP::Data->name('getLocation95')->attr({ xmlns => $attr });
}
+sub admin_district {
+ my ($e, $n) = @_;
+
+ setup_soap();
+ return unless $soap;
+
+ my $attr = 'http://ch/geoz/fixmyzuerich/service';
+ my $bo = 'http://ch/geoz/fixmyzuerich/bo';
+ my $method = SOAP::Data->name('getInfoByLocation')->attr({ xmlns => $attr });
+ my $location = SOAP::Data->name(
+ 'location' => \SOAP::Data->value(
+ SOAP::Data->name('bo:easting', $e),
+ SOAP::Data->name('bo:northing', $n),
+ )
+ )->attr({ 'xmlns:bo' => $bo });
+ my $search = SOAP::Data->value($location);
+ my $result;
+ eval {
+ $result = $soap->call($method, $security, $search);
+ };
+ if ($@) {
+ warn $@ if FixMyStreet->config('STAGING_SITE');
+ return 'The geocoder appears to be down.';
+ }
+ $result = $result->result;
+ return $result;
+}
+
# string STRING CONTEXT
# Looks up on Zurich web service a user-inputted location.
# Returns array of (LAT, LON, ERROR), where ERROR is either undef, a string, or
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/Email.pm b/perllib/FixMyStreet/SendReport/Email.pm
index 6cd9afccd..09847cf5f 100644
--- a/perllib/FixMyStreet/SendReport/Email.pm
+++ b/perllib/FixMyStreet/SendReport/Email.pm
@@ -53,6 +53,15 @@ sub send_from {
return [ $row->user->email, $row->name ];
}
+sub envelope_sender {
+ my ($self, $row) = @_;
+
+ if ($row->user->email && $row->user->email_verified) {
+ return FixMyStreet::Email::unique_verp_id('report', $row->id);
+ }
+ return FixMyStreet->config('DO_NOT_REPLY_EMAIL');
+}
+
sub send {
my $self = shift;
my ( $row, $h ) = @_;
@@ -82,12 +91,10 @@ sub send {
$params->{Bcc} = $self->bcc if @{$self->bcc};
- my $sender;
+ my $sender = $self->envelope_sender($row);
if ($row->user->email && $row->user->email_verified) {
- $sender = FixMyStreet::Email::unique_verp_id('report', $row->id);
$params->{From} = $self->send_from( $row );
} else {
- $sender = FixMyStreet->config('DO_NOT_REPLY_EMAIL');
my $name = sprintf(_("On behalf of %s"), @{ $self->send_from($row) }[1]);
$params->{From} = [ $sender, $name ];
}
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/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 16871d0f2..927e4556c 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -229,6 +229,17 @@ sub get_email {
return $emails[0];
}
+sub get_email_envelope {
+ my $mech = shift;
+ my @emails = FixMyStreet::Email::Sender->default_transport->deliveries;
+ @emails = map { $_->{envelope} } @emails;
+
+ return @emails if wantarray;
+
+ $mech->email_count_is(1) || return undef;
+ return $emails[0];
+}
+
sub get_text_body_from_email {
my ($mech, $email, $obj) = @_;
unless ($email) {
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/bodies.t b/t/app/controller/admin/bodies.t
index c1072eb15..75f0f606f 100644
--- a/t/app/controller/admin/bodies.t
+++ b/t/app/controller/admin/bodies.t
@@ -162,7 +162,7 @@ subtest 'check open311 configuring' => sub {
jurisdiction => 'open311',
send_comments => 0,
send_method => 'Open311',
- fetch_all_problems => 1,
+ 'extra[fetch_all_problems]' => 1,
}
}
);
@@ -181,7 +181,7 @@ subtest 'check open311 configuring' => sub {
jurisdiction => 'open311',
send_comments => 0,
send_method => 'Open311',
- fetch_all_problems => 0,
+ 'extra[fetch_all_problems]' => 0,
can_be_devolved => 1, # for next test
}
}
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/cobrand/zurich.t b/t/cobrand/zurich.t
index 0bfdd8351..a08eb431e 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -6,6 +6,7 @@ use Email::MIME;
use File::Temp;
use LWP::Protocol::PSGI;
use Test::LongString;
+use Test::MockModule;
use Path::Tiny;
use t::Mock::MapItZurich;
use FixMyStreet::Script::Reports;
@@ -28,18 +29,8 @@ $cobrand->db_state_migration;
my $sample_file = path(__FILE__)->parent->parent->child("app/controller/sample.jpg");
ok $sample_file->exists, "sample file $sample_file exists";
-# This is a helper method that will send the reports but with the config
-# correctly set - notably STAGING_FLAGS send_reports needs to be true, and
-# zurich must be allowed cobrand if we want to be able to call cobrand
-# methods on it.
sub send_reports_for_zurich {
- FixMyStreet::override_config {
- STAGING_FLAGS => { send_reports => 1 },
- ALLOWED_COBRANDS => ['zurich']
- }, sub {
- # Actually send the report
- FixMyStreet::Script::Reports::send('zurich');
- };
+ FixMyStreet::Script::Reports::send('zurich');
}
sub reset_report_state {
my ($report, $created) = @_;
@@ -51,45 +42,45 @@ sub reset_report_state {
$report->whensent(undef);
$report->state('submitted');
$report->created($created) if $created;
+ $report->category('Other');
$report->update;
}
-# Front page test
-ok $mech->host("zurich.example.com"), "change host to Zurich";
+my $UPLOAD_DIR = File::Temp->newdir();
FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
+ STAGING_FLAGS => { send_reports => 1 },
+ ALLOWED_COBRANDS => 'zurich',
+ MAPIT_URL => 'http://mapit.zurich/',
+ MAPIT_TYPES => [ 'O08' ],
+ MAPIT_ID_WHITELIST => [ 423017 ],
+ MAP_TYPE => 'Zurich,OSM',
+ PHOTO_STORAGE_BACKEND => 'FileSystem',
+ PHOTO_STORAGE_OPTIONS => {
+ UPLOAD_DIR => $UPLOAD_DIR,
+ },
}, sub {
- $mech->get_ok('/');
-};
+
+# Front page test
+ok $mech->host("zurich.example.com"), "change host to Zurich";
+$mech->get_ok('/');
$mech->content_like( qr/zurich/i );
# Set up bodies
my $zurich = $mech->create_body_ok( 1, 'Zurich' );
-$zurich->parent( undef );
-$zurich->update;
-my $division = $mech->create_body_ok( 2, 'Division 1' );
-$division->parent( $zurich->id );
-$division->send_method( 'Zurich' );
-$division->endpoint( 'division@example.org' );
-$division->update;
-$division->body_areas->find_or_create({ area_id => 423017 });
-my $subdivision = $mech->create_body_ok( 3, 'Subdivision A' );
-$subdivision->parent( $division->id );
-$subdivision->send_method( 'Zurich' );
-$subdivision->endpoint( 'subdivision@example.org' );
-$subdivision->update;
-my $external_body = $mech->create_body_ok( 4, 'External Body' );
-$external_body->send_method( 'Zurich' );
-$external_body->endpoint( 'external_body@example.net' );
-$external_body->update;
+my $division = $mech->create_body_ok( 423017, 'Division 1', {
+ parent => $zurich->id, send_method => 'Zurich', endpoint => 'division@example.org' } );
+my $division2 = $mech->create_body_ok( 423017, 'Division 2', {
+ parent => $zurich->id, send_method => 'Zurich', endpoint => 'division2@example.org' } );
+my $subdivision = $mech->create_body_ok( 3, 'Subdivision A',
+ { parent => $division->id, send_method => 'Zurich', endpoint => 'subdivision@example.org' } );
+my $external_body = $mech->create_body_ok( 4, 'External Body',
+ { send_method => 'Zurich', endpoint => 'external_body@example.net' } );
+my $external_body2 = $mech->create_body_ok( 4, 'Another Body External',
+ { send_method => 'Zurich', endpoint => 'external_body2@example.net' } );
sub get_export_rows_count {
my $mech = shift;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get_ok( '/admin/stats?export=1' );
- };
+ $mech->get_ok( '/admin/stats?export=1' );
is $mech->res->code, 200, 'csv retrieved ok';
is $mech->content_type, 'text/csv', 'content_type correct' and do {
my @lines = split /\n/, $mech->content;
@@ -117,29 +108,15 @@ my @reports = $mech->create_problems_for_body( 1, $division->id, 'Test', {
});
my $report = $reports[0];
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
- $mech->get_ok( '/report/' . $report->id );
-};
+$mech->get_ok( '/report/' . $report->id );
$mech->content_contains('&Uuml;berpr&uuml;fung ausstehend')
or die $mech->content;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
- my $json = $mech->get_ok_json( '/report/ajax/' . $report->id );
- is $json->{report}->{title}, "&Uuml;berpr&uuml;fung ausstehend", "correct title";
- is $json->{report}->{state}, "submitted", "correct state";
-};
+my $json = $mech->get_ok_json( '/report/ajax/' . $report->id );
+is $json->{report}->{title}, "&Uuml;berpr&uuml;fung ausstehend", "correct title";
+is $json->{report}->{state}, "submitted", "correct state";
subtest "Banners are displayed correctly" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
for my $test (
{
description => 'new report',
@@ -162,8 +139,8 @@ subtest "Banners are displayed correctly" => sub {
{
description => 'closed report',
state => 'external',
- banner_id => 'closed',
- banner_text => 'Extern',
+ banner_id => 'fixed',
+ banner_text => 'Beantwortet',
},
{
description => 'in progress report',
@@ -211,17 +188,14 @@ subtest "Banners are displayed correctly" => sub {
};
}
$report->update({ state => 'submitted' });
- };
};
-# Check logging in to deal with this report
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
+my $user;
+subtest 'check logging in to deal with this report' => sub {
$mech->get_ok( '/admin' );
is $mech->uri->path, '/auth', "got sent to the sign in page";
- my $user = $mech->log_in_ok( 'dm1@example.org') ;
+ $user = $mech->log_in_ok( 'dm1@example.org') ;
$user->from_body( undef );
$user->update;
ok $mech->get( '/admin' );
@@ -230,12 +204,12 @@ FixMyStreet::override_config {
$user->update;
$mech->get_ok( '/admin' );
-};
-is $mech->uri->path, '/admin', "am logged in";
+ is $mech->uri->path, '/admin', "am logged in";
-$mech->content_contains( 'report_edit/' . $report->id );
-$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
-$mech->content_contains( 'Erfasst' );
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
+ $mech->content_contains( 'Erfasst' );
+};
subtest "changing of categories" => sub {
# create a few categories (which are actually contacts)
@@ -260,13 +234,8 @@ subtest "changing of categories" => sub {
ok ( !$comments_rs->first, "There are no comments yet" );
# change the category via the web interface
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { category => 'Cat2' } } );
- };
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { category => 'Cat2' } } );
# check changes correctly saved
$report->discard_changes();
@@ -280,6 +249,38 @@ subtest "changing of categories" => sub {
$report->update({category => $original_category });
};
+subtest "private categories" => sub {
+ $mech->log_in_ok( 'super@example.org' );
+ $mech->get_ok('/admin/bodies');
+ $mech->follow_link_ok({ text => 'Division 1' });
+ $mech->submit_form_ok({ with_fields => {
+ category => 'Allgemein',
+ state => 'inactive',
+ email => 'allgemein@example.org',
+ 'extra[admin_label]' => 'StadtPeople',
+ 'extra[abbreviation]' => 'STA',
+ note => 'New',
+ }});
+ $mech->follow_link_ok({ text => 'Allgemein' });
+ $mech->content_contains('<option value="inactive" selected>');
+ $mech->content_like(qr/admin_label.*?StadtPeople/);
+
+ $mech->get_ok( '/around?lat=47.381817&lon=8.529156' );
+ $mech->content_lacks('StadtPeople');
+ $mech->content_contains('Allgemein');
+ $mech->get_ok( '/report/new?lat=47.381817&lon=8.529156' );
+ $mech->content_lacks('StadtPeople');
+ $mech->content_lacks('Allgemein');
+
+ $report->update({ category => 'Allgemein' });
+ $mech->get_ok('/report/' . $report->id);
+ $mech->content_lacks('StadtPeople');
+ $mech->content_contains('Allgemein');
+
+ $mech->get_ok('/admin/report_edit/' . $report->id);
+ $mech->content_contains('<option value="Allgemein">StadtPeople (STA)</option>');
+};
+
sub get_moderated_count {
# my %date_params = ( );
# my $moderated = FixMyStreet::DB->resultset('Problem')->search({
@@ -288,17 +289,12 @@ sub get_moderated_count {
# use a separate mech to avoid stomping on test state
my $mech = FixMyStreet::TestMech->new;
- my $user = $mech->log_in_ok( 'super@example.org' );
+ $mech->log_in_ok( 'super@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $mech->get( '/admin/stats' );
if ($mech->content =~/Innerhalb eines Arbeitstages moderiert: (\d+)/) {
return $1;
- }
- else {
+ } else {
fail sprintf "Could not get moderation results (%d)", $mech->status;
return undef;
}
@@ -306,127 +302,112 @@ sub get_moderated_count {
subtest "report_edit" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
+ reset_report_state($report);
+ ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' );
+ is get_moderated_count(), 0;
- reset_report_state($report);
- ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' );
- is get_moderated_count(), 0;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Unbest&auml;tigt' ); # Unconfirmed email
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
+ $mech->log_in_ok( 'dm1@example.org') ;
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains( 'Unbest&auml;tigt' ); # Unconfirmed email
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes();
+ $report->discard_changes();
- $mech->content_contains('Aufgenommen');
- $mech->content_contains('Test Test');
- $mech->content_lacks('photo/' . $report->id . '.0.jpeg');
- $mech->email_count_is(0);
+ $mech->content_contains('Aufgenommen');
+ $mech->content_contains('Test Test');
+ $mech->content_lacks('photo/' . $report->id . '.0.jpeg');
+ $mech->email_count_is(0);
- $report->discard_changes;
+ $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' );
- is get_moderated_count(), 1;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' );
+ is get_moderated_count(), 1;
- # Set state back to 10 days ago so that report is overdue
- my $created = $report->created;
- reset_report_state($report, $created->clone->subtract(days => 10));
+ # Set state back to 10 days ago so that report is overdue
+ my $created = $report->created;
+ reset_report_state($report, $created->clone->subtract(days => 10));
- is get_moderated_count(), 0;
+ is get_moderated_count(), 0;
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' );
- is get_moderated_count(), 0, 'Moderated count not increased when overdue';
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' );
+ is get_moderated_count(), 0, 'Moderated count not increased when overdue';
- reset_report_state($report, $created);
+ reset_report_state($report, $created);
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
- $mech->get_ok( '/report/' . $report->id );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' );
- is get_moderated_count(), 1;
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
+ $mech->get_ok( '/report/' . $report->id );
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' );
+ is get_moderated_count(), 1;
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
- $mech->get_ok( '/report/' . $report->id, 'still visible as response not published yet' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
+ $mech->get_ok( '/report/' . $report->id, 'still visible as response not published yet' );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." );
- is ( $report->state, 'feedback pending', 'Marking hidden actually sets state to feedback pending');
- is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden');
- is get_moderated_count(), 1, 'Check still counted moderated'
- or diag $report->get_column('extra');
-
- # publishing actually sets hidden
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'publish_response' } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $report->discard_changes;
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." );
+ is ( $report->state, 'feedback pending', 'Marking hidden actually sets state to feedback pending');
+ is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden');
+ is get_moderated_count(), 1, 'Check still counted moderated'
+ or diag $report->get_column('extra');
+
+ # publishing actually sets hidden
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'publish_response' } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $report->discard_changes;
- is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." );
- is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden');
- is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status');
+ is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." );
+ is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden');
+ is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status');
- $mech->submit_form_ok( { with_fields => { new_internal_note => 'Initial internal note.' } } );
- $report->discard_changes;
- is ( $report->state, 'hidden', 'Another internal note does not reopen');
+ $mech->submit_form_ok( { with_fields => { new_internal_note => 'Initial internal note.' } } );
+ $report->discard_changes;
+ is ( $report->state, 'hidden', 'Another internal note does not reopen');
- $mech->get( '/report/' . $report->id);
- is $mech->res->code, 410;
+ $mech->get( '/report/' . $report->id);
+ is $mech->res->code, 410;
- reset_report_state($report);
- is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' );
- is get_moderated_count(), 0;
+ reset_report_state($report);
+ is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' );
+ is get_moderated_count(), 0;
- # Check that setting to 'hidden' also triggers moderation
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'publish_response' } );
+ # Check that setting to 'hidden' also triggers moderation
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { with_fields => { state => 'hidden' } } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'publish_response' } );
- $report->discard_changes;
- is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' );
- is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' );
- is get_moderated_count(), 1;
+ $report->discard_changes;
+ is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' );
+ is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' );
+ is get_moderated_count(), 1;
- is ($cobrand->get_or_check_overdue($report), 0, 'sanity check');
- $report->update({ created => $created->clone->subtract(days => 10) });
- is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased');
+ is ($cobrand->get_or_check_overdue($report), 0, 'sanity check');
+ $report->update({ created => $created->clone->subtract(days => 10) });
+ is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased');
- reset_report_state($report, $created);
- }
+ reset_report_state($report, $created);
};
# Give the report three photos
-my $UPLOAD_DIR = File::Temp->newdir();
my @files = map { $_ x 40 . ".jpeg" } (1..3);
$sample_file->copy(path($UPLOAD_DIR, $_)) for @files;
$report->photo(join(',', @files));
$report->update;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAP_TYPE => 'Zurich,OSM',
- PHOTO_STORAGE_BACKEND => 'FileSystem',
- PHOTO_STORAGE_OPTIONS => {
- UPLOAD_DIR => $UPLOAD_DIR,
- },
-}, sub {
- # Photo publishing
+subtest 'Photo publishing' => sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'confirmed', publish_photo_1 => 1 } } );
$mech->get_ok( '/around?lat=' . $report->latitude . ';lon=' . $report->longitude);
@@ -469,50 +450,37 @@ $mech->log_out_ok;
subtest 'SDM' => sub {
my $user = $mech->log_in_ok( 'sdm1@example.org') ;
$user->update({ from_body => undef });
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- ok $mech->get( '/admin' );
- };
+ ok $mech->get( '/admin' );
is $mech->res->code, 403, 'Got 403';
$user->from_body( $subdivision->id );
$user->update;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get_ok( '/admin' );
- };
+ $mech->get_ok( '/admin' );
is $mech->uri->path, '/admin', "am logged in";
$mech->content_contains( 'report_edit/' . $report->id );
$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
$mech->content_contains( 'In Bearbeitung' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains( 'Initial internal note' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains( 'Initial internal note' );
- $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
- is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
- $mech->content_contains('This is an update');
- ok $mech->form_with_fields( 'status_update' );
- $mech->submit_form_ok( { button => 'no_more_updates' } );
- is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
+ $mech->submit_form_ok( { with_fields => { status_update => 'This is an update.' } } );
+ is $mech->uri->path, '/admin/report_edit/' . $report->id, "still on edit page";
+ $mech->content_contains('This is an update');
+ ok $mech->form_with_fields( 'status_update' );
+ $mech->submit_form_ok( { button => 'no_more_updates' } );
+ is $mech->uri->path, '/admin/summary', "redirected now finished with report.";
- # Can still view the edit page but can't change anything
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_contains('<input disabled');
- $mech->submit_form_ok( { with_fields => { status_update => 'This is a disallowed update.' } } );
- $mech->content_lacks('This is a disallowed update');
+ # Can still view the edit page but can't change anything
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('<input disabled');
+ $mech->submit_form_ok( { with_fields => { status_update => 'This is a disallowed update.' } } );
+ $mech->content_lacks('This is a disallowed update');
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('In Bearbeitung');
- $mech->content_contains('Test Test');
- };
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('In Bearbeitung');
+ $mech->content_contains('Test Test');
send_reports_for_zurich();
$email = $mech->get_email;
@@ -524,106 +492,86 @@ subtest 'SDM' => sub {
is $report->state, 'feedback pending', 'Report now in feedback pending state';
subtest 'send_back' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { form_number => 2, button => 'send_back' } );
- $report->discard_changes;
- is $report->state, 'confirmed', 'Report sent back to confirmed state';
- is $report->bodies_str, $division->id, 'Report sent back to division';
- };
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { form_number => 2, button => 'send_back' } );
+ $report->discard_changes;
+ is $report->state, 'confirmed', 'Report sent back to confirmed state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
};
subtest 'not contactable' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } );
- $report->discard_changes;
- is $report->state, 'feedback pending', 'Report sent back to Rueckmeldung ausstehend state';
- is $report->get_extra_metadata('closure_status'), 'not contactable', 'Report sent back to not_contactable state';
- is $report->bodies_str, $division->id, 'Report sent back to division';
- };
+ $report->update({ bodies_str => $subdivision->id, state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } );
+ $report->discard_changes;
+ is $report->state, 'feedback pending', 'Report sent back to Rueckmeldung ausstehend state';
+ is $report->get_extra_metadata('closure_status'), 'not contactable', 'Report sent back to not_contactable state';
+ is $report->bodies_str, $division->id, 'Report sent back to division';
};
$mech->log_out_ok;
};
-my $user = $mech->log_in_ok( 'dm1@example.org') ;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
+subtest 'Test publishing of final update by DM' => sub {
+ $user = $mech->log_in_ok( 'dm1@example.org');
$mech->get_ok( '/admin' );
-};
-reset_report_state($report);
-$report->update({ state => 'feedback pending' });
+ reset_report_state($report);
+ $report->update({ state => 'feedback pending' });
-$mech->content_contains( 'report_edit/' . $report->id );
-$mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") );
-# User confirms their email address
-$report->set_extra_metadata(email_confirmed => 1);
-$report->confirmed(DateTime->now);
-$report->update;
+ # User confirms their email address
+ $report->set_extra_metadata(email_confirmed => 1);
+ $report->confirmed(DateTime->now);
+ $report->update;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
# Quick RSS check here, while we have a report
$mech->get_ok('/rss/problems');
+ my $module = Test::MockModule->new('FixMyStreet::Geocode::Zurich');
+ $module->mock(admin_district => sub { 'Admin district' });
+
$mech->get_ok( '/admin/report_edit/' . $report->id );
+
+ $mech->content_contains('Admin district');
+
$mech->content_lacks( 'Unbest&auml;tigt' ); # Confirmed email
$mech->submit_form_ok( { with_fields => { status_update => 'FINAL UPDATE' } } );
$mech->form_with_fields( 'status_update' );
$mech->submit_form_ok( { button => 'publish_response' } );
$mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Beantwortet');
+ $mech->content_contains('Test Test');
+ $mech->content_contains('FINAL UPDATE');
+
+ $email = $mech->get_email;
+ like $email->header('To'), qr/test\@example.com/, 'to line looks correct';
+ like $email->header('From'), qr/do-not-reply\@example.org/, 'from line looks correct';
+ like $email->body, qr/FINAL UPDATE/, 'body looks correct';
+ $mech->clear_emails_ok;
};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Test Test');
-$mech->content_contains('FINAL UPDATE');
-
-$email = $mech->get_email;
-like $email->header('To'), qr/test\@example.com/, 'to line looks correct';
-like $email->header('From'), qr/do-not-reply\@example.org/, 'from line looks correct';
-like $email->body, qr/FINAL UPDATE/, 'body looks correct';
-$mech->clear_emails_ok;
-# Assign feedback pending (via confirmed), don't confirm email
-@reports = $mech->create_problems_for_body( 1, $division->id, 'Second', {
- state => 'submitted',
- confirmed => undef,
- cobrand => 'zurich',
- areas => ',423017,',
-});
-$report = $reports[0];
+subtest "Assign feedback pending (via confirmed), don't confirm email, no email sent" => sub {
+ @reports = $mech->create_problems_for_body( 1, $division->id, 'Second', {
+ state => 'submitted',
+ confirmed => undef,
+ cobrand => 'zurich',
+ areas => ',423017,',
+ });
+ $report = $reports[0];
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'confirmed' } } );
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->submit_form_ok( { with_fields => { state => 'feedback pending' } } );
$mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('In Bearbeitung');
-$mech->content_contains('Second Test');
+ $mech->content_contains('In Bearbeitung');
+ $mech->content_contains('Second Test');
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
-}, sub {
$mech->get_ok( '/admin/report_edit/' . $report->id );
$mech->content_contains( 'Unbest&auml;tigt' );
$report->discard_changes;
@@ -631,12 +579,12 @@ FixMyStreet::override_config {
$mech->submit_form_ok( { button => 'publish_response', with_fields => { status_update => 'FINAL UPDATE' } } );
$mech->get_ok( '/report/' . $report->id );
-};
-$mech->content_contains('Beantwortet');
-$mech->content_contains('Second Test');
-$mech->content_contains('FINAL UPDATE');
+ $mech->content_contains('Beantwortet');
+ $mech->content_contains('Second Test');
+ $mech->content_contains('FINAL UPDATE');
-$mech->email_count_is(0);
+ $mech->email_count_is(0);
+};
# Report assigned to third party
@@ -650,31 +598,27 @@ $report = $reports[0];
subtest "external report triggers email" => sub {
my $EXTERNAL_MESSAGE = 'Look Ma, no hands!';
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # required to see body_external field
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail.
- $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
- $report->update;
+ # required to see body_external field
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail.
+ $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
+ $report->update;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ $report->discard_changes;
+ $mech->get_ok( '/report/' . $report->id );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- } });
- $report->discard_changes;
- $mech->get_ok( '/report/' . $report->id );
- };
is ($report->state, 'external', 'Report was closed correctly');
- $mech->content_contains('Extern')
+ $mech->content_contains('Beantwortet')
or die $mech->content;
$mech->content_contains('Third Test');
$mech->content_contains($report->get_extra_metadata('public_response')) or die $mech->content;
@@ -688,30 +632,25 @@ subtest "external report triggers email" => sub {
$mech->clear_emails_ok;
subtest "Test third_personal boolean setting" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin' );
- # required to see body_external field
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
- $report->update;
+ $mech->get_ok( '/admin' );
+ # required to see body_external field
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich');
+ $report->update;
- is $mech->uri->path, '/admin', "am logged in";
- $mech->content_contains( 'report_edit/' . $report->id );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- third_personal => 1,
- } });
- $mech->get_ok( '/report/' . $report->id );
- };
- $mech->content_contains('Extern');
+ is $mech->uri->path, '/admin', "am logged in";
+ $mech->content_contains( 'report_edit/' . $report->id );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ third_personal => 1,
+ } });
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Beantwortet');
$mech->content_contains('Third Test');
$mech->content_contains($report->get_extra_metadata('public_response'));
send_reports_for_zurich();
@@ -724,30 +663,25 @@ subtest "external report triggers email" => sub {
};
subtest "Test external wish sending" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # set as wish
- $report->discard_changes;
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'wish');
- $report->update;
- is ($report->state, 'feedback pending', 'Sanity check') or die;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
-
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- } });
- # Wishes publicly viewable
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('Freundliche Gruesse Ihre Stadt Zuerich');
- };
+ # set as wish
+ $report->discard_changes;
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'wish');
+ $report->update;
+ is ($report->state, 'feedback pending', 'Sanity check') or die;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ } });
+ # Wishes publicly viewable
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Freundliche Gruesse Ihre Stadt Zuerich');
send_reports_for_zurich();
$email = $mech->get_email;
like $email->header('Subject'), qr/Weitergeleitete Meldung/, 'subject looks okay';
@@ -760,30 +694,26 @@ subtest "external report triggers email" => sub {
subtest "Closure email includes public response" => sub {
my $PUBLIC_RESPONSE = "This is the public response to your report. Freundliche Gruesse.";
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # set as extern
- reset_report_state($report);
- $report->state('feedback pending');
- $report->set_extra_metadata('closure_status' => 'external');
- $report->set_extra_metadata('email_confirmed' => 1);
- $report->unset_extra_metadata('public_response');
- $report->update;
- is ($report->state, 'feedback pending', 'Sanity check') or die;
-
- $mech->get_ok( '/admin/report_edit/' . $report->id );
-
- $mech->form_with_fields( 'publish_response' );
- $mech->submit_form_ok( {
- button => 'publish_response',
- with_fields => {
- body_external => $external_body->id,
- external_message => $EXTERNAL_MESSAGE,
- status_update => $PUBLIC_RESPONSE,
- } });
- };
+ # set as extern
+ reset_report_state($report);
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->set_extra_metadata('email_confirmed' => 1);
+ $report->unset_extra_metadata('public_response');
+ $report->update;
+ is ($report->state, 'feedback pending', 'Sanity check') or die;
+
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+
+ $mech->form_with_fields( 'publish_response' );
+ $mech->submit_form_ok( {
+ button => 'publish_response',
+ with_fields => {
+ body_external => $external_body->id,
+ external_message => $EXTERNAL_MESSAGE,
+ status_update => $PUBLIC_RESPONSE,
+ } });
+
$email = $mech->get_email;
my $report_id = $report->id;
like Encode::decode('MIME-Header', $email->header('Subject')), qr/Meldung #$report_id/, 'subject looks okay';
@@ -798,91 +728,89 @@ subtest "superuser and dm can see stats" => sub {
$mech->log_out_ok;
$user = $mech->log_in_ok( 'super@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $mech->get( '/admin/stats' );
is $mech->res->code, 200, "superuser should be able to see stats page";
$mech->log_out_ok;
$user = $mech->log_in_ok( 'dm1@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $mech->get( '/admin/stats' );
- };
+ $mech->get( '/admin/stats' );
is $mech->res->code, 200, "dm can now also see stats page";
$mech->log_out_ok;
};
subtest "only superuser can edit bodies" => sub {
$user = $mech->log_in_ok( 'dm1@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- }, sub {
- $mech->get( '/admin/body/' . $zurich->id );
- };
+ $mech->get( '/admin/body/' . $zurich->id );
is $mech->res->code, 403, "only superuser should be able to edit bodies";
$mech->log_out_ok;
};
subtest "only superuser can see 'Add body' form" => sub {
$user = $mech->log_in_ok( 'dm1@example.org' );
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- }, sub {
- $mech->get_ok( '/admin/bodies' );
- };
+ $mech->get_ok( '/admin/bodies' );
$mech->content_contains('External Body');
$mech->content_lacks( '<form method="post" action="bodies"' );
$mech->log_out_ok;
};
subtest "phone number is mandatory" => sub {
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $user = $mech->log_in_ok( 'dm1@example.org' );
- $mech->get_ok( '/report/new?lat=47.381817&lon=8.529156' );
- $mech->submit_form( with_fields => { phone => "" } );
- $mech->content_contains( 'Diese Information wird ben&ouml;tigt' );
- $mech->log_out_ok;
- };
+ $user = $mech->log_in_ok( 'dm1@example.org' );
+ $mech->get_ok( '/report/new?lat=47.381817&lon=8.529156' );
+ $mech->submit_form( with_fields => { phone => "" } );
+ $mech->content_contains( 'Diese Information wird ben&ouml;tigt' );
+ $mech->log_out_ok;
};
subtest "phone number is not mandatory for reports from mobile apps" => sub {
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->post_ok( '/report/new/mobile?lat=47.381817&lon=8.529156' , {
- service => 'iPhone',
- detail => 'Problem-Bericht',
- lat => 47.381817,
- lon => 8.529156,
- email => 'user@example.org',
- pc => '',
- name => '',
- category => 'bad category',
- });
- my $res = $mech->response;
- ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
- unlike $res->content, qr/Diese Information wird ben&ouml;tigt/, 'response should not contain phone error';
- # Clear out the mailq
- $mech->clear_emails_ok;
- };
+ $mech->post_ok( '/report/new/mobile?lat=47.381817&lon=8.529156' , {
+ service => 'iPhone',
+ detail => 'Problem-Bericht',
+ lat => 47.381817,
+ lon => 8.529156,
+ email => 'user@example.org',
+ pc => '',
+ name => '',
+ category => 'bad category',
+ });
+ my $res = $mech->response;
+ ok $res->header('Content-Type') =~ m{^application/json\b}, 'response should be json';
+ unlike $res->content, qr/Diese Information wird ben&ouml;tigt/, 'response should not contain phone error';
+ # Clear out the mailq
+ $mech->clear_emails_ok;
+};
+
+subtest "link external body to category" => sub {
+ $mech->log_in_ok( 'super@example.org' );
+ $mech->get_ok( '/admin/body/' . $zurich->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $division->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $subdivision->id );
+ $mech->content_lacks('extra[category]');
+ $mech->get_ok( '/admin/body/' . $external_body->id );
+ $mech->content_contains('extra[category]');
+ $mech->submit_form_ok({ with_fields => { 'extra[category]' => 'Cat1' } });
+ $mech->content_contains('<option value="Cat1" selected>');
+ $external_body->discard_changes;
+ is $external_body->get_extra_metadata('category'), 'Cat1';
+};
+
+subtest "shows correct external bodies" => sub {
+ $report->discard_changes;
+ $report->state('feedback pending');
+ $report->set_extra_metadata('closure_status' => 'external');
+ $report->update;
+ $user = $mech->log_in_ok( 'dm1@example.org' );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_like(qr/<option[^>]*>External Body<\/option>\s*<option[^>]*>Another Body External<\/option>/); # Test order
+
+ $user = $mech->log_in_ok( 'dm2@example.org' );
+ $user->update({ from_body => $division2->id });
+ $report->update({ bodies_str => $division2->id });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_contains('Another Body External');
+ $mech->content_lacks('External Body');
+ $report->update({ bodies_str => $division->id });
};
subtest "problems can't be assigned to deleted bodies" => sub {
@@ -891,23 +819,15 @@ subtest "problems can't be assigned to deleted bodies" => sub {
$user->update;
$report->state( 'confirmed' );
$report->update;
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok( '/admin/body/' . $external_body->id );
- $mech->submit_form_ok( { with_fields => { deleted => 1 } } );
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->content_lacks( $external_body->name )
- or do {
- diag $mech->content;
- diag $external_body->name;
- die;
- };
- };
+ $mech->get_ok( '/admin/body/' . $external_body->id );
+ $mech->submit_form_ok( { with_fields => { deleted => 1 } } );
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->content_lacks( $external_body->name )
+ or do {
+ diag $mech->content;
+ diag $external_body->name;
+ die;
+ };
$user->from_body( $division->id );
$user->update;
$mech->log_out_ok;
@@ -924,44 +844,32 @@ subtest "photo must be supplied for categories that require it" => sub {
note => "note for graffiti",
extra => { photo_required => 1 }
});
- FixMyStreet::override_config {
- MAPIT_TYPES => [ 'O08' ],
- MAPIT_URL => 'http://mapit.zurich/',
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_ID_WHITELIST => [ 423017 ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- $mech->get_ok('/report/new?lat=47.381817&lon=8.529156');
- $mech->submit_form_ok({ with_fields => {
- detail => 'Problem-Bericht',
- username => 'user@example.org',
- category => 'Graffiti - photo required',
- }});
- is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
- $mech->content_contains(_("Photo is required."), 'response should contain photo error message');
- };
+ $mech->get_ok('/report/new?lat=47.381817&lon=8.529156');
+ $mech->submit_form_ok({ with_fields => {
+ detail => 'Problem-Bericht',
+ username => 'user@example.org',
+ category => 'Graffiti - photo required',
+ }});
+ is $mech->res->code, 200, "missing photo shouldn't return anything but 200";
+ $mech->content_contains(_("Photo is required."), 'response should contain photo error message');
};
subtest "test stats" => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- }, sub {
- $user = $mech->log_in_ok( 'super@example.org' );
-
- $mech->get_ok( '/admin/stats' );
- is $mech->res->code, 200, "superuser should be able to see stats page";
-
- $mech->content_contains('Innerhalb eines Arbeitstages moderiert: 3');
- $mech->content_contains('Innerhalb von f&uuml;nf Arbeitstagen abgeschlossen: 3');
- # my @data = $mech->content =~ /(?:moderiert|abgeschlossen): \d+/g;
- # diag Dumper(\@data); use Data::Dumper;
-
- my $export_count = get_export_rows_count($mech);
- if (defined $export_count) {
- is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports';
- $mech->content_contains('fixed - council');
- }
- };
+ $user = $mech->log_in_ok( 'super@example.org' );
+
+ $mech->get_ok( '/admin/stats' );
+ is $mech->res->code, 200, "superuser should be able to see stats page";
+
+ $mech->content_contains('Innerhalb eines Arbeitstages moderiert: 3');
+ $mech->content_contains('Innerhalb von f&uuml;nf Arbeitstagen abgeschlossen: 3');
+ # my @data = $mech->content =~ /(?:moderiert|abgeschlossen): \d+/g;
+ # diag Dumper(\@data); use Data::Dumper;
+
+ my $export_count = get_export_rows_count($mech);
+ if (defined $export_count) {
+ is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports';
+ $mech->content_contains('fixed - council');
+ }
};
subtest "test admin_log" => sub {
@@ -977,136 +885,108 @@ subtest "test admin_log" => sub {
};
subtest 'email images to external partners' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- reset_report_state($report);
+ reset_report_state($report);
- my $photo = path(__FILE__)->parent->child('zurich-logo_portal.x.jpg')->slurp_raw;
- my $photoset = FixMyStreet::App::Model::PhotoSet->new({
- data_items => [ $photo ],
- });
- my $fileid = $photoset->data;
-
- $report->set_extra_metadata('publish_photo' => { 0 => 1 });
- # The below email comparison must not have an external message.
- $report->unset_extra_metadata('external_message');
- $report->update({
- state => 'external',
- photo => $fileid,
- external_body => $external_body->id,
- });
+ my $photo = path(__FILE__)->parent->child('zurich-logo_portal.x.jpg')->slurp_raw;
+ my $photoset = FixMyStreet::App::Model::PhotoSet->new({
+ data_items => [ $photo ],
+ });
+ my $fileid = $photoset->data;
+
+ $report->set_extra_metadata('publish_photo' => { 0 => 1 });
+ # The below email comparison must not have an external message.
+ $report->unset_extra_metadata('external_message');
+ $report->update({
+ state => 'external',
+ photo => $fileid,
+ external_body => $external_body->id,
+ });
- $mech->clear_emails_ok;
- send_reports_for_zurich();
+ $mech->clear_emails_ok;
+ send_reports_for_zurich();
- my @emails = $mech->get_email;
- my $email_as_string = $mech->get_first_email(@emails);
- my ($boundary) = $email_as_string =~ /boundary="([A-Za-z0-9.]*)"/ms;
- my $email = Email::MIME->new($email_as_string);
-
- my $expected_email_content = path(__FILE__)->parent->child('zurich_attachments.txt')->slurp;
-
- my $REPORT_ID = $report->id;
- $expected_email_content =~ s{Subject: (.*?)\r?\n}{
- my $subj = Encode::decode('MIME-Header', $1);
- $subj =~ s{REPORT_ID}{$REPORT_ID}g;
- 'Subject: ' . Email::MIME::Encode::mime_encode($subj, "utf-8", 9) . "\n";
- }eg;
- $expected_email_content =~ s{REPORT_ID}{$REPORT_ID}g;
- $expected_email_content =~ s{BOUNDARY}{$boundary}g;
- my $expected_email = Email::MIME->new($expected_email_content);
-
- my @email_parts;
- $email->walk_parts(sub {
- my ($part) = @_;
- push @email_parts, [ { $part->header_pairs }, $part->body ];
- });
- my @expected_email_parts;
- $expected_email->walk_parts(sub {
- my ($part) = @_;
- push @expected_email_parts, [ { $part->header_pairs }, $part->body ];
- });
- is_deeply \@email_parts, \@expected_email_parts, 'MIME email text ok'
- or do {
- (my $test_name = $0) =~ s{/}{_}g;
- my $path = path("test-output-$test_name.tmp");
- $path->spew($email_as_string);
- diag "Saved output in $path";
- };
+ my @emails = $mech->get_email;
+ my $email_as_string = $mech->get_first_email(@emails);
+ my ($boundary) = $email_as_string =~ /boundary="([A-Za-z0-9.]*)"/ms;
+ my $email = Email::MIME->new($email_as_string);
+
+ my $expected_email_content = path(__FILE__)->parent->child('zurich_attachments.txt')->slurp;
+
+ my $REPORT_ID = $report->id;
+ $expected_email_content =~ s{Subject: (.*?)\r?\n}{
+ my $subj = Encode::decode('MIME-Header', $1);
+ $subj =~ s{REPORT_ID}{$REPORT_ID}g;
+ 'Subject: ' . Email::MIME::Encode::mime_encode($subj, "utf-8", 9) . "\n";
+ }eg;
+ $expected_email_content =~ s{REPORT_ID}{$REPORT_ID}g;
+ $expected_email_content =~ s{BOUNDARY}{$boundary}g;
+ my $expected_email = Email::MIME->new($expected_email_content);
+
+ my @email_parts;
+ $email->walk_parts(sub {
+ my ($part) = @_;
+ push @email_parts, [ { $part->header_pairs }, $part->body ];
+ });
+ my @expected_email_parts;
+ $expected_email->walk_parts(sub {
+ my ($part) = @_;
+ push @expected_email_parts, [ { $part->header_pairs }, $part->body ];
+ });
+ is_deeply \@email_parts, \@expected_email_parts, 'MIME email text ok'
+ or do {
+ (my $test_name = $0) =~ s{/}{_}g;
+ my $path = path("test-output-$test_name.tmp");
+ $path->spew($email_as_string);
+ diag "Saved output in $path";
};
};
subtest 'Status update shown as appropriate' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- # ALL closed states must hide the public_response edit, and public ones
- # must show the answer in blue.
- for (['feedback pending', 1, 0, 0],
- ['fixed - council', 0, 1, 0],
- ['external', 0, 1, 0],
- ['hidden', 0, 0, 1])
- {
- my ($state, $update, $public, $user_response) = @$_;
- $report->update({ state => $state });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->contains_or_lacks($update, "name='status_update'");
- $mech->contains_or_lacks($public || $user_response, '<div class="admin-official-answer">');
-
- if ($public) {
- $mech->get_ok( '/report/' . $report->id );
- $mech->content_contains('Antwort</h4>');
- }
- }
- };
+ # ALL closed states must hide the public_response edit, and public ones
+ # must show the answer in blue.
+ for (['feedback pending', 1, 0, 0],
+ ['fixed - council', 0, 1, 0],
+ ['external', 0, 1, 0],
+ ['hidden', 0, 0, 1])
+ {
+ my ($state, $update, $public, $user_response) = @$_;
+ $report->update({ state => $state });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->contains_or_lacks($update, "name='status_update'");
+ $mech->contains_or_lacks($public || $user_response, '<div class="admin-official-answer">');
+
+ if ($public) {
+ $mech->get_ok( '/report/' . $report->id );
+ $mech->content_contains('Antwort</h4>');
+ }
+ }
};
subtest 'time_spent' => sub {
- FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAP_TYPE => 'Zurich,OSM',
- }, sub {
- my $report = $reports[0];
-
- is $report->get_time_spent, 0, '0 minutes spent';
- $report->update({ state => 'in progress' });
- $mech->get_ok( '/admin/report_edit/' . $report->id );
- $mech->form_with_fields( 'time_spent' );
- $mech->submit_form_ok( {
- with_fields => {
- time_spent => 10,
- } });
- is $report->get_time_spent, 10, '10 minutes spent';
- };
+ my $report = $reports[0];
+
+ is $report->get_time_spent, 0, '0 minutes spent';
+ $report->update({ state => 'in progress' });
+ $mech->get_ok( '/admin/report_edit/' . $report->id );
+ $mech->form_with_fields( 'time_spent' );
+ $mech->submit_form_ok( {
+ with_fields => {
+ time_spent => 10,
+ } });
+ is $report->get_time_spent, 10, '10 minutes spent';
};
$mech->log_out_ok;
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
- MAPIT_URL => 'http://mapit.zurich/',
- MAPIT_TYPES => [ 'ZZZ' ],
-}, sub {
- subtest 'users at the top level can be edited' => sub {
- $mech->log_in_ok( $superuser->email );
- $mech->get_ok('/admin/users/' . $superuser->id );
- };
+subtest 'users at the top level can be edited' => sub {
+ $mech->log_in_ok( $superuser->email );
+ $mech->get_ok('/admin/users/' . $superuser->id );
};
-FixMyStreet::override_config {
- ALLOWED_COBRANDS => [ 'zurich' ],
-}, sub {
- subtest 'A visit to /reports is okay' => sub {
- $mech->get_ok('/reports');
- };
+subtest 'A visit to /reports is okay' => sub {
+ $mech->get_ok('/reports');
};
-END {
- ok $mech->host("www.fixmystreet.com"), "change host back";
- done_testing();
-}
+};
-1;
+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/bodies/open311-form-fields.html b/templates/web/base/admin/bodies/open311-form-fields.html
index bdd4ad935..be2f13af0 100644
--- a/templates/web/base/admin/bodies/open311-form-fields.html
+++ b/templates/web/base/admin/bodies/open311-form-fields.html
@@ -161,7 +161,7 @@
</p>
</div>
<p>
- <input type="checkbox" id="fetch_all_problems" name="fetch_all_problems"[% ' checked' IF object.get_extra_metadata('fetch_all_problems') %]>
+ <input type="checkbox" id="fetch_all_problems" name="extra[fetch_all_problems]"[% ' checked' IF object.get_extra_metadata('fetch_all_problems') %]>
<label for="fetch_all_problems" class="inline">[% loc('Always fetch all problems') %]</label>
</p>
</div>
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/common_header_tags.html b/templates/web/base/common_header_tags.html
index e29d96655..728b81363 100644
--- a/templates/web/base/common_header_tags.html
+++ b/templates/web/base/common_header_tags.html
@@ -23,10 +23,7 @@
[% INCLUDE 'header_rss.html' %]
-<title>
- [% "$title :: " | html IF title %]
- [% site_name -%]
-</title>
+[% INCLUDE 'header/title.html' %]
[% IF bodyclass.match('frontpage') %]
<link rel="prefetch" href="[% version('/js/validation_rules.js') %]">
diff --git a/templates/web/base/header/title.html b/templates/web/base/header/title.html
new file mode 100644
index 000000000..835c87790
--- /dev/null
+++ b/templates/web/base/header/title.html
@@ -0,0 +1,4 @@
+<title>
+ [% "$title :: " | html IF title %]
+ [% site_name -%]
+</title>
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/_list-filter-status.html b/templates/web/base/reports/_list-filter-status.html
new file mode 100644
index 000000000..6923a7929
--- /dev/null
+++ b/templates/web/base/reports/_list-filter-status.html
@@ -0,0 +1,45 @@
+[% SET show_all_states = c.cobrand.filter_show_all_states OR (c.user_exists AND (c.user.is_superuser OR c.user.belongs_to_body(body.id))) %]
+
+<select class="form-control js-multiple" name="status" id="statuses" multiple
+ data-all="[% loc('All') %]"
+ [% IF show_all_states %]
+ [% options = [];
+ FOR group IN filter_states; FOR state IN group.1;
+ NEXT IF state == 'hidden';
+ SET state = 'fixed' IF state == 'fixed - council';
+ options.push(state);
+ END; END
+ %]
+ data-all-options='["[% options.join('", "') %]"]'
+ [%~ ELSE ~%]
+ [%~ IF has_fixed_state ~%]
+ data-all-options='["open","closed","fixed"]'
+ [%~ ELSE ~%]
+ data-all-options='["open","closed"]'
+ [%~ END ~%]
+ [%~ END ~%]
+ [% INCLUDE 'reports/_status_filter_options.html' %]
+ >
+ [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') AND !shortlist %]
+ <option value="shortlisted"[% ' selected' IF filter_status.shortlisted %]>[% loc('Shortlisted') %]</option>
+ <option value="unshortlisted"[% ' selected' IF filter_status.unshortlisted %]>[% loc('Unshortlisted') %]</option>
+ [% END %]
+ [% IF c.user_exists AND ( c.user.has_body_permission_to('report_inspect') OR c.user.has_body_permission_to('report_mark_private') ) %]
+ <option value="non_public"[% ' selected' IF filter_status.non_public %]>[% loc('Private only') %]</option>
+ [% END %]
+ [% IF show_all_states %]
+ [% FOR group IN filter_states %]
+ [% FOR state IN group.1 %]
+ [% NEXT IF state == 'hidden' %]
+ [% SET state = 'fixed' IF state == 'fixed - council' ~%]
+ <option value="[% state %]"[% ' selected' IF filter_status.$state %]>[% prettify_state(state, 1) %]</option>
+ [% END %]
+ [% END %]
+ [% ELSE %]
+ <option value="open"[% ' selected' IF filter_status.open %]>[% prettify_state('confirmed') %]</option>
+ <option value="closed"[% ' selected' IF filter_status.closed %]>[% prettify_state('closed') %]</option>
+ [% IF has_fixed_state %]
+ <option value="fixed"[% ' selected' IF filter_status.fixed %]>[% prettify_state('fixed') %]</option>
+ [% END %]
+ [% END %]
+</select>
diff --git a/templates/web/base/reports/_list-filters.html b/templates/web/base/reports/_list-filters.html
index 6acb5936c..77c257e01 100644
--- a/templates/web/base/reports/_list-filters.html
+++ b/templates/web/base/reports/_list-filters.html
@@ -1,49 +1,4 @@
-[% SET show_all_states = c.cobrand.filter_show_all_states OR (c.user_exists AND (c.user.is_superuser OR c.user.belongs_to_body(body.id))) %]
-[% select_status = BLOCK %]
- <select class="form-control js-multiple" name="status" id="statuses" multiple
- data-all="[% loc('All') %]"
- [% IF show_all_states %]
- [% options = [];
- FOR group IN filter_states; FOR state IN group.1;
- NEXT IF state == 'hidden';
- SET state = 'fixed' IF state == 'fixed - council';
- options.push(state);
- END; END
- %]
- data-all-options='["[% options.join('", "') %]"]'
- [%~ ELSE ~%]
- [%~ IF has_fixed_state ~%]
- data-all-options='["open","closed","fixed"]'
- [%~ ELSE ~%]
- data-all-options='["open","closed"]'
- [%~ END ~%]
- [%~ END ~%]
- [% INCLUDE 'reports/_status_filter_options.html' %]
- >
- [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') AND !shortlist %]
- <option value="shortlisted"[% ' selected' IF filter_status.shortlisted %]>[% loc('Shortlisted') %]</option>
- <option value="unshortlisted"[% ' selected' IF filter_status.unshortlisted %]>[% loc('Unshortlisted') %]</option>
- [% END %]
- [% IF c.user_exists AND ( c.user.has_body_permission_to('report_inspect') OR c.user.has_body_permission_to('report_mark_private') ) %]
- <option value="non_public"[% ' selected' IF filter_status.non_public %]>[% loc('Private only') %]</option>
- [% END %]
- [% IF show_all_states %]
- [% FOR group IN filter_states %]
- [% FOR state IN group.1 %]
- [% NEXT IF state == 'hidden' %]
- [% SET state = 'fixed' IF state == 'fixed - council' ~%]
- <option value="[% state %]"[% ' selected' IF filter_status.$state %]>[% prettify_state(state, 1) %]</option>
- [% END %]
- [% END %]
- [% ELSE %]
- <option value="open"[% ' selected' IF filter_status.open %]>[% prettify_state('confirmed') %]</option>
- <option value="closed"[% ' selected' IF filter_status.closed %]>[% prettify_state('closed') %]</option>
- [% IF has_fixed_state %]
- <option value="fixed"[% ' selected' IF filter_status.fixed %]>[% prettify_state('fixed') %]</option>
- [% END %]
- [% END %]
- </select>
-[% END %]
+[% select_status = PROCESS 'reports/_list-filter-status.html' %]
[% select_category = BLOCK %]
[% IF filter_categories.size %]
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/templates/web/westminster/footer_extra_js.html b/templates/web/westminster/footer_extra_js.html
index ec25926c5..f89cee3d4 100644
--- a/templates/web/westminster/footer_extra_js.html
+++ b/templates/web/westminster/footer_extra_js.html
@@ -3,6 +3,8 @@ 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/westminster/roadworks.js'),
version('/cobrands/westminster/assets.js'),
);
END
diff --git a/templates/web/zurich/admin/bodies/contact-form.html b/templates/web/zurich/admin/bodies/contact-form.html
index 7b59124fb..8449f2d39 100644
--- a/templates/web/zurich/admin/bodies/contact-form.html
+++ b/templates/web/zurich/admin/bodies/contact-form.html
@@ -15,6 +15,11 @@
<input type="text" class="form-control" name="extra[abbreviation]" id="abbreviation" size="30" value="[% contact.get_extra_metadata('abbreviation') | html %]">
</p>
+ <p>
+ <label for="admin_label">Admin-label</label>
+ <input type="text" class="form-control" name="extra[admin_label]" id="admin_label" size="30" value="[% contact.get_extra_metadata('admin_label') | html %]">
+ </p>
+
<p><strong>[% loc('Email:') %] </strong>
<input type="text" class="form-control" name="email" value="[% contact.email | html %]" size="30">
@@ -29,15 +34,12 @@
</div>
<p>
- [% IF contact.in_storage %]
<label for="state">[% loc('State') %]</label>
<select name="state" id="state">
<option value="confirmed"[% ' selected' IF contact.state == 'confirmed' %]>[% loc('Confirmed') %]
+ <option value="inactive"[% ' selected' IF contact.state == 'inactive' %]>[% loc('Inactive') %]
<option value="deleted"[% ' selected' IF contact.state == 'deleted' %]>[% loc('Deleted') %]
</select>
- [% ELSE %]
- <input type="hidden" name="state" value="confirmed" id="confirmed">
- [% END %]
<input type="checkbox" name="photo_required" value="1" id="photo_required"[% ' checked' IF contact.get_extra_metadata('photo_required') %]>
<label class="inline" for="photo_required">[% loc('Photo required') %]</label>
</p>
diff --git a/templates/web/zurich/admin/bodies/form.html b/templates/web/zurich/admin/bodies/form.html
index b625efc44..f9cd4f812 100644
--- a/templates/web/zurich/admin/bodies/form.html
+++ b/templates/web/zurich/admin/bodies/form.html
@@ -20,6 +20,18 @@
</select>
</p>
+ [% IF body AND NOT body.parent AND NOT body.bodies %]
+ <p>
+ <label for="category">[% loc('Category') %]</label>
+ <select class="form-control" name="extra[category]" id="category">
+ <option value="">[% loc('-- Pick a category --') %]</option>
+ [% FOR cat IN c.cobrand.category_options %]
+ <option value="[% cat.category %]"[% ' selected' IF cat.category == body.get_extra_metadata('category') %]>[% cat.category_display | html %]</option>
+ [% END %]
+ </select>
+ </p>
+ [% END %]
+
<p>
<label for="area_ids">[% loc('Area covered') %]</label>
<select class="form-control js-multiple" name="area_ids" id="area_ids" multiple data-none="-- [% loc('Select an area') %] --">
diff --git a/templates/web/zurich/admin/index-dm.html b/templates/web/zurich/admin/index-dm.html
index c93adbfb3..92df5b415 100644
--- a/templates/web/zurich/admin/index-dm.html
+++ b/templates/web/zurich/admin/index-dm.html
@@ -1,7 +1,9 @@
[% PROCESS 'admin/header.html' title=loc('Summary') -%]
[% PROCESS 'admin/report_blocks.html' %]
-[% INCLUDE status_message %]
+<div class="index-status">
+[% status_message %]
+</div>
<h2 id="submitted">[% loc('Submitted') %]</h2>
[% INCLUDE list, problems = submitted.all, hash = 'submitted' %]
diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html
index b9fb6ff4d..d8e6c2625 100644
--- a/templates/web/zurich/admin/report_edit-sdm.html
+++ b/templates/web/zurich/admin/report_edit-sdm.html
@@ -39,23 +39,11 @@
<dd class="screen-no-space-after">
<strong>[% PROCESS format_date this_date=problem.created %] [% problem.created.hms %]</strong>
</dd>
- <dt class="print-only">[% loc('Coordinates:') %] <!-- Koordinaten --></dt>
- <dd class="screen-no-space-after print-no-space-after">
- [% problem.local_coords.join(',') %]
- <input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% problem.latitude %]">
- <input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% problem.longitude %]">
- </dd>
- <dd class="screen-no-space-after print-no-space-after">
- [% IF problem.used_map %]
- [% loc('Used map') %]
- [% ELSE %]
- [% loc("Didn't use map") %]
- [% END %]
- </dd>
- <dd>[%
- safe = problem.postcode | html;
- tprintf( loc('originally entered: &ldquo;%s&rdquo;'), safe )
- %]</dd>
+
+ <dd>[% c.cobrand.admin_district_lookup(problem) %]</dd>
+
+ <input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% problem.latitude %]">
+ <input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% problem.longitude %]">
<dt class="print-only">[% loc('Reported by:') %] <!-- Meldende Person --></dt>
<dd>
@@ -78,10 +66,6 @@
<dt>[% loc('Time spent (in minutes):') %]</dt>
<dd>[% problem.get_time_spent %]</dd>
- <dd>
- [% INCLUDE status_message %]
- </dd>
-
[% IF problem.photo %]
<dd>
[% FOR photo IN problem.photos %]
@@ -102,6 +86,9 @@
<div class="admin-report-edit admin-report-edit--interact">
<p align="right" class="screen-only"><input [% sdm_disabled %] type="submit" class="btn" name="send_back" value="[% loc('Not for my subdivision') %]"></p>
+
+[% status_message %]
+
<p align="right" class="screen-only"><input [% sdm_disabled %] type="submit" class="btn" name="not_contactable" value="[% loc('Customer not contactable') %]"></p>
<ul class="no-bullets screen-only">
diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html
index 0186a6286..6f69161fe 100644
--- a/templates/web/zurich/admin/report_edit.html
+++ b/templates/web/zurich/admin/report_edit.html
@@ -58,23 +58,11 @@
<dd class="screen-no-space-after">
<strong>[% PROCESS format_date this_date=problem.created %] [% problem.created.hms %]</strong>
</dd>
- <dt class="print-only">[% loc('Coordinates:') %] <!-- Koordinaten --></dt>
- <dd class="screen-no-space-after print-no-space-after">
- [% problem.local_coords.join(',') %]
- <input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% problem.latitude %]">
- <input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% problem.longitude %]">
- </dd>
- <dd class="screen-no-space-after print-no-space-after">
- [% IF problem.used_map %]
- [% loc('Used map') %]
- [% ELSE %]
- [% loc("Didn't use map") %]
- [% END %]
- </dd>
- <dd>[%
- safe = problem.postcode | html;
- tprintf( loc('originally entered: &ldquo;%s&rdquo;'), safe )
- %]</dd>
+
+ <dd>[% c.cobrand.admin_district_lookup(problem) %]</dd>
+
+ <input type="hidden" name="latitude" id="fixmystreet.latitude" value="[% problem.latitude %]">
+ <input type="hidden" name="longitude" id="fixmystreet.longitude" value="[% problem.longitude %]">
[% SET fields = problem.get_extra_fields; IF fields.size %]
<dd>
@@ -129,7 +117,7 @@
<div class="admin-report-edit admin-report-edit--interact">
-[% INCLUDE status_message %]
+[% status_message %]
<dl [% IF status_message %]class="with-message"[% END %]>
@@ -280,6 +268,7 @@
[% ELSE %]
[% loc('Message to competent body:') %]
[% END %]
+ [% problem.body(c).endpoint %]
</h2>
<div class="admin-external-message">
[% problem.extra.external_message | html_para %]
diff --git a/templates/web/zurich/header.html b/templates/web/zurich/header.html
index b453465f7..cd08e9503 100644
--- a/templates/web/zurich/header.html
+++ b/templates/web/zurich/header.html
@@ -9,6 +9,7 @@
<meta name="HandHeldFriendly" content="true">
<meta name="mobileoptimized" content="0">
+ [% INCLUDE 'header_opengraph.html' %]
[% INCLUDE 'header/css.html' %]
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/themes/redmond/jquery-ui.css">
diff --git a/templates/web/zurich/header/title.html b/templates/web/zurich/header/title.html
new file mode 100644
index 000000000..118817e48
--- /dev/null
+++ b/templates/web/zurich/header/title.html
@@ -0,0 +1,4 @@
+<title>
+ [% "$title :: " | html IF title %]
+ Züri wie neu – Infrastrukturschäden melden – Stadt Zürich
+</title>
diff --git a/templates/web/zurich/header_opengraph.html b/templates/web/zurich/header_opengraph.html
new file mode 100644
index 000000000..0a7dc42d7
--- /dev/null
+++ b/templates/web/zurich/header_opengraph.html
@@ -0,0 +1,8 @@
+ <meta property="og:url" content="[% c.cobrand.base_url %][% c.req.uri.path %]">
+ <meta property="og:title" content="[% title || site_name | html %]">
+ <meta property="og:site_name" content="[% site_name %]">
+ [% IF c.req.uri.path == '/' %]
+ <meta name="description" property="og:description" content="Melden Sie Schäden an der Infrastruktur der Stadt Zürich wie Schlaglöcher, defekte Beleuchtung/Signalisation, Graffitis, Schädlinge oder Abfall auf öffentlichem Grund.">
+ [% END %]
+ <meta property="og:type" content="website">
+ [% INCLUDE 'header_opengraph_image.html' %]
diff --git a/templates/web/zurich/reports/_list-filter-status.html b/templates/web/zurich/reports/_list-filter-status.html
new file mode 100644
index 000000000..bf56821f6
--- /dev/null
+++ b/templates/web/zurich/reports/_list-filter-status.html
@@ -0,0 +1,7 @@
+<select class="form-control js-multiple" name="status" id="statuses" multiple
+ data-all="[% loc('All') %]" data-all-options='["open","closed"]'
+ [% INCLUDE 'reports/_status_filter_options.html' %]
+>
+ <option value="open"[% ' selected' IF filter_status.open %]>[% prettify_state('confirmed') %]</option>
+ <option value="closed"[% ' selected' IF filter_status.closed %]>[% prettify_state('closed') %]</option>
+</select>
diff --git a/web/cobrands/fixmystreet-uk-councils/roadworks.js b/web/cobrands/fixmystreet-uk-councils/roadworks.js
index f4da4c310..2b0de306a 100644
--- a/web/cobrands/fixmystreet-uk-councils/roadworks.js
+++ b/web/cobrands/fixmystreet-uk-councils/roadworks.js
@@ -222,16 +222,4 @@ fixmystreet.roadworks.display_message = function(feature) {
$msg.prependTo('#js-post-category-messages');
};
-/* Stop sending a needless header so that no preflight CORS request */
-OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
- if (sName.toLowerCase() == 'x-requested-with') {
- return;
- }
- if (!this._headers) {
- this._headers = {};
- }
- this._headers[sName] = sValue;
- return this._object.setRequestHeader(sName, sValue);
-};
-
})();
diff --git a/web/cobrands/fixmystreet/assets.js b/web/cobrands/fixmystreet/assets.js
index c30fa2b5e..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);
@@ -944,16 +947,6 @@ OpenLayers.Format.GML.v3.MultiCurveFix = OpenLayers.Class(OpenLayers.Format.GML.
CLASS_NAME: "OpenLayers.Format.GML.v3.MultiCurveFix"
});
-OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
- if (sName.toLowerCase() == 'x-requested-with') {
- return;
- }
- if (!this._headers) {
- this._headers = {};
- }
- this._headers[sName] = sValue;
- return this._object.setRequestHeader(sName, sValue);
-};
})();
/* Handling of body override functionality */
@@ -1031,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) {
@@ -1129,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') {
@@ -1160,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);
}
@@ -1235,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 8d6b2091b..c7749c729 100644
--- a/web/cobrands/fixmystreet/fixmystreet.js
+++ b/web/cobrands/fixmystreet/fixmystreet.js
@@ -1522,7 +1522,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()
);
@@ -1538,8 +1543,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/cobrands/westminster/roadworks.js b/web/cobrands/westminster/roadworks.js
new file mode 100644
index 000000000..d7a30b63d
--- /dev/null
+++ b/web/cobrands/westminster/roadworks.js
@@ -0,0 +1,32 @@
+(function(){
+
+if (!fixmystreet.maps) {
+ return;
+}
+
+var org_id = '1160';
+var body = "Westminster City 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
+});
+
+// Westminster want to also display the responsible party in roadworks messages
+var original_display_message = fixmystreet.roadworks.display_message;
+fixmystreet.roadworks.display_message = function(feature) {
+ var retval = original_display_message.apply(this, arguments);
+
+ if (feature.attributes.promoter) {
+ var $dl = $(".js-roadworks-message-" + feature.layer.id + " dl");
+ $dl.append("<dt>Responsibility</dt>");
+ $dl.append($("<dd></dd>").text(feature.attributes.promoter));
+ }
+
+ return retval;
+};
+
+})();
diff --git a/web/cobrands/zurich/layout.scss b/web/cobrands/zurich/layout.scss
index 97ae8fc4a..d98afba5d 100644
--- a/web/cobrands/zurich/layout.scss
+++ b/web/cobrands/zurich/layout.scss
@@ -315,6 +315,9 @@ body.mappage.admin {
font-weight: bold;
position: absolute;
}
+ .index-status .message-updated {
+ margin-top: -1.5em;
+ }
}
.admin-nav-wrapper {
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index cd2283491..1588bda2e 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -562,6 +562,9 @@ $.extend(fixmystreet.utils, {
} else {
$.extend(style.defaultStyle, { fillColor: 'black', strokeColor: 'black' });
}
+ if (!this.features.length) {
+ return;
+ }
var geometry = this.features[0].geometry;
if (geometry.CLASS_NAME == 'OpenLayers.Geometry.Collection' ||
geometry.CLASS_NAME == 'OpenLayers.Geometry.MultiPolygon') {
@@ -673,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') {
@@ -1185,3 +1188,15 @@ OpenLayers.Renderer.SVGBig = OpenLayers.Class(OpenLayers.Renderer.SVG, {
CLASS_NAME: "OpenLayers.Renderer.SVGBig"
});
+
+/* Stop sending a needless header so that no preflight CORS request */
+OpenLayers.Request.XMLHttpRequest.prototype.setRequestHeader = function(sName, sValue) {
+ if (sName.toLowerCase() == 'x-requested-with') {
+ return;
+ }
+ if (!this._headers) {
+ this._headers = {};
+ }
+ this._headers[sName] = sValue;
+ return this._object.setRequestHeader(sName, sValue);
+};
diff --git a/web/js/map-wmts-base.js b/web/js/map-wmts-base.js
index fe8d8015e..43f829ab5 100644
--- a/web/js/map-wmts-base.js
+++ b/web/js/map-wmts-base.js
@@ -28,27 +28,4 @@ fixmystreet.maps.setup_wmts_base_map = function() {
tileOrigin: new OpenLayers.LonLat(fixmystreet.wmts_config.origin_x, fixmystreet.wmts_config.origin_y)
});
});
-
- // Give main code a new bbox_strategy that translates between
- // lat/lon and our WMTS layer's coordinates
- fixmystreet.bbox_strategy = new OpenLayers.Strategy.ReprojectBBOX({
- ratio: 1
- });
};
-
-OpenLayers.Strategy.ReprojectBBOX = OpenLayers.Class(OpenLayers.Strategy.BBOX, {
- getMapBounds: function() {
- // Get the map bounds but return them in lat/lon, not
- // local coordinates
- if (this.layer.map === null) {
- return null;
- }
-
- var localBounds = this.layer.map.getExtent();
- // Transform bound corners into WGS84
- localBounds.transform( new OpenLayers.Projection(fixmystreet.wmts_config.map_projection), new OpenLayers.Projection("EPSG:4326") );
- return localBounds;
- },
-
- CLASS_NAME: "OpenLayers.Strategy.ReprojectBBOX"
-});
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';
+ }
+};