aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/update-schema1
-rw-r--r--db/downgrade_0038---0037.sql2
-rw-r--r--db/schema.sql3
-rw-r--r--db/schema_0038-time-spent.sql2
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm13
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm54
-rw-r--r--perllib/FixMyStreet/DB/Result/AdminLog.pm2
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm12
-rw-r--r--perllib/FixMyStreet/TestMech.pm1
-rw-r--r--t/app/controller/questionnaire.t2
-rw-r--r--t/cobrand/zurich.t22
-rw-r--r--templates/web/zurich/admin/report_edit-sdm.html18
-rw-r--r--templates/web/zurich/admin/report_edit.html17
-rw-r--r--web/cobrands/zurich/base.scss7
14 files changed, 147 insertions, 9 deletions
diff --git a/bin/update-schema b/bin/update-schema
index d98fe6e9c..1af08b002 100755
--- a/bin/update-schema
+++ b/bin/update-schema
@@ -195,6 +195,7 @@ else {
# By querying the database schema, we can see where we're currently at
# (assuming schema change files are never half-applied, which should be the case)
sub get_db_version {
+ return '0038' if column_exists('admin_log', 'time_spent');
return '0037' if table_exists('response_templates');
return '0036' if constraint_contains('problem_cobrand_check', 'a-z0-9_');
return '0035' if column_exists('problem', 'bodies_missing');
diff --git a/db/downgrade_0038---0037.sql b/db/downgrade_0038---0037.sql
new file mode 100644
index 000000000..11a0d11ad
--- /dev/null
+++ b/db/downgrade_0038---0037.sql
@@ -0,0 +1,2 @@
+alter table admin_log
+ drop column time_spent;
diff --git a/db/schema.sql b/db/schema.sql
index e87a2aafe..72fccd7f3 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -427,7 +427,8 @@ create table admin_log (
action text not null,
whenedited timestamp not null default current_timestamp,
user_id int references users(id) null,
- reason text not null default ''
+ reason text not null default '',
+ time_spent int not null default 0
);
create table moderation_original_data (
diff --git a/db/schema_0038-time-spent.sql b/db/schema_0038-time-spent.sql
new file mode 100644
index 000000000..093eb4086
--- /dev/null
+++ b/db/schema_0038-time-spent.sql
@@ -0,0 +1,2 @@
+alter table admin_log
+ add column time_spent int not null default 0;
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index be705110b..5ebeffc11 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -1339,13 +1339,24 @@ Adds an entry into the admin_log table using the current user.
=cut
sub log_edit : Private {
- my ( $self, $c, $id, $object_type, $action ) = @_;
+ my ( $self, $c, $id, $object_type, $action, $time_spent ) = @_;
+
+ $time_spent //= 0;
+ $time_spent = 0 if $time_spent < 0;
+
+ my $user_object = do {
+ my $auth_user = $c->user;
+ $auth_user ? $auth_user->get_object : undef;
+ };
+
$c->model('DB::AdminLog')->create(
{
admin_user => $c->forward('get_user'),
+ $user_object ? ( user => $user_object ) : (), # as (rel => undef) doesn't work
object_type => $object_type,
action => $action,
object_id => $id,
+ time_spent => $time_spent,
}
)->insert();
}
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index 46d57158b..c039deb0d 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -5,6 +5,7 @@ use DateTime;
use POSIX qw(strcoll);
use RABX;
use Scalar::Util 'blessed';
+use DateTime::Format::Pg;
use strict;
use warnings;
@@ -277,13 +278,46 @@ sub get_or_check_overdue {
return $self->overdue($problem);
}
+=head1 C<set_problem_state>
+
+If the state has changed, sets the state and calls C::Admin's C<log_edit> action.
+If the state hasn't changed, defers to update_admin_log (to update time_spent if any).
+
+Returns either undef or the AdminLog entry created.
+
+=cut
+
sub set_problem_state {
my ($self, $c, $problem, $new_state) = @_;
- return if $new_state eq $problem->state;
+ return $self->update_admin_log($c, $problem) if $new_state eq $problem->state;
$problem->state( $new_state );
$c->forward( 'log_edit', [ $problem->id, 'problem', "state change to $new_state" ] );
}
+=head1 C<update_admin_log>
+
+Calls C::Admin's C<log_edit> if either a) text is provided, or b) there has
+been time_spent on the task. As set_problem_state will already call log_edit
+if required, don't call this as well.
+
+Returns either undef or the AdminLog entry created.
+
+=cut
+
+sub update_admin_log {
+ my ($self, $c, $problem, $text) = @_;
+
+ my $time_spent = ( ($c->req->param('time_spent') // 0) + 0 );
+ $c->req->param('time_spent' => 0); # explicitly zero this to avoid duplicates
+
+ if (!$text) {
+ return unless $time_spent;
+ $text = "Logging time_spent";
+ }
+
+ $c->forward( 'log_edit', [ $problem->id, 'problem', $text, $time_spent ] );
+}
+
# Specific administrative displays
sub admin_pages {
@@ -503,6 +537,7 @@ sub admin_report_edit {
$problem->whensent( undef );
$problem->set_extra_metadata(changed_category => 1);
$internal_note_text = "Weitergeleitet von $old_cat an $new_cat";
+ $self->update_admin_log($c, $problem, "Changed category from $old_cat to $new_cat");
$redirect = 1 if $cat->body_id ne $body->id;
} elsif ( my $subdiv = $c->get_param('body_subdivision') ) {
$problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) );
@@ -576,6 +611,10 @@ sub admin_report_edit {
} );
}
+ # Just update if time_spent still hasn't been logged
+ # (this will only happen if no other update_admin_log has already been called)
+ $self->update_admin_log($c, $problem);
+
if ( $redirect ) {
$c->detach('index');
}
@@ -748,7 +787,10 @@ sub admin_stats {
if ($y && $m) {
$c->stash->{start_date} = DateTime->new( year => $y, month => $m, day => 1 );
$c->stash->{end_date} = $c->stash->{start_date} + DateTime::Duration->new( months => 1 );
- $date_params{created} = { '>=', $c->stash->{start_date}, '<', $c->stash->{end_date} };
+ $date_params{created} = {
+ '>=', DateTime::Format::Pg->format_datetime($c->stash->{start_date}),
+ '<', DateTime::Format::Pg->format_datetime($c->stash->{end_date}),
+ };
}
my %params = (
@@ -760,6 +802,8 @@ sub admin_stats {
my $problems = $c->model('DB::Problem')->search(
{%date_params},
{
+ join => 'admin_log_entries',
+ distinct => 1,
columns => [
'id', 'created',
'latitude', 'longitude',
@@ -771,10 +815,11 @@ sub admin_stats {
'whensent', 'lastupdate',
'service',
'extra',
- ],
+ { sum_time_spent => { sum => 'admin_log_entries.time_spent' } },
+ ]
}
);
- my $body = "Report ID,Created,Sent to Agency,Last Updated,E,N,Category,Status,UserID,External Body,Title,Detail,Media URL,Interface Used,Council Response\n";
+ my $body = "Report ID,Created,Sent to Agency,Last Updated,E,N,Category,Status,UserID,External Body,Time Spent,Title,Detail,Media URL,Interface Used,Council Response\n";
require Text::CSV;
my $csv = Text::CSV->new({ binary => 1 });
while ( my $report = $problems->next ) {
@@ -802,6 +847,7 @@ sub admin_stats {
$report->local_coords, $report->category,
$report->state, $report->user_id,
$body_name,
+ $report->get_column('sum_time_spent') || 0,
$report->title,
$detail,
$media_url,
diff --git a/perllib/FixMyStreet/DB/Result/AdminLog.pm b/perllib/FixMyStreet/DB/Result/AdminLog.pm
index fcf909692..d60915cfc 100644
--- a/perllib/FixMyStreet/DB/Result/AdminLog.pm
+++ b/perllib/FixMyStreet/DB/Result/AdminLog.pm
@@ -37,6 +37,8 @@ __PACKAGE__->add_columns(
{ data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"reason",
{ data_type => "text", default_value => "", is_nullable => 0 },
+ "time_spent",
+ { data_type => "integer", default_value => "0", is_nullable => 0 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->belongs_to(
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index d3a30db4e..637f4acbf 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -886,6 +886,18 @@ __PACKAGE__->has_many(
}
);
+sub get_time_spent {
+ my $self = shift;
+ my $admin_logs = $self->admin_log_entries->search({},
+ {
+ group_by => 'object_id',
+ columns => [
+ { sum_time_spent => { sum => 'time_spent' } },
+ ]
+ })->single;
+ return $admin_logs ? $admin_logs->get_column('sum_time_spent') : 0;
+}
+
# we need the inline_constructor bit as we don't inherit from Moose
__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 8325b07a8..1035a47ba 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -165,6 +165,7 @@ sub delete_user {
$a->delete;
}
$_->delete for $user->comments;
+ $_->delete for $user->admin_logs;
$user->delete;
return 1;
diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t
index d4fc9c74b..2a89454d5 100644
--- a/t/app/controller/questionnaire.t
+++ b/t/app/controller/questionnaire.t
@@ -276,7 +276,7 @@ foreach my $test (
$questionnaire->discard_changes;
is $report->state, $result eq 'unknown' ? $test->{problem_state} : $result;
is $report->send_questionnaire, $another;
- ok DateTime::Format::Pg->format_datetime( $report->lastupdate) gt $report_time, 'lastupdate changed'
+ ok (DateTime::Format::Pg->format_datetime( $report->lastupdate) gt $report_time, 'lastupdate changed')
unless $test->{fields}{been_fixed} eq 'Unknown' || $test->{lastupdate_static};
is $questionnaire->old_state, $test->{problem_state};
is $questionnaire->new_state, $result;
diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t
index 02f502d31..5dbbc3bbe 100644
--- a/t/cobrand/zurich.t
+++ b/t/cobrand/zurich.t
@@ -705,8 +705,6 @@ subtest "test stats" => sub {
$mech->content_contains('fixed - council');
$mech->content_contains(',hidden,');
}
-
- $mech->log_out_ok;
};
};
@@ -764,6 +762,26 @@ subtest 'email images to external partners' => sub {
};
};
+subtest 'time_spent' => sub {
+ FixMyStreet::override_config {
+ ALLOWED_COBRANDS => [ 'zurich' ],
+ }, 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';
+ };
+};
+
+$mech->log_out_ok;
+
END {
$mech->delete_body($subdivision);
$mech->delete_body($division);
diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html
index 82bbeba23..6e952022a 100644
--- a/templates/web/zurich/admin/report_edit-sdm.html
+++ b/templates/web/zurich/admin/report_edit-sdm.html
@@ -46,6 +46,10 @@
<li><span class="mock-label">[% loc('Phone:') %]</span> [% IF problem.user.phone %][% problem.user.phone | html %][% ELSE %]<em>[% loc('None') %]</em>[% END %]</li>
<li><span class="mock-label">[% loc('Created:') %]</span> [% PROCESS format_date this_date=problem.created %] [% problem.created.hms %]</li>
+<li>
+ <label>[% loc('Time spent (in minutes):') %]</label> [% problem.get_time_spent %]
+</li>
+
[% IF problem.photo %]
<li><img alt="" src="[% c.cobrand.base_url %]/photo/[% problem.photo %].temp.jpeg"></li>
[% END %]
@@ -60,6 +64,20 @@
</ul>
+<p class="report-edit-action">
+<label for="time_spent">[% loc('Time spent (in minutes):') %]</label>
+<input type="text" name="time_spent" id="form_time_spent" style="width: 4em" value="0">
+<script>
+ $(function () {
+ $('#form_time_spent').spinner({
+ spin: function (e, ui) {
+ if (ui.value < 0) { return false }
+ }
+ });
+ });
+</script>
+</p>
+
<p class="cf">
<input style="float:left" type="submit" name="Submit changes" value="[% loc('Submit changes') %]" >
<input style="float:right" type="submit" name="no_more_updates" value="[% loc('No further updates') %]">
diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html
index d2c1760ff..89f27dcda 100644
--- a/templates/web/zurich/admin/report_edit.html
+++ b/templates/web/zurich/admin/report_edit.html
@@ -60,6 +60,9 @@
<li><span class="mock-label">[% loc('Phone:') %]</span> [% IF problem.user.phone %][% problem.user.phone | html %][% ELSE %]<em>[% loc('None') %]</em>[% END %]</li>
<li><span class="mock-label">[% loc('Created:') %]</span> [% PROCESS format_date this_date=problem.created %] [% problem.created.hms %]</li>
+<li>
+ <label>[% loc('Time spent (in minutes):') %]</label> [% problem.get_time_spent %]
+</li>
[% IF problem.photo %]
<li>
@@ -215,6 +218,20 @@ Ihre Stadt Zürich
[% END %]
+<p>
+<label for="time_spent">[% loc('Time spent (in minutes):') %]</label>
+<input type="text" name="time_spent" id="form_time_spent" style="width: 4em" value="0">
+<script>
+ $(function () {
+ $('#form_time_spent').spinner({
+ spin: function (e, ui) {
+ if (ui.value < 0) { return false }
+ }
+ });
+ });
+</script>
+</p>
+
<p align="right">
[% IF problem.state == 'planned' %]
<input type="submit" name="publish_response" value="[% loc('Publish the response') %]">
diff --git a/web/cobrands/zurich/base.scss b/web/cobrands/zurich/base.scss
index 10eed0b11..013c071bd 100644
--- a/web/cobrands/zurich/base.scss
+++ b/web/cobrands/zurich/base.scss
@@ -179,6 +179,13 @@ h4.static-with-rule {
}
}
+.ui-spinner input {
+ // stop jQuery UI spinner inputs from inheriting FMS input styles
+ padding: 1px;
+ border: none;
+ border-radius: 0;
+}
+
@media print {
#site-header .container {
position: relative;