diff options
-rwxr-xr-x | bin/zurich-overdue-alert | 83 | ||||
-rw-r--r-- | conf/crontab.ugly | 4 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 15 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 63 | ||||
-rw-r--r-- | templates/email/zurich/alert-moderation-overdue.txt | 1 | ||||
-rw-r--r-- | templates/web/zurich/admin/header.html | 47 | ||||
-rw-r--r-- | templates/web/zurich/admin/problem_row.html | 5 | ||||
-rw-r--r-- | templates/web/zurich/admin/report_edit.html | 27 | ||||
-rw-r--r-- | templates/web/zurich/header.html | 35 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/position_map.js | 4 | ||||
-rw-r--r-- | web/cobrands/zurich/layout.scss | 18 |
11 files changed, 241 insertions, 61 deletions
diff --git a/bin/zurich-overdue-alert b/bin/zurich-overdue-alert new file mode 100755 index 000000000..aa9f6fe60 --- /dev/null +++ b/bin/zurich-overdue-alert @@ -0,0 +1,83 @@ +#!/usr/bin/env perl + +# zurich-overdue-alert: +# Send email alerts to administrators for overdue admin activities. +# +# Copyright (c) 2012 UK Citizens Online Democracy. All rights reserved. +# Email: matthew@mysociety.org. WWW: http://www.mysociety.org + +use strict; +use warnings; +require 5.8.0; + +use DateTime; +use CronFns; +use FixMyStreet::App; + +my ($verbose, $nomail) = CronFns::options(); + +# Only run on working days +my $now = DateTime->now(); +exit if FixMyStreet::Cobrand::Zurich::is_public_holiday($now) or FixMyStreet::Cobrand::Zurich::is_weekend($now); + +my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker('zurich')->new(); +my %bodies = map { $_->id => $_ } FixMyStreet::App->model("DB::Body")->all; + +loop_through( 'alert-moderation-overdue.txt', 0, 1, [ 'unconfirmed', 'confirmed' ] ); +loop_through( 'alert-overdue.txt', 1, 5, 'in progress' ); + +sub loop_through { + my ( $template, $include_parent, $days, $states ) = @_; + + my $reports = FixMyStreet::App->model("DB::Problem")->search( { + state => $states, + whensent => { '<', FixMyStreet::Cobrand::Zurich::sub_days( $now, $days ) }, + bodies_str => { '!=', undef }, + } ); + + my %to_send = (); + while (my $row = $reports->next) { + $to_send{$row->bodies_str} .= '* ' . $row->id . ": '" . $row->title . "'\n\n"; + } + + my $template_path = FixMyStreet->path_to( "templates", "email", "zurich", $template )->stringify; + $template = Utils::read_file( $template_path ); + + foreach my $body_id (keys %to_send) { + send_alert( $template, $body_id, $to_send{$body_id}, $include_parent ); + } +} + +sub send_alert { + my ( $template, $body_id, $data, $include_parent ) = @_; + + my $body = $bodies{$body_id}; + my $body_email = $body->endpoint; + + my $h = { + data => $data, + admin_url => $cobrand->admin_base_url, + }; + + my $env_to = [ $body_email ]; + my $to = [ [ $body_email, $body->name ] ]; + if ( $include_parent ) { + my $parent = $body->parent; + my $parent_email = $parent->endpoint; + push @$env_to, $parent_email; + push @$to, [ $parent_email, $parent->name ]; + } + + my $result = FixMyStreet::App->send_email_cron( + { + _template_ => $template, + _parameters_ => $h, + To => $to, + From => [ FixMyStreet->config('CONTACT_EMAIL'), FixMyStreet->config('CONTACT_NAME') ], + }, + FixMyStreet->config('CONTACT_EMAIL'), + $env_to, + $nomail + ); +} + diff --git a/conf/crontab.ugly b/conf/crontab.ugly index 7a2ab1891..c1de3d66f 100644 --- a/conf/crontab.ugly +++ b/conf/crontab.ugly @@ -64,3 +64,7 @@ my %no_alerts = map { $_ => 1 } @no_alerts; 39 2 * * * !!(*= $user *)!! /data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/problems-filed-graph 43 2 * * * !!(*= $user *)!! /data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/problem-creation-graph 00 8 * * * !!(*= $user *)!! /data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/check-for-zombies !!(*= $user *)!! + +!!(* if ($vhost =~ /zurich/) { *)!! +30 0 * * * !!(*= $user *)!! /data/vhost/!!(*= $vhost *)!!/fixmystreet/bin/zurich-overdue-alert +!!(* } *)!! diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index de69880c1..7869b21b7 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -606,6 +606,21 @@ sub report_edit : Path('report_edit') : Args(1) { } if ( $c->cobrand->moniker eq 'zurich' ) { + + FixMyStreet::Map::display_map( + $c, + latitude => $problem->latitude, + longitude => $problem->longitude, + pins => $problem->used_map + ? [ { + latitude => $problem->latitude, + longitude => $problem->longitude, + colour => 'yellow', + type => 'big', + } ] + : [], + ); + my $done = $c->cobrand->admin_report_edit(); return if $done; } diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 81ace5a05..6ac04ce1e 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -1,6 +1,7 @@ package FixMyStreet::Cobrand::Zurich; use base 'FixMyStreet::Cobrand::Default'; +use DateTime; use POSIX qw(strcoll); use strict; @@ -43,6 +44,68 @@ sub get_body_sender { return { method => 'Zurich' }; } +# Report overdue functions + +my %public_holidays = map { $_ => 1 } ( + '2013-01-01', '2013-01-02', '2013-03-29', '2013-04-01', + '2013-04-15', '2013-05-01', '2013-05-09', '2013-05-20', + '2013-08-01', '2013-09-09', '2013-12-25', '2013-12-26', + '2014-01-01', '2014-01-02', '2014-04-18', '2014-04-21', + '2014-04-28', '2014-05-01', '2014-05-29', '2014-06-09', + '2014-08-01', '2014-09-15', '2014-12-25', '2014-12-26', +); + +sub is_public_holiday { + my $dt = shift; + return $public_holidays{$dt->ymd}; +} + +sub is_weekend { + my $dt = shift; + return $dt->dow > 5; +} + +sub add_days { + my ( $dt, $days ) = @_; + $dt = $dt->clone; + while ( $days > 0 ) { + $dt->add ( days => 1 ); + next if is_public_holiday($dt) or is_weekend($dt); + $days--; + } + return $dt; +} + +sub sub_days { + my ( $dt, $days ) = @_; + $dt = $dt->clone; + while ( $days > 0 ) { + $dt->subtract ( days => 1 ); + next if is_public_holiday($dt) or is_weekend($dt); + $days--; + } + return $dt; +} + +sub overdue { + my ( $self, $problem ) = @_; + + my $w = $problem->whensent; + return 0 unless $w; + + if ( $problem->state eq 'unconfirmed' || $problem->state eq 'confirmed' ) { + # One working day + $w = add_days( $w, 1 ); + return $w < DateTime->now(); + } elsif ( $problem->state eq 'in progress' ) { + # Five working days + $w = add_days( $w, 5 ); + return $w < DateTime->now(); + } else { + return 0; + } +} + # Specific administrative displays sub admin_pages { diff --git a/templates/email/zurich/alert-moderation-overdue.txt b/templates/email/zurich/alert-moderation-overdue.txt index cf3569bc5..c3aab66d2 100644 --- a/templates/email/zurich/alert-moderation-overdue.txt +++ b/templates/email/zurich/alert-moderation-overdue.txt @@ -1,6 +1,7 @@ Subject: eskalierte Meldungen auf Fix my Zurich Die folgenden Meldungen auf Fix my Zurich sind älter als einen Tag und müssen dringend bearbeitet werden: + <?=$values['data']?> Um diese Meldungen zu moderieren, klicken Sie auf folgende URL: diff --git a/templates/web/zurich/admin/header.html b/templates/web/zurich/admin/header.html index d0c399a83..72472492a 100644 --- a/templates/web/zurich/admin/header.html +++ b/templates/web/zurich/admin/header.html @@ -1,5 +1,7 @@ -[% INCLUDE 'header.html' admin = 1, bodyclass = 'fullwidthpage admin' %] [% + SET bodyclass = bodyclass || 'fullwidthpage'; + INCLUDE 'header.html' admin = 1, bodyclass = bodyclass _ ' admin'; + states = { 'unconfirmed' = loc('Submitted'), 'confirmed' = loc('Open'), @@ -11,45 +13,10 @@ } %] <style type="text/css"> -dt { clear: left; float: left; font-weight: bold; } -dd { margin-left: 8em; } -.adminhidden { color: #666666; } -.error { color: red; } -select { width: auto; } + .adminhidden { color: #666666; } + .error { color: red; } + .overdue { color: #660000; } + select { width: auto; } </style> - <!--<strong>[% loc('FixMyStreet admin:') %]</strong>--> - <div class="admin-nav"> - <ul> - [% pagename = c.req.uri.path %] - [% pagename = pagename.replace('/admin/?(\w*).*', '$1') %] - - <li [% IF pagename == 'summary' OR pagename == '' %]class="current"[% END %]> - <a href="/admin/summary">[% loc('Summary') %]</a> - </li> - <li [% IF pagename == 'reports' OR pagename == 'report_edit' %]class="current"[% END %]> - <a href="/admin/reports">[% loc('Reports') %]</a> - </li> - [% IF admin_type == 'dm' OR admin_type == 'super' %] - <li [% IF pagename == 'bodies' OR pagename == 'body' %]class="current"[% END %]> - <a href="/admin/bodies">[% loc('Bodies') %]</a> - </li> - [% END %] - [% IF admin_type == 'super' %] - <li [% IF pagename == 'users' OR pagename == 'user_edit' %]class="current"[% END %]> - <a href="/admin/users">[% loc('Users') %]</a> - </li> - [% END %] - <li class="search-box"> - <form method="get" action="[% c.uri_for('reports') %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> - <input type="text" name="search" size="20" id="search" placeholder="[% loc('Search reports') %]"> - </form> - </li> - </ul> - </div> - <!-- | <a href="timeline">Timeline</a> --> - <!-- | <a href="questionnaire">Survey</a> --> - <!-- | <a href="flagged">Flagged</a> --> - <!-- | <a href="stats">Stats</a> --> - <h1 style="clear:both;">[% title %]</h1> diff --git a/templates/web/zurich/admin/problem_row.html b/templates/web/zurich/admin/problem_row.html index 176f1a1a6..617490232 100644 --- a/templates/web/zurich/admin/problem_row.html +++ b/templates/web/zurich/admin/problem_row.html @@ -4,7 +4,10 @@ [% NEXT IF admin_type == 'sdm' AND p_body.id != body.id %] [% NEXT IF admin_type == 'dm' AND p_body.id != body.id AND p_body.parent.id != body.id %] [% END %] - <tr[% ' class="adminhidden"' IF problem.state == 'hidden' %]> + <tr[% + ' class="adminhidden"' IF problem.state == 'hidden'; + ' class="overdue"' IF c.cobrand.overdue( problem ); + %]> <td class="record-id">[%- IF problem.is_visible -%] <a href="[% c.uri_for_email( '/report', problem.id ) %]">[% problem.id %]</a> [%- ELSE %] diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html index eb543a777..122045550 100644 --- a/templates/web/zurich/admin/report_edit.html +++ b/templates/web/zurich/admin/report_edit.html @@ -1,18 +1,20 @@ -[% INCLUDE 'admin/header.html' title=tprintf(loc('Editing problem %d'), problem.id ) -%] -[% PROCESS 'admin/report_blocks.html' %] +[% + PROCESS "maps/zurich.html"; + INCLUDE 'admin/header.html' + title = tprintf(loc('Editing problem %d'), problem.id ), + bodyclass = 'mappage'; + PROCESS 'admin/report_blocks.html' +-%] + +[% map_html %] +</div> [% status_message %] -[% IF problem.state == 'planned' %] -[% INCLUDE 'admin/list_updates.html' %] -[% END %] - <form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> <input type="hidden" name="token" value="[% token %]" > <input type="hidden" name="submit" value="1" > -<div style="float:left; margin-top: 1em; width:48%; margin-right:2%"> - <ul> <li><a href="[% c.uri_for_email( '/report', problem.id ) %]">[% loc('View report on site' )%]</a></li> @@ -53,9 +55,6 @@ <label class="inline" for="publish_photo">[% loc("Publish photo") %]</label></li> [% END %] </ul> -</div> - -<div style="float:right;width:48%"> <p><label for="internal_notes">[% loc('Internal notes:') %]</label> <textarea name='internal_notes' id='internal_notes' cols=60 rows=5>[% problem.extra.internal_notes | html %]</textarea></p> @@ -154,9 +153,6 @@ $(function(){ [% END %] -</div> - -<div style="clear:both"></div> <p align="right"> [% IF problem.state == 'planned' %] <input type="submit" name="publish_response" value="[% loc('Publish the response') %]"> @@ -166,9 +162,6 @@ $(function(){ </form> -[% IF problem.state != 'planned' %] [% INCLUDE 'admin/list_updates.html' %] -[% END %] - [% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/zurich/header.html b/templates/web/zurich/header.html index 47d7d39d2..77dd3cd63 100644 --- a/templates/web/zurich/header.html +++ b/templates/web/zurich/header.html @@ -44,6 +44,41 @@ </header> <div class="container"> + +[% IF admin %] + <div class="admin-nav-wrapper"> + <div class="admin-nav"> + <ul> + [% pagename = c.req.uri.path %] + [% pagename = pagename.replace('/admin/?(\w*).*', '$1') %] + + <li [% IF pagename == 'summary' OR pagename == '' %]class="current"[% END %]> + <a href="/admin/summary">[% loc('Summary') %]</a> + </li> + <li [% IF pagename == 'reports' OR pagename == 'report_edit' %]class="current"[% END %]> + <a href="/admin/reports">[% loc('Reports') %]</a> + </li> + [% IF admin_type == 'dm' OR admin_type == 'super' %] + <li [% IF pagename == 'bodies' OR pagename == 'body' %]class="current"[% END %]> + <a href="/admin/bodies">[% loc('Bodies') %]</a> + </li> + [% END %] + [% IF admin_type == 'super' %] + <li [% IF pagename == 'users' OR pagename == 'user_edit' %]class="current"[% END %]> + <a href="/admin/users">[% loc('Users') %]</a> + </li> + [% END %] + <li class="search-box"> + <form method="get" action="[% c.uri_for('reports') %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> + <input type="text" name="search" size="20" id="search" placeholder="[% loc('Search reports') %]"> + </form> + + </li> + </ul> + </div> + </div> +[% END %] + <div class="content[% " $mainclass" | html IF mainclass %]" role="main"> [% INCLUDE 'nav_over_content.html' %] diff --git a/web/cobrands/fixmystreet/position_map.js b/web/cobrands/fixmystreet/position_map.js index 4a18d9f9a..71794e8d6 100644 --- a/web/cobrands/fixmystreet/position_map.js +++ b/web/cobrands/fixmystreet/position_map.js @@ -1,14 +1,14 @@ function position_map_box() { var $html = $('html'); if ($html.hasClass('ie6')) { - $('#map_box').prependTo('.wrapper').css({ + $('#map_box').prependTo('body').css({ zIndex: 0, position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, width: '100%', height: $(window).height(), margin: 0 }); } else { - $('#map_box').prependTo('.wrapper').css({ + $('#map_box').prependTo('body').css({ zIndex: 0, position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, width: '100%', height: '100%', diff --git a/web/cobrands/zurich/layout.scss b/web/cobrands/zurich/layout.scss index 9ebab6da1..189957f5d 100644 --- a/web/cobrands/zurich/layout.scss +++ b/web/cobrands/zurich/layout.scss @@ -190,6 +190,11 @@ body.fullwidthpage.admin .content { width: 100%; } +body.mappage.admin .content { + margin-top: 6em; + margin-left: 0.5em; + +} .admin { .content { margin: 2em 0 1em; @@ -239,11 +244,22 @@ body.fullwidthpage.admin .content { } } +.admin-nav-wrapper { + background-color: white; + padding: 1.5em 0 1em; +} +body.mappage .admin-nav-wrapper { + box-sizing: border-box; + padding-left: 10px; + padding-right: 10px; + position: fixed; + width: 100%; +} + .admin-nav { background: #f4f4f4; @include background(linear-gradient(#fbfbfb, #efefef)); border-bottom: 2px solid $table_border_color; - margin: 0 0 1em 0; ul { overflow:auto; margin:0 0 -2px 0; |