diff options
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 10 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Dashboard.pm | 126 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 30 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Bromley.pm | 33 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/Result/User.pm | 2 | ||||
-rw-r--r-- | t/app/controller/report_new.t | 2 | ||||
-rwxr-xr-x | templates/web/bromley/around/display_location.html | 2 | ||||
-rw-r--r-- | templates/web/bromley/index.html | 2 | ||||
-rw-r--r-- | templates/web/bromley/report/display.html | 8 | ||||
-rw-r--r-- | templates/web/default/dashboard/index.html | 131 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/_base.scss | 6 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/_layout.scss | 2 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 2 |
13 files changed, 341 insertions, 15 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index 42e218f61..d11f1645e 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -547,8 +547,7 @@ sub report_edit : Path('report_edit') : Args(1) { } )->first; - $c->detach( '/page_error_404_not_found', - [ _('The requested URL was not found on this server.') ] ) + $c->detach( '/page_error_404_not_found' ) unless $problem; $c->stash->{problem} = $problem; @@ -710,8 +709,7 @@ sub update_edit : Path('update_edit') : Args(1) { } )->first; - $c->detach( '/page_error_404_not_found', - [ _('The requested URL was not found on this server.') ] ) + $c->detach( '/page_error_404_not_found' ) unless $update; $c->forward('get_token'); @@ -1044,7 +1042,7 @@ sub check_token : Private { my ( $self, $c ) = @_; if ( !$c->req->param('token') || $c->req->param('token' ) ne $c->stash->{token} ) { - $c->detach( '/page_error_404_not_found', [ _('The requested URL was not found on this server.') ] ); + $c->detach( '/page_error_404_not_found' ); } return 1; @@ -1214,7 +1212,7 @@ sub check_page_allowed : Private { $page ||= 'summary'; if ( !grep { $_ eq $page } keys %{ $c->stash->{allowed_pages} } ) { - $c->detach( '/page_error_404_not_found', [ _('The requested URL was not found on this server.') ] ); + $c->detach( '/page_error_404_not_found' ); } return 1; diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm new file mode 100644 index 000000000..6c327d479 --- /dev/null +++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm @@ -0,0 +1,126 @@ +package FixMyStreet::App::Controller::Dashboard; +use Moose; +use namespace::autoclean; + +use DateTime; + +BEGIN { extends 'Catalyst::Controller'; } + +=head1 NAME + +FixMyStreet::App::Controller::Dashboard - Catalyst Controller + +=head1 DESCRIPTION + +Catalyst Controller. + +=head1 METHODS + +=cut + +=head2 check_page_allowed + +Checks if we can view this page, and if not redirect to 404. + +=cut + +sub check_page_allowed : Private { + my ( $self, $c ) = @_; + + $c->detach( '/auth/redirect' ) unless $c->user_exists; + + $c->detach( '/page_error_404_not_found' ) + unless $c->user_exists && $c->user->from_council; + + return $c->user->from_council; +} + +=head2 index + +Show the dashboard table. + +=cut + +sub index : Path : Args(0) { + my ( $self, $c ) = @_; + + my $council = $c->forward('check_page_allowed'); + + my $children = mySociety::MaPit::call('area/children', $council, + type => $mySociety::VotingArea::council_child_types, + ); + $c->stash->{children} = $children; + + my %counts; + my $t = DateTime->today; + + $counts{wtd} = $c->forward( 'updates_search', [ { + council => $council, + 'me.confirmed' => { '>=', $t->subtract( days => $t->dow - 1 ) + } } ] ); + + $counts{week} = $c->forward( 'updates_search', [ { + council => $council, + 'me.confirmed' => { '>=', DateTime->now->subtract( weeks => 1 ) + } } ] ); + + $counts{weeks} = $c->forward( 'updates_search', [ { + council => $council, + 'me.confirmed' => { '>=', DateTime->now->subtract( weeks => 4 ) + } } ] ); + + $counts{ytd} = $c->forward( 'updates_search', [ { + council => $council, + 'me.confirmed' => { '>=', DateTime->today->set( day => 1, month => 1 ) + } } ] ); + + $c->stash->{problems} = \%counts; +} + +sub updates_search : Private { + my ( $self, $c, $params ) = @_; + + my $comments = $c->model('DB::Comment')->search( + $params, + { + group_by => [ 'problem_state' ], + select => [ 'problem_state', { count => 'me.id' } ], + as => [ qw/state state_count/ ], + join => 'problem' + } + ); + + my %counts = + map { ($_->state||'-') => $_->get_column('state_count') } $comments->all; + %counts = + map { $_ => $counts{$_} || 0 } + ('confirmed', 'investigating', 'in progress', 'closed', 'fixed - council', + 'fixed - user', 'fixed', 'unconfirmed', 'hidden', + 'partial', 'planned'); + + $counts{fixed_user} = $c->model('DB::Comment')->search( + { %$params, mark_fixed => 1 }, { join => 'problem' } + )->count; + + $counts{total} = $c->cobrand->problems->search( + { %$params, state => [ FixMyStreet::DB::Result::Problem::visible_states() ] } + )->count; + + return \%counts; +} + +=head1 AUTHOR + +Matthew Somerville + +=head1 LICENSE + +Copyright (c) 2012 UK Citizens Online Democracy. All rights reserved. +Licensed under the Affero GPL. + +=cut + +__PACKAGE__->meta->make_immutable; + +1; + diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index afe180c29..cca625bd5 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -153,6 +153,36 @@ sub generate_map_tags : Private { return 1; } +sub delete :Local :Args(1) { + my ( $self, $c, $id ) = @_; + + $c->forward( 'load_problem_or_display_error', [ $id ] ); + my $p = $c->stash->{problem}; + + my $uri = $c->uri_for( '/report', $id ); + + return $c->res->redirect($uri) unless $c->user_exists; + + my $council = $c->user->obj->from_council; + return $c->res->redirect($uri) unless $council; + + my %councils = map { $_ => 1 } @{$p->councils}; + return $c->res->redirect($uri) unless $councils{$council}; + + $p->state('hidden'); + $p->lastupdate( \'ms_current_timestamp()' ); + $p->update; + + $c->model('DB::AdminLog')->create( { + admin_user => $c->user->email, + object_type => 'problem', + action => 'state_change', + object_id => $id, + } ); + + return $c->res->redirect($uri); +} + __PACKAGE__->meta->make_immutable; 1; diff --git a/perllib/FixMyStreet/Cobrand/Bromley.pm b/perllib/FixMyStreet/Cobrand/Bromley.pm index acdefb41e..5bc292306 100644 --- a/perllib/FixMyStreet/Cobrand/Bromley.pm +++ b/perllib/FixMyStreet/Cobrand/Bromley.pm @@ -36,6 +36,10 @@ sub example_places { return ( 'BR1 3UH', 'Glebe Rd, Bromley' ); } +sub on_map_default_max_pin_age { + return '1 month'; +} + sub recent_photos { my ( $self, $area, $num, $lat, $lon, $dist ) = @_; $num = 3 if $num > 3 && $area eq 'alert'; @@ -44,10 +48,37 @@ sub recent_photos { sub pin_colour { my ( $self, $p ) = @_; - return 'green' if time() - $p->confirmed_local->epoch < 7 * 24 * 60 * 60; + #return 'green' if time() - $p->confirmed_local->epoch < 7 * 24 * 60 * 60; return 'yellow'; } +# Copy of function from FixMyStreet.pm cobrand as it's not inherited currently +sub generate_problem_banner { + my ( $self, $problem ) = @_; + + my $banner = {}; + if ( $problem->is_open && time() - $problem->lastupdate_local->epoch > 8 * 7 * 24 * 60 * 60 ) + { + $banner->{id} = 'unknown'; + $banner->{text} = _('Unknown'); + } + if ($problem->is_fixed) { + $banner->{id} = 'fixed'; + $banner->{text} = _('Fixed'); + } + if ($problem->is_closed) { + $banner->{id} = 'closed'; + $banner->{text} = _('Closed'); + } + + if ( grep { $problem->state eq $_ } ( 'investigating', 'in progress', 'planned' ) ) { + $banner->{id} = 'progress'; + $banner->{text} = _('In progress'); + } + + return $banner; +} + sub process_extras { my $self = shift; my $ctx = shift; diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index 6788447d7..7f43d1a52 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -195,7 +195,7 @@ sub split_name { my ($first, $last) = $self->name =~ /^(\S*)(?: (.*))?$/; - return { first => $first, last => $last }; + return { first => $first || '', last => $last || '' }; } 1; diff --git a/t/app/controller/report_new.t b/t/app/controller/report_new.t index 4a8cbbbfe..5fc6e6a5d 100644 --- a/t/app/controller/report_new.t +++ b/t/app/controller/report_new.t @@ -731,7 +731,7 @@ subtest "check that a lat/lon off coast leads to /around" => sub { is $mech->uri->path, '/around', "redirected to '/around'"; is_deeply # - $mech->page_errors, + $mech->form_errors, [ 'That spot does not appear to be covered by a council. If you have' . ' tried to report an issue past the shoreline, for example, please' . ' specify the closest point on land.' ], # diff --git a/templates/web/bromley/around/display_location.html b/templates/web/bromley/around/display_location.html index d2726e035..b961ef4c6 100755 --- a/templates/web/bromley/around/display_location.html +++ b/templates/web/bromley/around/display_location.html @@ -70,7 +70,7 @@ <div id="side"> <h1 class="big-green-banner">[% loc( 'Click map to report a problem' ) %] - <span>Pins show existing reports</span></h1> + <span>Yellow pins show existing reports</span></h1> <p id="skip-this-step"> [% diff --git a/templates/web/bromley/index.html b/templates/web/bromley/index.html index 4b95230df..aeb4cc01c 100644 --- a/templates/web/bromley/index.html +++ b/templates/web/bromley/index.html @@ -21,7 +21,7 @@ Modernizr.load({ <h1 class="main mob-only">Reporting a problem in Bromley’s streets or parks</h1> [% IF error %] - <p class="error">[% error %]</p> + <p class="form-error">[% error %]</p> [% END %] <div id="front-main"> diff --git a/templates/web/bromley/report/display.html b/templates/web/bromley/report/display.html index fd74ac8db..c1a938b71 100644 --- a/templates/web/bromley/report/display.html +++ b/templates/web/bromley/report/display.html @@ -24,7 +24,13 @@ <div class="shadow-wrap"> <ul id="key-tools"> - <li><a rel="nofollow" id="key-tool-report-abuse" class="abuse" href="[% c.uri_for( '/contact', { id => problem.id } ) %]">[% loc('Report abuse' ) %]</a></li> + [% IF c.user_exists AND c.user.council == 'Bromley Council' %] + <li><form method="post" action="/report/delete/[% problem.id %]"> + <input type="submit" class="abuse" value="Remove from site"> + </form></li> + [% ELSE %] + <li><a rel="nofollow" id="key-tool-report-abuse" class="abuse" href="[% c.uri_for( '/contact', { id => problem.id } ) %]">[% loc('Report abuse') %]</a></li> + [% END %] <li><a rel="nofollow" id="key-tool-report-updates" class="feed" href="[% c.uri_for( '/alert/subscribe', { id => problem.id } ) %]">[% loc('Get updates' ) %]</a></li> <li><a class="chevron" id="key-tool-problems-nearby" href="[% c.uri_for( '/around', { lat => short_latitude, lon => short_longitude } ) %]">[% loc( 'Problems nearby' ) %]</a></li> </ul> diff --git a/templates/web/default/dashboard/index.html b/templates/web/default/dashboard/index.html new file mode 100644 index 000000000..c54635b2a --- /dev/null +++ b/templates/web/default/dashboard/index.html @@ -0,0 +1,131 @@ +[% + INCLUDE 'header.html' + title = loc('Dashboard') + robots = 'noindex, nofollow' + bodyclass = 'fullwidthpage' +%] + +<style> + th[scope=row] { text-align: left; } + tr.subtotal { background-color: #eee; } + #overview tr:nth-child(2) { background-color: #fee; } +</style> + +<p>Ward: <select name="ward"><option>All</option> + [% FOR ward IN children.values.sort('name') %] + <option value="[% ward.id %]">[% ward.name %]</option> + [% END %] +</select> + +<h2>Performance Overview</h2> + +<p>Report category: <select name="category"><option>All</option> + [% FOR category IN categories %] + <option></option> + [% END %] +</select> + +<table width="100%" id="overview"> + <tr> + <td> </td> + <th scope="col">WTD</th> + <th scope="col">Last 7 days</th> + <th scope="col">Last 4 weeks</th> + <th scope="col">YTD</th> + </tr> + + [% + rows = { + '0' => [ "total", "Total reports received" ] + '1' => [ "fixed - council", "Council has marked as fixed" ] + '2' => [ "fixed_user", "User has marked as fixed" ] + }; + FOR row IN rows %] + <tr> + <th scope="row">[% row.value.1 %]</th> + <td>[% problems.wtd.${row.value.0} %]</td> + <td>[% problems.week.${row.value.0} %]</td> + <td>[% problems.weeks.${row.value.0} %]</td> + <td>[% problems.ytd.${row.value.0} %]</td> + </tr> + [% END %] + + <tr class='subtotal'> + <th scope="row">Total marked as fixed</th> + <td>[% problems.wtd.${"fixed - council"} + problems.wtd.fixed_user %]</td> + <td>[% problems.week.${"fixed - council"} + problems.week.fixed_user %]</td> + <td>[% problems.weeks.${"fixed - council"} + problems.weeks.fixed_user %]</td> + <td>[% problems.ytd.${"fixed - council"} + problems.ytd.fixed_user %]</td> + </tr> + + [% + rows = { + '0' => [ "in progress", "Council has marked as in progress" ] + '1' => [ "planned", "Council has marked as planned" ] + '2' => [ "investigating", "Council has marked as investigating" ] + }; + wtd = 0, week = 0, weeks = 0, ytd = 0; + FOR row IN rows %] + <tr> + <th scope="row">[% row.value.1 %]</th> + <td>[% problems.wtd.${row.value.0} %]</td> + <td>[% problems.week.${row.value.0} %]</td> + <td>[% problems.weeks.${row.value.0} %]</td> + <td>[% problems.ytd.${row.value.0} %]</td> + </tr> + [% END %] + + <tr class='subtotal'> + <th scope="row">Total marked</th> + <td>[% problems.wtd.${"in progress"} + problems.wtd.planned + problems.wtd.investigating %]</td> + <td>[% problems.week.${"in progress"} + problems.week.planned + problems.week.investigating %]</td> + <td>[% problems.weeks.${"in progress"} + problems.weeks.planned + problems.weeks.investigating %]</td> + <td>[% problems.ytd.${"in progress"} + problems.ytd.planned + problems.ytd.investigating %]</td> + </tr> + + <tr> + <th scope="row">Average time to fix</th> + <td>-</td> + <td>-</td> + <td>-</td> + <td>-</td> + </tr> + + <tr> + <th scope="row">Average time to mark</th> + <td>-</td> + <td>-</td> + <td>-</td> + <td>-</td> + </tr> + + <tr class='subtotal'> + <th scope="row">Total not marked</th> + <td>-</td> + <td>-</td> + <td>-</td> + <td>-</td> + </tr> + +</table> + +<h2>Reports</h2> + +<p>Report state: <select name="state"><option>All</option></select> + +<table width="100%"> + <tr> + <th scope="col">Less than 7 days old</th> + <th scope="col">7-14 days old</th> + <th scope="col">14-30 days old</th> + <th scope="col">30+ days old</th> + </tr> + <tr> + <td><ul><li></li></ul></td> + <td><ul><li></li></ul></td> + <td><ul><li></li></ul></td> + <td><ul><li></li></ul></td> + </tr> +</table> + +[% INCLUDE 'footer.html' %] diff --git a/web/cobrands/fixmystreet/_base.scss b/web/cobrands/fixmystreet/_base.scss index ef60a8bef..bc8616954 100644 --- a/web/cobrands/fixmystreet/_base.scss +++ b/web/cobrands/fixmystreet/_base.scss @@ -529,7 +529,11 @@ p.label-valid { &:last-child { border-right:none; } - a { + input[type=submit] { + width: 100%; + border: none; + } + a, input[type=submit] { display: block; background-color: #f5f5f5; background-repeat: no-repeat; diff --git a/web/cobrands/fixmystreet/_layout.scss b/web/cobrands/fixmystreet/_layout.scss index 5756d4df3..207c6a4c4 100644 --- a/web/cobrands/fixmystreet/_layout.scss +++ b/web/cobrands/fixmystreet/_layout.scss @@ -592,7 +592,7 @@ body.twothirdswidthpage { @include box-shadow(-0em 0px 1em 1em #fff); li { border:none; - a { + a, input[type=submit] { font-size: 0.75em; color:#666; padding: 0.5em 1.5em 0.5em 0; diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index f65d8083a..b674020b1 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -143,7 +143,7 @@ $(function(){ // Remove full-screen-ness var banner_text; if (cobrand == 'bromley') { - banner_text = 'Click map to report a problem<span>Pins show existing reports</span>'; + banner_text = 'Click map to report a problem<span>Yellow pins show existing reports</span>'; } else { $('#site-header').show(); banner_text = 'Click map to report a problem'; |