aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStruan Donald <struan@exo.org.uk>2017-11-30 15:19:39 +0000
committerMatthew Somerville <matthew-github@dracos.co.uk>2017-12-15 17:35:53 +0000
commitfb75d4f912c504b42d11f2c8f32b5dcff2b348b6 (patch)
tree794942f1aa5fff74c3dd40439764c1ad86456692
parentf8f4d505ee63e3e8eb83576b3e3ce64c2b35c322 (diff)
[fixmystreet.com] Marketing page, filterable stats
Uses the dashboard stats code to display a rough table of stats which can be used as the basis for a chart later
-rw-r--r--perllib/FixMyStreet/App/Controller/Dashboard.pm8
-rw-r--r--perllib/FixMyStreet/App/Controller/Reports.pm93
-rw-r--r--perllib/FixMyStreet/Cobrand/FixMyStreet.pm5
-rw-r--r--t/cobrand/fixmystreet.t1
-rwxr-xr-xtemplates/web/base/reports/index.html54
-rw-r--r--templates/web/fixmystreet.com/reports/summary.html173
6 files changed, 260 insertions, 74 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm
index 5fe473c54..cff4c8dab 100644
--- a/perllib/FixMyStreet/App/Controller/Dashboard.pm
+++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm
@@ -175,15 +175,15 @@ sub generate_data {
$state_map->{$_} = 'closed' foreach FixMyStreet::DB::Result::Problem->closed_states;
$state_map->{$_} = 'fixed' foreach FixMyStreet::DB::Result::Problem->fixed_states;
- $self->generate_grouped_data($c);
+ $c->forward('generate_grouped_data');
$self->generate_summary_figures($c);
}
-sub generate_grouped_data {
+sub generate_grouped_data : Private {
my ($self, $c) = @_;
my $state_map = $c->stash->{state_map};
- my $group_by = $c->get_param('group_by') || '';
+ my $group_by = $c->get_param('group_by') || $c->stash->{group_by_default} || '';
my (%grouped, @groups, %totals);
if ($group_by eq 'category') {
%grouped = map { $_->category => {} } @{$c->stash->{contacts}};
@@ -197,6 +197,8 @@ sub generate_grouped_data {
);
} elsif ($group_by eq 'device+site') {
@groups = qw/cobrand service/;
+ } elsif ($group_by eq 'device') {
+ @groups = qw/service/;
} else {
$group_by = 'category+state';
@groups = qw/category state/;
diff --git a/perllib/FixMyStreet/App/Controller/Reports.pm b/perllib/FixMyStreet/App/Controller/Reports.pm
index b6281f0ca..5ac3da197 100644
--- a/perllib/FixMyStreet/App/Controller/Reports.pm
+++ b/perllib/FixMyStreet/App/Controller/Reports.pm
@@ -69,19 +69,8 @@ sub index : Path : Args(0) {
}
}
- my $dashboard = eval {
- my $data = FixMyStreet->config('TEST_DASHBOARD_DATA');
- # uncoverable branch true
- unless ($data) {
- my $fn = '../data/all-reports-dashboard';
- if ($c->stash->{body}) {
- $fn .= '-' . $c->stash->{body}->id;
- }
- $data = decode_json(path(FixMyStreet->path_to($fn . '.json'))->slurp_utf8);
- }
- $c->stash($data);
- return 1;
- };
+ my $dashboard = $c->forward('load_dashboard_data');
+
my $table = !$c->stash->{body} && eval {
my $data = path(FixMyStreet->path_to('../data/all-reports.json'))->slurp_utf8;
$c->stash(decode_json($data));
@@ -425,6 +414,65 @@ sub ward_check : Private {
$c->detach( 'redirect_body' );
}
+=head2 summary
+
+This is the summary page used on fixmystreet.com
+
+=cut
+
+sub summary : Private {
+ my ($self, $c) = @_;
+ my $dashboard = $c->forward('load_dashboard_data');
+
+ eval {
+ my $data = path(FixMyStreet->path_to('../data/all-reports-dashboard.json'))->slurp_utf8;
+ $data = decode_json($data);
+ $c->stash(
+ top_five_bodies => $data->{top_five_bodies},
+ average => $data->{average},
+ );
+ };
+
+ my $dtf = $c->model('DB')->storage->datetime_parser;
+ my $period = $c->stash->{period} = $c->get_param('period') || '';
+ my $start_date;
+ if ($period eq 'ever') {
+ $start_date = DateTime->new(year => 2007);
+ } elsif ($period eq 'year') {
+ $start_date = DateTime->now->subtract(years => 1);
+ } elsif ($period eq '3months') {
+ $start_date = DateTime->now->subtract(months => 3);
+ } elsif ($period eq 'week') {
+ $start_date = DateTime->now->subtract(weeks => 1);
+ } else {
+ $c->stash->{period} = 'month';
+ $start_date = DateTime->now->subtract(months => 1);
+ }
+
+ # required to stop errors in generate_grouped_data
+ $c->stash->{q_state} = '';
+ $c->stash->{ward} = $c->get_param('ward');
+ $c->stash->{start_date} = $dtf->format_date($start_date);
+ $c->stash->{end_date} = $c->get_param('end_date');
+
+ $c->stash->{group_by_default} = 'category';
+
+ my $area_id = $c->stash->{body}->body_areas->first->area_id;
+ my $children = mySociety::MaPit::call('area/children', $area_id,
+ type => $c->cobrand->area_types_children,
+ );
+ $c->stash->{children} = $children;
+
+ $c->forward('/admin/fetch_contacts');
+ $c->stash->{contacts} = [ $c->stash->{contacts}->all ];
+
+ $c->forward('/dashboard/construct_rs_filter');
+
+ $c->forward('/dashboard/generate_grouped_data');
+
+ $c->stash->{template} = 'reports/summary.html';
+}
+
=head2 check_canonical_url
Given an already found (case-insensitively) body, check what URL
@@ -441,6 +489,25 @@ sub check_canonical_url : Private {
$c->detach( 'redirect_body' ) unless $body_short eq $url_short;
}
+sub load_dashboard_data : Private {
+ my ($self, $c) = @_;
+ my $dashboard = eval {
+ my $data = FixMyStreet->config('TEST_DASHBOARD_DATA');
+ # uncoverable branch true
+ unless ($data) {
+ my $fn = '../data/all-reports-dashboard';
+ if ($c->stash->{body}) {
+ $fn .= '-' . $c->stash->{body}->id;
+ }
+ $data = decode_json(path(FixMyStreet->path_to($fn . '.json'))->slurp_utf8);
+ }
+ $c->stash($data);
+ return 1;
+ };
+
+ return $dashboard;
+}
+
sub load_and_group_problems : Private {
my ( $self, $c ) = @_;
diff --git a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
index 2153ca33b..591234877 100644
--- a/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
+++ b/perllib/FixMyStreet/Cobrand/FixMyStreet.pm
@@ -81,14 +81,13 @@ sub council_dashboard_hook {
}
$c->forward('/admin/fetch_contacts');
- $c->stash->{display_contacts} = 1;
- return if $c->user->is_superuser;
+ $c->detach('/reports/summary') if $c->user->is_superuser;
my $body = $c->user->from_body || _user_to_body($c);
if ($body) {
# Matching URL and user's email body
- return if $body->id eq $c->stash->{body}->id;
+ $c->detach('/reports/summary') if $body->id eq $c->stash->{body}->id;
# Matched /a/ body, redirect to its summary page
$c->stash->{body} = $body;
diff --git a/t/cobrand/fixmystreet.t b/t/cobrand/fixmystreet.t
index 4d76e43c6..b48593593 100644
--- a/t/cobrand/fixmystreet.t
+++ b/t/cobrand/fixmystreet.t
@@ -44,7 +44,6 @@ FixMyStreet::override_config {
# Logged in, redirects
$mech->get_ok('/about/council-dashboard');
is $mech->uri->path, '/reports/Birmingham/summary';
- $mech->content_contains('Top 5 wards');
$mech->content_contains('Where we send Birmingham');
$mech->content_contains('lights@example.com');
diff --git a/templates/web/base/reports/index.html b/templates/web/base/reports/index.html
index ff812f113..70f4b3929 100755
--- a/templates/web/base/reports/index.html
+++ b/templates/web/base/reports/index.html
@@ -139,58 +139,4 @@
</div>
</div>
-[% IF display_contacts %]
-<div class="dashboard-row">
- <div class="dashboard-item dashboard-item--12">
- <h2 class="dashboard-subheading">[% tprintf( loc('Where we send %s reports'), body.name ) %]</h2>
- [% IF body.send_method == 'Refused' %]
- <p>
- [% tprintf( loc('%s currently does not accept reports from FixMyStreet.'), body.name) %]
- </p>
-
- <p>
- [% loc('If you&rsquo;d like to discuss this then <a href="/contact">get in touch</a>.') %]
- </p>
- [% ELSIF body.send_method == 'Noop' %]
- <p>
- [% tprintf( loc('Reports are currently not being sent to %s.'), body.name ) %]
- </p>
- [% ELSIF body.send_method != 'Email' AND body.send_method != '' %]
- <p>
- [% tprintf( loc('Reports to %s are currently sent directly into backend services.'), body.name) %]
- </p>
- [% ELSE %]
- <p>
- [% loc('We currently send all reports to the email addresses below.') %]
- </p>
-
- <p>
- [% loc('Did you know that if you used the approved open standard Open311 you could send reports directly into your own backend services &ndash; and get much more control over what additional information you request?') %]
- </p>
-
- <p>
- [% loc('If that&rsquo;s new to you, <a href="https://www.mysociety.org/2013/01/10/open311-introduced/">take a look at our simple Open311 primer</a> to see what you need to do to get up and running in a few days.') %]
- </p>
-
- <p>
- [% loc('If you would like to change either the categories or the contact emails below then <a href="/contact">get in touch</a>.') %]
- <p>
- <table class="dashboard-contacts-table">
- <tr>
- <th>[% loc('Category') %]</th>
- <th>[% loc('Contact') %]</th>
- </tr>
- [% WHILE ( cat = live_contacts.next ) %]
- <tr>
- <td class="contact-category"><a href="[% c.uri_for( 'body', body_id, cat.category ) %]">[% cat.category_display | html %]</a>
- </td>
- <td>[% cat.email | html %]</td>
- </tr>
- [% END %]
- </table>
- [% END %]
- </div>
-</div>
-[% END %]
-
[% INCLUDE 'footer.html' pagefooter = 'yes' %]
diff --git a/templates/web/fixmystreet.com/reports/summary.html b/templates/web/fixmystreet.com/reports/summary.html
new file mode 100644
index 000000000..6ea664331
--- /dev/null
+++ b/templates/web/fixmystreet.com/reports/summary.html
@@ -0,0 +1,173 @@
+[% USE Number.Format -%]
+[%
+ other_categories_formatted = other_categories | format_number;
+-%]
+[% extra_js = [
+ version('/vendor/chart.min.js'),
+ version('/js/dashboard.js')
+] -%]
+[% INCLUDE 'header.html', title = loc('Dashboard'), bodyclass => 'dashboard fullwidthpage' %]
+
+<div class="dashboard-header">
+ <h1>FMS [% loc('Dashboard') %]
+ [% IF body %] – [% body.name %] [% END %]
+ </h1>
+</div>
+
+<form method="GET">
+ <div class="filters">
+ <p>
+ <label for="ward">[% loc('Problems reported in area:') %]</label>
+ <select class="form-control" id="ward" name="ward">
+ <option value="">[% body.name %]</option>
+ [% FOR w IN children.values.sort('name') %]
+ <option value="[% w.id %]"[% ' selected' IF w.id == ward %]>[% w.name %]</option>
+ [% END %]
+ </select>
+ </p>
+ <p class="pro-feature">
+ <label for="category">[% loc('Category:') %]</label>
+ <select class="form-control" id="category" disabled>
+ <option>[% loc('All categories') %]</option>
+ </select>
+ </p>
+ <p class="pro-feature">
+ <label for="state">[% loc('Report state:') %]</label>
+ <select class="form-control" id="state" disabled>
+ <option>[% loc('All states') %]</option>
+ </select>
+ </p>
+ <p>
+ <label for="period">[% loc('Reported:') %]</label>
+ <select class="form-control" id="period" name="period">
+ <option value="week"[% ' selected' IF period == 'week' %]>This past week</option>
+ <option value="month"[% ' selected' IF period == 'month' %]>This past month</option>
+ <option value="3months"[% ' selected' IF period == '3months' %]>In the past 3 months</option>
+ <option value="year"[% ' selected' IF period == 'year' %]>This past year</option>
+ <option value="ever"[% ' selected' IF period == 'ever' %]>Any time</option>
+ <option disabled>Custom date range (Pro)</option>
+ </select>
+ </p>
+ <p class="no-label">
+ <input type="submit" class="btn" value="[% loc('Look up') %]">
+ </p>
+ </div>
+ <input type="hidden" name="group_by" value="[% group_by %]">
+
+ [% BLOCK gb %]
+ [% IF group_by == new_gb %]
+ <strong title="Currently grouped by [% text %]">[% text %]</strong>
+ [% ELSE %]
+ <a href="[% c.uri_with({ group_by => new_gb }) %]" title="Group by [% text %]">[% text %]</a>
+ [% END %]
+ [% END %]
+
+ <div class="dashboard-row">
+ <div class="dashboard-item dashboard-item--12">
+ <table class="dashboard-ranking-table js-make-bar-chart">
+ [% FOR k IN rows %]
+ <tr>
+ [% IF group_by == 'state' %]
+ <th scope="row">[% prettify_state(k) %]</th>
+ [% ELSE %]
+ <th scope="row">[% k or loc('Website') %]</th>
+ [% END %]
+ <td>[% grouped.$k.total OR 0 %]</td>
+ </tr>
+ [% END %]
+ </table>
+
+ <ul class="dashboard-options-tabs dashboard-options-tabs--below">
+ <li role="presentation"><span>[% loc('Group by:') %]</span><li>
+ <li>[% INCLUDE gb new_gb='category' text='category' %]</li>
+ <li>[% INCLUDE gb new_gb='device' text='device' %]</li>
+ <li>[% INCLUDE gb new_gb='state' text='state' %]</li>
+ <li class="pull-right"><a href="[% c.uri_with({ csv => 1 }) %]">[% loc('Export as CSV') %]</a></li>
+ </ul>
+ </div>
+ </div>
+
+</form>
+
+<div class="dashboard-row">
+ <div class="dashboard-item dashboard-item--6">
+ <h2 class="dashboard-subheading">[% tprintf( loc('How responsive is %s?'), body.name ) %]</h2>
+ <p>[% loc('Average time between a problem being reported and being fixed, last 100 reports.') %]</p>
+ <table class="dashboard-ranking-table">
+ <tbody>
+ [% FOR line IN top_five_bodies %]
+ <tr><td>[% line.name %]</td><td>[% tprintf(nget("%s day", "%s days", line.days), line.days) %]</td></tr>
+ [% END %]
+ </tbody>
+ <tfoot>
+ <tr><td>[% loc('Overall average') %]</td><td>[% tprintf(nget("%s day", "%s days", average), average) %]</td></tr>
+ </tfoot>
+ </table>
+ </div>
+ <div class="dashboard-item dashboard-item--6">
+ <h2 class="dashboard-subheading">[% tprintf( loc('Most popular categories in %s'), body.name ) %]</h2>
+ <p>[% loc('Number of problems reported in each category, in the last 7 days.') %]</p>
+ <table class="dashboard-ranking-table">
+ <tbody>
+ [% FOR line IN top_five_categories %]
+ [% line_count = line.count | format_number ~%]
+ <tr><td>[% line.category %]</td><td>[% tprintf(nget("%s report", "%s reports", line.count), decode(line_count)) %]</td></tr>
+ [% END %]
+ </tbody>
+ <tfoot>
+ <tr><td>[% loc('Other categories') %]</td><td>[% tprintf(nget("%s report", "%s reports", other_categories), decode(other_categories_formatted)) %]</td></tr>
+ </tfoot>
+ </table>
+ </div>
+</div>
+
+<div class="dashboard-row">
+ <div class="dashboard-item dashboard-item--12">
+ <h2 class="dashboard-subheading">[% tprintf( loc('Where we send %s reports'), body.name ) %]</h2>
+ [% IF body.send_method == 'Refused' %]
+ <p>
+ [% tprintf( loc('%s currently does not accept reports from FixMyStreet.'), body.name) %]
+ </p>
+
+ <p>
+ [% loc('If you&rsquo;d like to discuss this then <a href="/contact">get in touch</a>.') %]
+ </p>
+ [% ELSIF body.send_method == 'Noop' %]
+ <p>
+ [% tprintf( loc('Reports are currently not being sent to %s.'), body.name ) %]
+ </p>
+ [% ELSIF body.send_method != 'Email' AND body.send_method != '' %]
+ <p>
+ [% tprintf( loc('Reports to %s are currently sent directly into backend services.'), body.name) %]
+ </p>
+ [% ELSE %]
+ <p>
+ [% loc('We currently send all reports to the email addresses below.') %]
+ </p>
+ <table class="dashboard-ranking-table" style="margin-bottom: 1em;">
+ <tr>
+ <th>[% loc('Category') %]</th>
+ <th>[% loc('Contact') %]</th>
+ </tr>
+ [% WHILE ( cat = live_contacts.next ) %]
+ <tr>
+ <td class="contact-category"><a href="[% body_url %]?filter_category=[% cat.category | uri %]">[% cat.category_display | html %]</a>
+ </td>
+ <td>[% cat.email | html %]</td>
+ </tr>
+ [% END %]
+ </table>
+ <p>
+ [% loc('If you would like to change either the categories or the contact emails above then <a href="/contact">get in touch</a>.') %]
+ <p>
+ <p>
+ [% loc('Did you know that if you used the approved open standard Open311 you could send reports directly into your own backend services &ndash; and get much more control over what additional information you request?') %]
+ </p>
+ <p>
+ [% loc('If that&rsquo;s new to you, <a href="https://www.mysociety.org/2013/01/10/open311-introduced/">take a look at our simple Open311 primer</a> to see what you need to do to get up and running in a few days.') %]
+ </p>
+ [% END %]
+ </div>
+</div>
+
+[% INCLUDE 'footer.html' pagefooter = 'yes' %]