aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin/Triage.pm1
-rw-r--r--perllib/FixMyStreet/App/Controller/Dashboard.pm120
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm123
-rw-r--r--perllib/FixMyStreet/Cobrand/Bromley.pm87
-rw-r--r--perllib/FixMyStreet/Cobrand/FixMyStreet.pm6
-rw-r--r--perllib/FixMyStreet/Cobrand/IsleOfWight.pm6
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm1
-rw-r--r--t/cobrand/bromley.t5
-rw-r--r--templates/web/base/admin/stats/index.html9
-rw-r--r--templates/web/base/dashboard/heatmap-list.html (renamed from templates/web/bromley/about/heatmap-list.html)2
-rwxr-xr-xtemplates/web/base/dashboard/heatmap.html (renamed from templates/web/bromley/about/heatmap.html)15
-rw-r--r--templates/web/base/reports/_list-filter-status.html2
-rw-r--r--templates/web/bromley/footer_extra_js.html1
-rw-r--r--web/cobrands/fixmystreet/density-map.js (renamed from web/cobrands/bromley/js.js)16
-rw-r--r--web/js/map-OpenLayers.js17
-rw-r--r--web/vendor/HeatmapLayer.js (renamed from web/cobrands/bromley/HeatmapLayer.js)0
17 files changed, 244 insertions, 172 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4429bb95e..e718a42a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,6 +13,8 @@
- Pass ‘filter_category’ param to front page to pre-filter map.
- Remove on-map Permalink.
- Darken front page step numbers, and improve nested heading structure.
+ - Set report title autocomplete to off to prevent email autocompleting
+ - Add map filter debouncing to reduce server requests. #2675
- Admin improvements:
- Add new roles system, to group permissions and apply to users. #2483
- Contact form emails now include user admin links.
@@ -21,6 +23,7 @@
- New features:
- Categories can be listed under more than one group #2475
- OpenID Connect login support. #2523
+ - Heatmap dashboard. #2675
- Bugfixes:
- Prevent creation of two templates with same title. #2471
- Fix bug going between report/new pages client side. #2484
@@ -38,8 +41,6 @@
- Allow contact send method to be unset always.
- Fix z-index stacking bug that was causing unclickable RSS icons on /alert page. #2624
- Fix issue with inspector duplication workflow.
- - Front end improvements:
- - Set report title autocomplete to off to prevent email autocompleting
- Development improvements:
- Upgrade the underlying framework and a number of other packages. #2473
- Add feature cobrand helper function.
diff --git a/perllib/FixMyStreet/App/Controller/Admin/Triage.pm b/perllib/FixMyStreet/App/Controller/Admin/Triage.pm
index 385248cd1..50d1b1437 100644
--- a/perllib/FixMyStreet/App/Controller/Admin/Triage.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin/Triage.pm
@@ -45,6 +45,7 @@ sub index : Path : Args(0) {
}
$c->stash->{body} = $c->forward('/reports/body_find', [ $c->cobrand->council_area ]);
$c->forward( 'stash_report_filter_status' );
+ $c->forward('/reports/stash_report_sort', [ $c->cobrand->reports_ordering ]);
$c->forward( '/reports/load_and_group_problems' );
$c->stash->{page} = 'reports'; # So the map knows to make clickable pins
diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm
index 495e47c2a..f226e08de 100644
--- a/perllib/FixMyStreet/App/Controller/Dashboard.pm
+++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm
@@ -70,15 +70,20 @@ sub check_page_allowed : Private {
$c->detach( '/auth/redirect' ) unless $c->user_exists;
- $c->detach( '/page_error_404_not_found' )
- unless $c->user->from_body || $c->user->is_superuser;
+ my $cobrand_body = $c->cobrand->can('council_area_id') ? $c->cobrand->body : undef;
- my $body = $c->user->from_body;
- if (!$body && $c->get_param('body')) {
- # Must be a superuser, so allow query parameter if given
- $body = $c->model('DB::Body')->find({ id => $c->get_param('body') });
+ my $body;
+ if ($c->user->is_superuser) {
+ if ($c->get_param('body')) {
+ $body = $c->model('DB::Body')->find({ id => $c->get_param('body') });
+ } else {
+ $body = $cobrand_body;
+ }
+ } elsif ($c->user->from_body && (!$cobrand_body || $cobrand_body->id == $c->user->from_body->id)) {
+ $body = $c->user->from_body;
+ } else {
+ $c->detach( '/page_error_404_not_found' )
}
-
return $body;
}
@@ -494,6 +499,107 @@ sub generate_csv : Private {
}
}
+sub heatmap : Local : Args(0) {
+ my ($self, $c) = @_;
+
+ my $body = $c->stash->{body} = $c->forward('check_page_allowed');
+ $c->detach( '/page_error_404_not_found' )
+ unless $body && $c->cobrand->feature('heatmap');
+
+ $c->stash->{page} = 'reports'; # So the map knows to make clickable pins
+
+ my @wards = $c->get_param_list('wards', 1);
+ $c->forward('/reports/ward_check', [ @wards ]) if @wards;
+ $c->forward('/reports/stash_report_filter_status');
+ $c->forward('/reports/stash_report_sort', [ $c->cobrand->reports_ordering ]); # Not actually used
+ my $parameters = $c->forward( '/reports/load_problems_parameters');
+
+ my $where = $parameters->{where};
+ my $filter = $parameters->{filter};
+ delete $filter->{rows};
+
+ $c->forward('heatmap_filters', [ $where ]);
+
+ # Load the relevant stuff for the sidebar as well
+ my $problems = $c->cobrand->problems;
+ $problems = $problems->to_body($body);
+ $problems = $problems->search($where, $filter);
+
+ $c->forward('heatmap_sidebar', [ $problems, $where ]);
+
+ if ($c->get_param('ajax')) {
+ my @pins;
+ while ( my $problem = $problems->next ) {
+ push @pins, $problem->pin_data($c, 'reports');
+ }
+ $c->stash->{pins} = \@pins;
+ $c->detach('/reports/ajax', [ 'dashboard/heatmap-list.html' ]);
+ }
+
+ my $children = $c->stash->{body}->first_area_children;
+ $c->stash->{children} = $children;
+ $c->stash->{ward_hash} = { map { $_->{id} => 1 } @{$c->stash->{wards}} } if $c->stash->{wards};
+
+ $c->forward('/reports/setup_categories_and_map');
+}
+
+sub heatmap_filters :Private {
+ my ($self, $c, $where) = @_;
+
+ # Wards
+ my @areas = @{$c->user->area_ids || []};
+ # Want to get everything if nothing given in an ajax call
+ if (!$c->stash->{wards} && @areas) {
+ $c->stash->{wards} = [ map { { id => $_ } } @areas ];
+ $where->{areas} = [
+ map { { 'like', '%,' . $_ . ',%' } } @areas
+ ];
+ }
+
+ # Date range
+ my $start_default = DateTime->today(time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone)->subtract(months => 1);
+ $c->stash->{start_date} = $c->get_param('start_date') || $start_default->strftime('%Y-%m-%d');
+ $c->stash->{end_date} = $c->get_param('end_date');
+
+ my $range = FixMyStreet::DateRange->new(
+ start_date => $c->stash->{start_date},
+ start_default => $start_default,
+ end_date => $c->stash->{end_date},
+ formatter => $c->model('DB')->storage->datetime_parser,
+ );
+ $where->{'me.confirmed'} = $range->sql;
+}
+
+sub heatmap_sidebar :Private {
+ my ($self, $c, $problems, $where) = @_;
+
+ $c->stash->{five_newest} = [ $problems->search(undef, {
+ rows => 5,
+ order_by => { -desc => 'confirmed' },
+ })->all ];
+
+ $c->stash->{ten_oldest} = [ $problems->search({
+ 'me.state' => [ FixMyStreet::DB::Result::Problem->open_states() ],
+ }, {
+ rows => 10,
+ order_by => 'lastupdate',
+ })->all ];
+
+ my $params = { map { my $n = $_; s/me\./problem\./; $_ => $where->{$n} } keys %$where };
+ my $body = $c->stash->{body};
+ my @c = $c->model('DB::Comment')->to_body($body)->search({
+ %$params,
+ 'me.user_id' => { -not_in => [ $c->user->id, $body->comment_user_id || () ] },
+ 'me.state' => 'confirmed',
+ }, {
+ columns => 'problem_id',
+ group_by => 'problem_id',
+ order_by => { -desc => \'max(me.confirmed)' },
+ rows => 5,
+ })->all;
+ $c->stash->{five_commented} = [ map { $_->problem } @c ];
+}
+
=head1 AUTHOR
Matthew Somerville
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index 741cbb60f..85e647f65 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -151,6 +151,7 @@ sub ward : Path : Args(2) {
if @wards;
$c->forward( 'check_canonical_url', [ $body ] );
$c->forward( 'stash_report_filter_status' );
+ $c->forward('stash_report_sort', [ $c->cobrand->reports_ordering ]);
$c->forward( 'load_and_group_problems' );
if ($c->get_param('ajax')) {
@@ -164,6 +165,25 @@ sub ward : Path : Args(2) {
$c->stash->{stats} = $c->cobrand->get_report_stats();
+ $c->forward('setup_categories_and_map');
+
+ # List of wards
+ if ( !$c->stash->{wards} && $c->stash->{body}->id && $c->stash->{body}->body_areas->first ) {
+ my $children = $c->stash->{body}->first_area_children;
+ unless ($children->{error}) {
+ foreach (values %$children) {
+ $_->{url} = $c->uri_for( $c->stash->{body_url}
+ . '/' . $c->cobrand->short_name( $_ )
+ );
+ }
+ $c->stash->{children} = $children;
+ }
+ }
+}
+
+sub setup_categories_and_map :Private {
+ my ($self, $c) = @_;
+
my @categories = $c->stash->{body}->contacts->not_deleted->search( undef, {
columns => [ 'id', 'category', 'extra', 'body_id', 'send_method' ],
distinct => 1,
@@ -188,19 +208,6 @@ sub ward : Path : Args(2) {
);
$c->cobrand->tweak_all_reports_map( $c );
-
- # List of wards
- if ( !$c->stash->{wards} && $c->stash->{body}->id && $c->stash->{body}->body_areas->first ) {
- my $children = $c->stash->{body}->first_area_children;
- unless ($children->{error}) {
- foreach (values %$children) {
- $_->{url} = $c->uri_for( $c->stash->{body_url}
- . '/' . $c->cobrand->short_name( $_ )
- );
- }
- $c->stash->{children} = $children;
- }
- }
}
sub rss_area : Path('/rss/area') : Args(1) {
@@ -551,9 +558,51 @@ sub load_dashboard_data : Private {
sub load_and_group_problems : Private {
my ( $self, $c ) = @_;
- $c->forward('stash_report_sort', [ $c->cobrand->reports_ordering ]);
+ my $parameters = $c->forward('load_problems_parameters');
+ my $body = $c->stash->{body}; # Might be undef
my $page = $c->get_param('p') || 1;
+
+ my $problems = $c->cobrand->problems;
+ my $where = $parameters->{where};
+ my $filter = $parameters->{filter};
+
+ if ($where->{areas} || $body) {
+ $problems = $problems->to_body($body);
+ }
+
+ $problems = $problems->search(
+ $where,
+ $filter
+ )->include_comment_counts->page( $page );
+
+ $c->stash->{pager} = $problems->pager;
+
+ my ( %problems, @pins );
+ while ( my $problem = $problems->next ) {
+ if ( !$body ) {
+ add_row( $c, $problem, 0, \%problems, \@pins );
+ next;
+ }
+ # Add to bodies it was sent to
+ my $bodies = $problem->bodies_str_ids;
+ foreach ( @$bodies ) {
+ next if $_ != $body->id;
+ add_row( $c, $problem, $_, \%problems, \@pins );
+ }
+ }
+
+ $c->stash(
+ problems => \%problems,
+ pins => \@pins,
+ );
+
+ return 1;
+}
+
+sub load_problems_parameters : Private {
+ my ($self, $c) = @_;
+
my $category = [ $c->get_param_list('filter_category', 1) ];
my $states = $c->stash->{filter_problem_states};
@@ -600,15 +649,10 @@ sub load_and_group_problems : Private {
$where->{category} = $category;
}
- my $problems = $c->cobrand->problems;
-
if ($c->stash->{wards}) {
$where->{areas} = [
map { { 'like', '%,' . $_->{id} . ',%' } } @{$c->stash->{wards}}
];
- $problems = $problems->to_body($body);
- } elsif ($body) {
- $problems = $problems->to_body($body);
}
if (my $bbox = $c->get_param('bbox')) {
@@ -617,45 +661,14 @@ sub load_and_group_problems : Private {
$where->{longitude} = { '>=', $min_lon, '<', $max_lon };
}
- my $cobrand_problems = $c->cobrand->call_hook('munge_load_and_group_problems', $where, $filter);
-
- # JS will request the same (or more) data client side
- return if $c->get_param('js');
-
- if ($cobrand_problems) {
- $problems = $cobrand_problems;
- } else {
- $problems = $problems->search(
- $where,
- $filter
- )->include_comment_counts->page( $page );
-
- $c->stash->{pager} = $problems->pager;
- }
-
- my ( %problems, @pins );
- while ( my $problem = $problems->next ) {
- if ( !$body ) {
- add_row( $c, $problem, 0, \%problems, \@pins );
- next;
- }
- # Add to bodies it was sent to
- my $bodies = $problem->bodies_str_ids;
- foreach ( @$bodies ) {
- next if $_ != $body->id;
- add_row( $c, $problem, $_, \%problems, \@pins );
- }
- }
-
- $c->stash(
- problems => \%problems,
- pins => \@pins,
- );
+ $c->cobrand->call_hook('munge_load_and_group_problems', $where, $filter);
- return 1;
+ return {
+ where => $where,
+ filter => $filter,
+ };
}
-
sub check_non_public_reports_permission : Private {
my ($self, $c, $where) = @_;
diff --git a/perllib/FixMyStreet/Cobrand/Bromley.pm b/perllib/FixMyStreet/Cobrand/Bromley.pm
index 391106346..29ff4393f 100644
--- a/perllib/FixMyStreet/Cobrand/Bromley.pm
+++ b/perllib/FixMyStreet/Cobrand/Bromley.pm
@@ -127,16 +127,9 @@ sub tweak_all_reports_map {
}
# A place where this can happen
- return unless $c->stash->{template} && $c->stash->{template} eq 'about/heatmap.html';
-
- my $children = $c->stash->{body}->first_area_children;
- foreach (values %$children) {
- $_->{url} = $c->uri_for( $c->stash->{body_url}
- . '/' . $c->cobrand->short_name( $_ )
- );
- }
- $c->stash->{children} = $children;
+ return unless $c->action eq 'dashboard/heatmap';
+ # Bromley only subcategory stuff
my %subcats = $self->subcategories;
my $filter = $c->stash->{filter_categories};
my @new_contacts;
@@ -156,8 +149,6 @@ sub tweak_all_reports_map {
my $subcats = $c->user->get_extra_metadata('subcategories') || [];
$c->stash->{filter_category} = { map { $_ => 1 } @$cats, @$subcats } if @$cats || @$subcats;
}
-
- $c->stash->{ward_hash} = { map { $_->{id} => 1 } @{$c->stash->{wards}} } if $c->stash->{wards};
}
sub title_list {
@@ -331,27 +322,14 @@ sub add_admin_subcategories {
return \@new_contacts;
}
-sub about_hook {
- my $self = shift;
- my $c = $self->{c};
-
- # Display a special custom dashboard page, with heatmap
- if ($c->stash->{template} eq 'about/heatmap.html') {
- $c->forward('/dashboard/check_page_allowed');
- # We want a special sidebar
- $c->stash->{ajax_template} = "about/heatmap-list.html";
- $c->set_param('js', 1) unless $c->get_param('ajax'); # Want to load pins client-side
- $c->forward('/reports/body', [ 'Bromley' ]);
- }
-}
-
-# On heatmap page, include querying on subcategories, wards, dates, provided
+# On heatmap page, include querying on subcategories
sub munge_load_and_group_problems {
my ($self, $where, $filter) = @_;
my $c = $self->{c};
- return unless $c->stash->{template} && $c->stash->{template} eq 'about/heatmap.html';
+ return unless $c->action eq 'dashboard/heatmap';
+ # Bromley subcategory stuff
if (!$where->{category}) {
my $cats = $c->user->categories;
my $subcats = $c->user->get_extra_metadata('subcategories') || [];
@@ -370,61 +348,6 @@ sub munge_load_and_group_problems {
};
delete $where->{category};
}
-
- # Wards
- my @areas = @{$c->user->area_ids || []};
- # Want to get everything if nothing given in an ajax call
- if (!$c->stash->{wards} && @areas) {
- $c->stash->{wards} = [ map { { id => $_ } } @areas ];
- $where->{areas} = [
- map { { 'like', '%,' . $_ . ',%' } } @areas
- ];
- }
-
- # Date range
- my $start_default = DateTime->today(time_zone => FixMyStreet->time_zone || FixMyStreet->local_time_zone)->subtract(months => 1);
- $c->stash->{start_date} = $c->get_param('start_date') || $start_default->strftime('%Y-%m-%d');
- $c->stash->{end_date} = $c->get_param('end_date');
-
- my $range = FixMyStreet::DateRange->new(
- start_date => $c->stash->{start_date},
- start_default => $start_default,
- end_date => $c->stash->{end_date},
- formatter => $c->model('DB')->storage->datetime_parser,
- );
- $where->{'me.confirmed'} = $range->sql;
-
- delete $filter->{rows};
-
- # Load the relevant stuff for the sidebar as well
- my $problems = $self->problems->search($where, $filter);
-
- $c->stash->{five_newest} = [ $problems->search(undef, {
- rows => 5,
- order_by => { -desc => 'confirmed' },
- })->all ];
-
- $c->stash->{ten_oldest} = [ $problems->search({
- 'me.state' => [ FixMyStreet::DB::Result::Problem->open_states() ],
- }, {
- rows => 10,
- order_by => 'lastupdate',
- })->all ];
-
- my $params = { map { my $n = $_; s/me\./problem\./; $_ => $where->{$n} } keys %$where };
- my @c = $c->model('DB::Comment')->to_body($self->body)->search({
- %$params,
- 'me.user_id' => { -not_in => [ $c->user->id, $self->body->comment_user_id || () ] },
- 'me.state' => 'confirmed',
- }, {
- columns => 'problem_id',
- group_by => 'problem_id',
- order_by => { -desc => \'max(me.confirmed)' },
- rows => 5,
- })->all;
- $c->stash->{five_commented} = [ map { $_->problem } @c ];
-
- return $problems;
}
1;
diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
index 72ba51dd8..e830b10b2 100644
--- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
+++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
@@ -99,11 +99,7 @@ sub munge_load_and_group_problems {
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;
+ $where->{category} = $self->expand_triage_cat_list($where->{category});
}
sub expand_triage_cat_list {
diff --git a/perllib/FixMyStreet/Cobrand/IsleOfWight.pm b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm
index 6a719604d..26e3ba474 100644
--- a/perllib/FixMyStreet/Cobrand/IsleOfWight.pm
+++ b/perllib/FixMyStreet/Cobrand/IsleOfWight.pm
@@ -173,11 +173,7 @@ sub munge_load_and_group_problems {
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;
+ $where->{category} = $self->expand_triage_cat_list($where->{category});
}
sub munge_around_filter_category_list {
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index 9cf1030f0..6cbaa285b 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -324,6 +324,7 @@ sub report_page_data {
$c->stash->{page} = 'reports';
$c->forward( 'stash_report_filter_status' );
+ $c->forward('stash_report_sort', [ $c->cobrand->reports_ordering ]);
$c->forward( 'load_and_group_problems' );
$c->stash->{body} = { id => 0 }; # So template can fetch the list
diff --git a/t/cobrand/bromley.t b/t/cobrand/bromley.t
index 6750d3183..3ab1f6150 100644
--- a/t/cobrand/bromley.t
+++ b/t/cobrand/bromley.t
@@ -233,10 +233,11 @@ subtest 'check heatmap page' => sub {
FixMyStreet::override_config {
ALLOWED_COBRANDS => 'bromley',
MAPIT_URL => 'http://mapit.uk/',
+ COBRAND_FEATURES => { heatmap => { bromley => 1 } },
}, sub {
$mech->log_in_ok($user->email);
- $mech->get_ok('/about/heatmap?end_date=2018-12-31');
- $mech->get_ok('/about/heatmap?filter_category=RED&ajax=1');
+ $mech->get_ok('/dashboard/heatmap?end_date=2018-12-31');
+ $mech->get_ok('/dashboard/heatmap?filter_category=RED&ajax=1');
};
};
diff --git a/templates/web/base/admin/stats/index.html b/templates/web/base/admin/stats/index.html
index d47054427..452af001e 100644
--- a/templates/web/base/admin/stats/index.html
+++ b/templates/web/base/admin/stats/index.html
@@ -5,6 +5,15 @@
<li><a href="[% c.uri_for_action('admin/stats/state') %]">[% loc('Problem breakdown by state') %]</a></li>
<li><a href="[% c.uri_for_action('admin/stats/fix_rate') %]">[% loc('Category fix rate for problems > 4 weeks old') %]</a></li>
<li><a href="[% c.uri_for_action('dashboard/index') %]">[% loc('Summary statistics') %]</a></li>
+[% IF c.cobrand.feature('heatmap').keys %]
+ <li>[% loc('Heatmap') %] <ul>
+ [% FOR body IN c.cobrand.feature('heatmap').pairs %]
+ <li><a href="[% c.uri_for_action('dashboard/heatmap') %]?body=[% body.value %]">[% body.key %]</a></li>
+ [% END %]
+ </ul> </li>
+[% ELSIF c.cobrand.feature('heatmap') %]
+<li><a href="[% c.uri_for_action('dashboard/heatmap') %]">[% loc('Heatmap') %]</a></li>
+[% END %]
[% IF c.cobrand.moniker == 'fixmystreet' %]
<li><a href="[% c.uri_for_action('admin/stats/refused') %]">Refused</a></li>
[% END %]
diff --git a/templates/web/bromley/about/heatmap-list.html b/templates/web/base/dashboard/heatmap-list.html
index e04df8581..d736a11f4 100644
--- a/templates/web/bromley/about/heatmap-list.html
+++ b/templates/web/base/dashboard/heatmap-list.html
@@ -2,7 +2,7 @@
[% INCLUDE column problems = five_newest %]
<h3>Five most recent commented reports<br>
-<small>Not from yourself or Confirm</small>
+<small>Not from yourself/backend</small>
</h3>
[% INCLUDE column problems = five_commented %]
diff --git a/templates/web/bromley/about/heatmap.html b/templates/web/base/dashboard/heatmap.html
index 0cb8bfb1b..ba5c10c17 100755
--- a/templates/web/bromley/about/heatmap.html
+++ b/templates/web/base/dashboard/heatmap.html
@@ -1,5 +1,8 @@
[%
- map_js.push(version('/cobrands/bromley/HeatmapLayer.js'));
+ map_js.push(
+ '/vendor/HeatmapLayer.js',
+ '/cobrands/fixmystreet/density-map.js',
+ );
PROCESS "maps/${map.type}.html";
SET bodyclass = 'mappage';
INCLUDE 'header.html',
@@ -18,7 +21,9 @@
<div class="full-width">
-[% INCLUDE "reports/_list-filters.html", use_form_wrapper = 1 %]
+[% INCLUDE "reports/_list-filters.html", use_form_wrapper = 1 heatmap=1 %]
+
+<input type="hidden" id="body" name="body" value="[% body.id | html %]">
<p class="report-list-filters" style='padding-top:0.25em'>
From <input type="date" id="start_date" name="start_date" class="form-control" value="[% start_date | html %]">
@@ -35,14 +40,14 @@ In wards <select class="form-control js-multiple" multiple id="wards" name="ward
</div>
<p class="segmented-control segmented-control--radio">
- <input type="radio" name="heatmap" id="heatmap_yes" value="Yes">
+ <input type="radio" name="heatmap" id="heatmap_yes" value="Yes" checked>
<label class="btn" for="heatmap_yes">Heatmap</label>
- <input type="radio" name="heatmap" id="heatmap_no" value="No" checked>
+ <input type="radio" name="heatmap" id="heatmap_no" value="No">
<label class="btn" for="heatmap_no">Pin map</label>
</p>
<div id="js-reports-list">
- [% INCLUDE 'about/heatmap-list.html' %]
+ [% INCLUDE 'dashboard/heatmap-list.html' %]
</div>
</div>
diff --git a/templates/web/base/reports/_list-filter-status.html b/templates/web/base/reports/_list-filter-status.html
index 6923a7929..6fa998fc1 100644
--- a/templates/web/base/reports/_list-filter-status.html
+++ b/templates/web/base/reports/_list-filter-status.html
@@ -20,7 +20,7 @@
[%~ END ~%]
[% INCLUDE 'reports/_status_filter_options.html' %]
>
- [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') AND !shortlist %]
+ [% IF c.user_exists AND c.user.has_body_permission_to('planned_reports') AND !shortlist AND !heatmap %]
<option value="shortlisted"[% ' selected' IF filter_status.shortlisted %]>[% loc('Shortlisted') %]</option>
<option value="unshortlisted"[% ' selected' IF filter_status.unshortlisted %]>[% loc('Unshortlisted') %]</option>
[% END %]
diff --git a/templates/web/bromley/footer_extra_js.html b/templates/web/bromley/footer_extra_js.html
index 26c8fe9f5..b58dda570 100644
--- a/templates/web/bromley/footer_extra_js.html
+++ b/templates/web/bromley/footer_extra_js.html
@@ -5,7 +5,6 @@
) %]
[% IF bodyclass.match('mappage');
scripts.push(
- version('/cobrands/bromley/js.js'),
version('/vendor/OpenLayers.Projection.OrdnanceSurvey.js'),
version('/cobrands/fixmystreet/assets.js'),
version('/cobrands/bromley/map.js'),
diff --git a/web/cobrands/bromley/js.js b/web/cobrands/fixmystreet/density-map.js
index 8ff314189..9febf66d7 100644
--- a/web/cobrands/bromley/js.js
+++ b/web/cobrands/fixmystreet/density-map.js
@@ -19,12 +19,15 @@ if (window.Heatmap) {
fixmystreet.protocol_params.wards = 'wards';
fixmystreet.protocol_params.start_date = 'start_date';
fixmystreet.protocol_params.end_date = 'end_date';
+fixmystreet.protocol_params.body = 'body';
$(function(){
if (!window.Heatmap) {
return;
}
+ var heatmap_on = $('input[name=heatmap]:checked').val() === 'Yes';
+
var heat_layer = new Heatmap.Layer("Heatmap");
heat_layer.setOpacity(0.7);
heat_layer.setVisibility(false);
@@ -59,17 +62,22 @@ $(function(){
fixmystreet.markers.setVisibility(true);
});
+ if (heatmap_on) {
+ fixmystreet.markers.setVisibility(false);
+ heat_layer.setVisibility(true);
+ }
+
$('#sort').closest('.report-list-filters').hide();
- $("#wards, #start_date, #end_date").on("change.filters", function() {
+ $("#wards, #start_date, #end_date").on("change.filters", debounce(function() {
// If the category or status has changed we need to re-fetch map markers
fixmystreet.markers.events.triggerEvent("refresh", {force: true});
- });
- $("#filter_categories, #statuses").on("change.filters", function() {
+ }, 1000));
+ $("#filter_categories, #statuses").on("change.filters", debounce(function() {
if (!fixmystreet.markers.getVisibility()) {
// If not visible, still want to trigger change for heatmap
fixmystreet.markers.events.triggerEvent("refresh", {force: true});
}
- });
+ }, 1000));
});
diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js
index 1588bda2e..eb62904b0 100644
--- a/web/js/map-OpenLayers.js
+++ b/web/js/map-OpenLayers.js
@@ -10,6 +10,19 @@ if (!Object.keys) {
};
}
+function debounce(fn, delay) {
+ var timeout;
+ return function() {
+ var that = this, args = arguments;
+ var debounced = function() {
+ timeout = null;
+ fn.apply(that, args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(debounced, delay);
+ };
+}
+
var fixmystreet = fixmystreet || {};
fixmystreet.utils = fixmystreet.utils || {};
@@ -428,10 +441,10 @@ $.extend(fixmystreet.utils, {
}
}
- function categories_or_status_changed() {
+ var categories_or_status_changed = debounce(function() {
// If the category or status has changed we need to re-fetch map markers
fixmystreet.markers.refresh({force: true});
- }
+ }, 1000);
function replace_query_parameter(qs, id, key) {
var value,
diff --git a/web/cobrands/bromley/HeatmapLayer.js b/web/vendor/HeatmapLayer.js
index 93f3e84b2..93f3e84b2 100644
--- a/web/cobrands/bromley/HeatmapLayer.js
+++ b/web/vendor/HeatmapLayer.js