diff options
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Report.pm | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 207 | ||||
-rw-r--r-- | t/cobrand/zurich.t | 208 | ||||
-rw-r--r-- | templates/web/zurich/admin/header.html | 6 | ||||
-rw-r--r-- | templates/web/zurich/admin/problem_row.html | 4 | ||||
-rw-r--r-- | templates/web/zurich/admin/report_edit-sdm.html | 6 | ||||
-rw-r--r-- | templates/web/zurich/admin/report_edit.html | 47 | ||||
-rw-r--r-- | templates/web/zurich/admin/response_templates_select.html | 2 |
8 files changed, 308 insertions, 175 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Report.pm b/perllib/FixMyStreet/App/Controller/Report.pm index 3aaa3e201..d7cae05d4 100644 --- a/perllib/FixMyStreet/App/Controller/Report.pm +++ b/perllib/FixMyStreet/App/Controller/Report.pm @@ -112,7 +112,8 @@ sub load_problem_or_display_error : Private { $c->detach( '/page_error_404_not_found', [ _('Unknown problem ID') ] ) unless $c->cobrand->show_unconfirmed_reports ; } - elsif ( $problem->hidden_states->{ $problem->state } ) { + elsif ( $problem->hidden_states->{ $problem->state } or + (($problem->get_extra_metadata('closure_status')||'') eq 'hidden')) { $c->detach( '/page_error_410_gone', [ _('That report has been removed from FixMyStreet.') ] # diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 3f57ecf5a..1a9963a60 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -108,8 +108,11 @@ sub prettify_dt { sub zurich_closed_states { my $states = { 'fixed - council' => 1, - 'closed' => 1, + 'closed' => 1, # extern 'hidden' => 1, + 'investigating' => 1, # wish + 'unable to fix' => 1, # jurisdiction unknown + 'partial' => 1, # not contactable }; return wantarray ? keys %{ $states } : $states; @@ -525,6 +528,7 @@ sub admin_report_edit { } } + # Problem updates upon submission if ( ($type eq 'super' || $type eq 'dm') && $c->get_param('submit') ) { $problem->set_extra_metadata('publish_photo' => $c->get_param('publish_photo') || 0 ); @@ -564,6 +568,17 @@ sub admin_report_edit { my $redirect = 0; my $new_cat = $c->get_param('category') || ''; my $state = $c->get_param('state') || ''; + my $oldstate = $problem->state; + + my %closure_states = ( + 'closed' => 1, + 'investigating' => 1, + 'hidden' => 1, + 'partial' => 1, + 'unable to fix' => 1, + ); + + my $old_closure_state = $problem->get_extra_metadata('closure_status'); if ( ($state eq 'confirmed') @@ -580,6 +595,23 @@ sub admin_report_edit { $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 ( $closure_states{$state} and + ( $oldstate ne 'planned' ) + || (($old_closure_state ||'') ne $state)) + { + # for these states + # - closed (Extern) + # - investigating (Wish) + # - hidden + # - partial (Not contactable) + # - unable to fix (Jurisdiction unknown) + # we divert to planned (Rueckmeldung ausstehend) and set closure_status to the requested state + # From here, the DM can reply to the user, triggering the setting of problem to correct state + $problem->set_extra_metadata( closure_status => $state ); + $self->set_problem_state($c, $problem, 'planned'); + $state = 'planned'; + $redirect = 1; + } elsif ( my $subdiv = $c->get_param('body_subdivision') ) { $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); $self->set_problem_state($c, $problem, 'in progress'); @@ -587,55 +619,75 @@ sub admin_report_edit { $problem->bodies_str( $subdiv ); $problem->whensent( undef ); $redirect = 1; - } elsif ( my $external = $c->get_param('body_external') and $state =~/^(closed|investigating)$/) { - # Extern | Wish - my $external_body = $c->model('DB::Body')->find($external) - or die "Body $external not found"; - $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); - $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); - $problem->external_body( $external ); - $problem->whensent( undef ); - $self->set_problem_state($c, $problem, $state); - if ( my $external_message = $c->req->params->{external_message} ) { - $problem->add_to_comments( { - text => ( - sprintf '(%s %s) %s', - $state eq 'closed' ? - _('Forwarded to external body') : - _('Forwarded wish to external body'), - $external_body->name, - $external_message, - ), - user => $c->user->obj, - state => 'hidden', # seems best fit, should not be shown publicly - mark_fixed => 0, - anonymous => 1, - extra => { is_internal_note => 1, is_external_message => 1 }, - } ); - # set the external_message in extra, so that it will be picked up - # later by send-reports - $problem->set_extra_metadata( external_message => $external_message ); - } - my $template = ($state eq 'investigating') ? 'problem-wish.txt' : 'problem-external.txt'; - _admin_send_email( $c, $template, $problem ); - $redirect = 1; } else { if ($state) { - if ($problem->state eq 'unconfirmed' and $state ne 'unconfirmed') { + if ($oldstate eq 'unconfirmed' and $state ne 'unconfirmed') { # only set this for the first state change $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); } - $self->set_problem_state($c, $problem, $state); + $self->set_problem_state($c, $problem, $state) + unless $closure_states{$state}; # in closure-states case, we'll defer to clause below if ($self->problem_is_closed($problem)) { $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); + $c->stash->{problem_is_closed} = 1; } - if ( $state eq 'hidden' && $c->get_param('send_rejected_email') ) { - _admin_send_email( $c, 'problem-rejected.txt', $problem ); + } + } + + if ($problem->state eq 'planned') { + # Rueckmeldung ausstehend + # override $state from the metadata set above + $state = $problem->get_extra_metadata('closure_status') || ''; + my $closed = 0; + + if ($state eq 'hidden' && $c->req->params->{publish_response} ) { + _admin_send_email( $c, 'problem-rejected.txt', $problem ); + $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); + $self->set_problem_state($c, $problem, $state); + $closed++; + } + elsif ($state =~/^(closed|investigating)$/) { # Extern | Wish + # Nested if instead of `and` because in these cases, we *don't* + # want to close unless we have body_external (so we don't want + # the final elsif clause below to kick in on publish_response) + if (my $external = $c->req->params->{body_external}) { + my $external_body = $c->model('DB::Body')->find($external) + or die "Body $external not found"; + $problem->external_body( $external ); + } + if ($problem->external_body && $c->req->params->{publish_response}) { + $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); + $problem->whensent( undef ); + $self->set_problem_state($c, $problem, $state); + my $template = ($state eq 'investigating') ? 'problem-wish.txt' : 'problem-external.txt'; + _admin_send_email( $c, $template, $problem ); + $redirect = 1; + $closed++; } + # else should really return a message here + } + elsif ($c->req->params->{publish_response}) { + # otherwise we only set the state if publish_response is set + + # if $state wasn't set, then we are simply closing the message as fixed + $state ||= 'fixed - council'; + _admin_send_email( $c, 'problem-closed.txt', $problem ); + $redirect = 1; + $closed++; } + + if ($closed) { + # set to either the closure_status from metadata or 'fixed - council' as above + $self->set_problem_state($c, $problem, $state); + $problem->set_extra_metadata_if_undefined( closed_overdue => $self->overdue( $problem ) ); + $problem->unset_extra_metadata('closure_status'); + } + } + else { + $problem->unset_extra_metadata('closure_status'); } $problem->title( $c->get_param('title') ) if $c->get_param('title'); @@ -643,16 +695,40 @@ sub admin_report_edit { $problem->latitude( $c->get_param('latitude') ); $problem->longitude( $c->get_param('longitude') ); - # Final, public, Update from DM - if (my $update = $c->get_param('status_update')) { + # update the public update from DM + if (my $update = $c->req->param('status_update')) { $problem->set_extra_metadata(public_response => $update); - if ($c->get_param('publish_response')) { - $self->set_problem_state($c, $problem, 'fixed - council'); - $problem->set_extra_metadata( closed_overdue => $self->overdue( $problem ) ); - _admin_send_email( $c, 'problem-closed.txt', $problem ); - } } - $c->stash->{default_public_response} = "\nFreundliche Grüsse\n\nIhre Stadt Zürich\n"; + + # send external_message if provided and state is *now* Wish|Extern + # e.g. was already, or was set in the Rueckmeldung ausstehend clause above. + if ( my $external_message = $c->req->params->{external_message} + and $problem->state =~ /^(closed|investigating)$/) + { + my $external = $problem->external_body; + my $external_body = $c->model('DB::Body')->find($external) + or die "Body $external not found"; + + $problem->set_extra_metadata_if_undefined( moderated_overdue => $self->overdue( $problem ) ); + $problem->add_to_comments( { + text => ( + sprintf '(%s %s) %s', + $state eq 'closed' ? + _('Forwarded to external body') : + _('Forwarded wish to external body'), + $external_body->name, + $external_message, + ), + user => $c->user->obj, + state => 'hidden', # seems best fit, should not be shown publicly + mark_fixed => 0, + anonymous => 1, + extra => { is_internal_note => 1, is_external_message => 1 }, + } ); + # set the external_message in extra, so that it will be picked up + # later by send-reports + $problem->set_extra_metadata( external_message => $external_message ); + } $problem->lastupdate( \'current_timestamp' ); $problem->update; @@ -682,7 +758,7 @@ sub admin_report_edit { $self->update_admin_log($c, $problem); if ( $redirect ) { - $c->detach('index'); + $c->go('index'); } $c->stash->{updates} = [ $c->model('DB::Comment') @@ -708,8 +784,14 @@ sub admin_report_edit { my $not_contactable = $c->req->param('not_contactable'); $problem->bodies_str( $body->parent->id ); - my $new_state = $not_contactable ? 'partial' : 'confirmed'; - $self->set_problem_state($c, $problem, $new_state); + if ($not_contactable) { + # we can't directly set state, but mark the closure_status for DM to confirm. + $self->set_problem_state($c, $problem, 'planned'); + $problem->set_extra_metadata( closure_status => 'partial'); + } + else { + $self->set_problem_state($c, $problem, 'confirmed'); + } $problem->update; $c->forward( 'log_edit', [ $problem->id, 'problem', $not_contactable ? @@ -792,11 +874,6 @@ sub stash_states { unconfirmed => 1, }, { - # Rueckmeldung ausstehend - state => 'planned', - trans => _('Planned'), - }, - { # Unsichtbar (hidden) state => 'hidden', trans => _('Hidden'), @@ -824,7 +901,26 @@ sub stash_states { trans => _('Not contactable'), }, ); + my %state_trans = map { $_->{state} => $_->{trans} } @states; + my $state = $problem->state; + + # Rueckmeldung ausstehend may also indicate the status it's working towards. + push @states, do { + if ($state eq 'planned' and my $closure_status = $problem->get_extra_metadata('closure_status')) { + { + state => $closure_status, + trans => sprintf '%s (%s)', _('Planned'), $state_trans{$closure_status}, + }; + } + else { + { + state => 'planned', + trans => _('Planned'), + }; + } + }; + if ($state eq 'in progress') { push @states, { state => 'in progress', @@ -841,6 +937,11 @@ sub stash_states { @states = grep { $_->{$state} } @states; } $c->stash->{states} = \@states; + + # stash details about the public response + $c->stash->{default_public_response} = "\nFreundliche Grüsse\n\nIhre Stadt Zürich\n"; + $c->stash->{show_publish_response} = + ($problem->state eq 'planned'); } =head2 _admin_send_email diff --git a/t/cobrand/zurich.t b/t/cobrand/zurich.t index 038a2fe35..0a622cb2b 100644 --- a/t/cobrand/zurich.t +++ b/t/cobrand/zurich.t @@ -46,6 +46,7 @@ sub reset_report_state { $report->unset_extra_metadata('moderated_overdue'); $report->unset_extra_metadata('subdiv_overdue'); $report->unset_extra_metadata('closed_overdue'); + $report->unset_extra_metadata('closure_status'); $report->whensent(undef); $report->state('unconfirmed'); $report->created($created) if $created; @@ -122,7 +123,8 @@ FixMyStreet::override_config { }, sub { $mech->get_ok( '/report/' . $report->id ); }; -$mech->content_contains('Überprüfung ausstehend'); +$mech->content_contains('Überprüfung ausstehend') + or die $mech->content; # Check logging in to deal with this report FixMyStreet::override_config { @@ -215,102 +217,100 @@ sub get_moderated_count { subtest "report_edit" => sub { - reset_report_state($report); - - ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' ); - - is get_moderated_count(), 0; - FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { + + reset_report_state($report); + ok ( ! $report->get_extra_metadata('moderated_overdue'), 'Report currently unmoderated' ); + is get_moderated_count(), 0; + $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->content_contains( 'Unbestätigt' ); # Unconfirmed email $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); $report->discard_changes(); - is $report->state, 'confirmed', 'state has been updated to confirmed'; - }; - - $mech->content_contains('Aufgenommen'); - $mech->content_contains('Test Test'); - $mech->content_lacks('photo/' . $report->id . '.0.jpeg'); - $mech->email_count_is(0); - $report->discard_changes; + $mech->content_contains('Aufgenommen'); + $mech->content_contains('Test Test'); + $mech->content_lacks('photo/' . $report->id . '.0.jpeg'); + $mech->email_count_is(0); - is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' ); - is get_moderated_count(), 1; + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Report now marked moderated' ); + is get_moderated_count(), 1; - # Set state back to 10 days ago so that report is overdue - my $created = $report->created; - reset_report_state($report, $created->clone->subtract(days => 10)); + # Set state back to 10 days ago so that report is overdue + my $created = $report->created; + reset_report_state($report, $created->clone->subtract(days => 10)); - is get_moderated_count(), 0; + is get_moderated_count(), 0; - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); - }; - $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' ); - is get_moderated_count(), 0, 'Moderated count not increased when overdue'; - reset_report_state($report, $created); + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 1, 'moderated_overdue set correctly when overdue' ); + is get_moderated_count(), 0, 'Moderated count not increased when overdue'; + + reset_report_state($report, $created); - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); $mech->get_ok( '/report/' . $report->id ); - }; - $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' ); - is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' ); - is get_moderated_count(), 1; + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking confirmed sets moderated_overdue' ); + is ( $report->get_extra_metadata('closed_overdue'), undef, 'Marking confirmed does NOT set closed_overdue' ); + is get_moderated_count(), 1; - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'hidden' } } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - }; - $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' ); - is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden also set closed_overdue' ); - is get_moderated_count(), 1, 'Check still counted moderated' - or diag $report->get_column('extra'); - reset_report_state($report); + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Still marked moderated_overdue' ); + is ( $report->get_extra_metadata('closed_overdue'), undef, "Marking hidden doesn't set closed_overdue..." ); + is ( $report->state, 'planned', 'Marking hidden actually sets state to planned'); + is ( $report->get_extra_metadata('closure_status'), 'hidden', 'Marking hidden sets closure_status to hidden'); + is get_moderated_count(), 1, 'Check still counted moderated' + or diag $report->get_column('extra'); + + # publishing actually sets hidden + $mech->form_with_fields( 'status_update' ); + $mech->submit_form_ok( { button => 'publish_response' } ); + $mech->get_ok( '/admin/report_edit/' . $report->id ); + $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' ); - is get_moderated_count(), 0; + is ( $report->get_extra_metadata('closed_overdue'), 0, "Closing as hidden sets closed_overdue..." ); + is ( $report->state, 'hidden', 'Closing as hidden sets state to hidden'); + is ( $report->get_extra_metadata('closure_status'), undef, 'Closing as hidden unsets closure_status'); - # Check that setting to 'hidden' also triggers moderation - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { + + reset_report_state($report); + is ( $report->get_extra_metadata('moderated_overdue'), undef, 'Sanity check' ); + is get_moderated_count(), 0; + + # Check that setting to 'hidden' also triggers moderation $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'hidden' } } ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - }; - $report->discard_changes; - is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' ); - is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' ); - is get_moderated_count(), 1; + $mech->form_with_fields( 'status_update' ); + $mech->submit_form_ok( { button => 'publish_response' } ); + + $report->discard_changes; + is ( $report->get_extra_metadata('moderated_overdue'), 0, 'Marking hidden from scratch sets moderated_overdue' ); + is ( $report->get_extra_metadata('closed_overdue'), 0, 'Marking hidden from scratch also set closed_overdue' ); + is get_moderated_count(), 1; - is ($cobrand->get_or_check_overdue($report), 0, 'sanity check'); - $report->update({ created => $created->clone->subtract(days => 10) }); - is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased'); + is ($cobrand->get_or_check_overdue($report), 0, 'sanity check'); + $report->update({ created => $created->clone->subtract(days => 10) }); + is ($cobrand->get_or_check_overdue($report), 0, 'overdue call not increased'); - reset_report_state($report, $created); + reset_report_state($report, $created); + } }; FixMyStreet::override_config { @@ -335,7 +335,7 @@ FixMyStreet::override_config { $mech->content_contains( 'Originaltext: “Test Test 1 for ' . $division->id . ' Detail”' ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { body_subdivision => $subdivision->id, send_rejected_email => 1 } } ); + $mech->submit_form_ok( { with_fields => { body_subdivision => $subdivision->id } } ); $mech->get_ok( '/report/' . $report->id ); $mech->content_contains('In Bearbeitung'); @@ -421,13 +421,12 @@ subtest 'SDM' => sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { button => 'not_contactable', form_number => 2 } ); $report->discard_changes; - is $report->state, 'partial', 'Report sent back to partial (not_contactable) state'; + is $report->state, 'planned', 'Report sent back to Rueckmeldung ausstehend state'; + is $report->get_extra_metadata('closure_status'), 'partial', 'Report sent back to partial (not_contactable) state'; is $report->bodies_str, $division->id, 'Report sent back to division'; }; }; - $report->update({ state => 'planned' }); - $mech->log_out_ok; }; @@ -438,6 +437,9 @@ FixMyStreet::override_config { $mech->get_ok( '/admin' ); }; +reset_report_state($report); +$report->update({ state => 'planned' }); + $mech->content_contains( 'report_edit/' . $report->id ); $mech->content_contains( DateTime->now->strftime("%d.%m.%Y") ); @@ -466,7 +468,7 @@ like $email->header('From'), qr/division\@example.org/, 'from line looks correct like $email->body, qr/FINAL UPDATE/, 'body looks correct'; $mech->clear_emails_ok; -# Assign directly to planned, don't confirm email +# Assign planned (via confirmed), don't confirm email @reports = $mech->create_problems_for_body( 1, $division->id, 'Second', { state => 'unconfirmed', confirmed => undef, @@ -479,6 +481,8 @@ FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->submit_form_ok( { with_fields => { state => 'confirmed' } } ); + $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->submit_form_ok( { with_fields => { state => 'planned' } } ); $mech->get_ok( '/report/' . $report->id ); }; @@ -490,6 +494,8 @@ FixMyStreet::override_config { }, sub { $mech->get_ok( '/admin/report_edit/' . $report->id ); $mech->content_contains( 'Unbestätigt' ); + $report->discard_changes; + $mech->form_with_fields( 'status_update' ); $mech->submit_form_ok( { button => 'publish_response', with_fields => { status_update => 'FINAL UPDATE' } } ); $mech->get_ok( '/report/' . $report->id ); @@ -515,18 +521,28 @@ subtest "external report triggers email" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { + + # required to see body_external field + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'closed'); # Set the public_response manually here because the default one will have line breaks that get escaped as HTML, causing the comparison to fail. $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); - $report->update({ state => 'closed' }); # required to see body_external field + $report->update; + $mech->get_ok( '/admin/report_edit/' . $report->id ); + $mech->form_with_fields( 'publish_response' ); $mech->submit_form_ok( { + button => 'publish_response', with_fields => { body_external => $external_body->id, external_message => $EXTERNAL_MESSAGE, } }); + $report->discard_changes; $mech->get_ok( '/report/' . $report->id ); }; - $mech->content_contains('Extern'); + is ($report->state, 'closed', 'Report was closed correctly'); + $mech->content_contains('Extern') + or die $mech->content; $mech->content_contains('Third Test'); $mech->content_contains($report->get_extra_metadata('public_response')) or die $mech->content; send_reports_for_zurich(); @@ -543,13 +559,24 @@ subtest "external report triggers email" => sub { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { $mech->get_ok( '/admin' ); - $report->update({ state => 'closed' }); # required to see body_external field + # required to see body_external field + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'closed'); + $report->set_extra_metadata('public_response' => 'Freundliche Gruesse Ihre Stadt Zuerich'); + $report->update; + is $mech->uri->path, '/admin', "am logged in"; $mech->content_contains( 'report_edit/' . $report->id ); $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { body_external => $external_body->id, third_personal => 1 } } ); - $mech->get_ok( '/report/' . $report->id ); - }; + $mech->form_with_fields( 'publish_response' ); + $mech->submit_form_ok( { + button => 'publish_response', + with_fields => { + body_external => $external_body->id, + third_personal => 1, + } }); + $mech->get_ok( '/report/' . $report->id ); + }; $mech->content_contains('Extern'); $mech->content_contains('Third Test'); $mech->content_contains($report->get_extra_metadata('public_response')); @@ -566,9 +593,18 @@ subtest "external report triggers email" => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'zurich' ], }, sub { - $report->update({ state => 'investigating' }); # Wish + # set as wish + $report->discard_changes; + $report->state('planned'); + $report->set_extra_metadata('closure_status' => 'investigating'); + $report->update; + is ($report->state, 'planned', 'Sanity check') or die; + $mech->get_ok( '/admin/report_edit/' . $report->id ); + + $mech->form_with_fields( 'publish_response' ); $mech->submit_form_ok( { + button => 'publish_response', with_fields => { body_external => $external_body->id, external_message => $EXTERNAL_MESSAGE, @@ -702,25 +738,6 @@ subtest "problems can't be assigned to deleted bodies" => sub { $mech->log_out_ok; }; -subtest "hidden report email are only sent when requested" => sub { - $user = $mech->log_in_ok( 'dm1@example.org') ; - $report->set_extra_metadata(email_confirmed => 1); - $report->update; - FixMyStreet::override_config { - ALLOWED_COBRANDS => [ 'zurich' ], - }, sub { - $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { state => 'hidden', send_rejected_email => 1 } } ); - $mech->email_count_is(1); - $mech->clear_emails_ok; - $mech->get_ok( '/admin/report_edit/' . $report->id ); - $mech->submit_form_ok( { with_fields => { state => 'hidden', send_rejected_email => undef } } ); - $mech->email_count_is(0); - $mech->clear_emails_ok; - $mech->log_out_ok; - }; -}; - subtest "photo must be supplied for categories that require it" => sub { FixMyStreet::App->model('DB::Contact')->find_or_create({ body => $division, @@ -774,7 +791,6 @@ subtest "test stats" => sub { if (defined $export_count) { is $export_count - $EXISTING_REPORT_COUNT, 3, 'Correct number of reports'; $mech->content_contains('fixed - council'); - $mech->content_contains(',hidden,'); } }; }; @@ -788,8 +804,8 @@ subtest "test admin_log" => sub { # XXX: following is dependent on all of test up till now, rewrite to explicitly # test which things need to be logged! - is scalar @entries, 1, 'State changes logged'; - is $entries[-1]->action, 'state change to hidden', 'State change logged as expected'; + is scalar @entries, 3, 'State changes logged'; + is $entries[-1]->action, 'state change to investigating', 'State change logged as expected'; }; subtest 'email images to external partners' => sub { diff --git a/templates/web/zurich/admin/header.html b/templates/web/zurich/admin/header.html index 1cbcfd233..929df8352 100644 --- a/templates/web/zurich/admin/header.html +++ b/templates/web/zurich/admin/header.html @@ -9,7 +9,11 @@ 'planned' = loc('Planned'), 'fixed - council' = loc('Closed'), 'hidden' = loc('Hidden'), - 'closed' = loc('Closed'), + 'closed' = loc('Extern'), + 'partial' = loc('Not contactable'), + 'investigating' = loc('Wish'), + 'unable to fix' = loc('Jurisdiction unknown'), + 'fixed - council' = loc('Closed'), } %] <style type="text/css"> diff --git a/templates/web/zurich/admin/problem_row.html b/templates/web/zurich/admin/problem_row.html index 123ff5469..baa8d3ac7 100644 --- a/templates/web/zurich/admin/problem_row.html +++ b/templates/web/zurich/admin/problem_row.html @@ -18,7 +18,9 @@ <td>[% PROCESS value_or_nbsp value=problem.category %]</td> <td>[% PROCESS format_date this_date=problem.created %]</td> <td>[% PROCESS format_date this_date=problem.lastupdate %]</td> - <td>[% states.${problem.state} %]</td> + <td> [% states.${problem.state} %][% IF problem.state == 'planned'; + SET cs=problem.get_extra_metadata('closure_status'); + IF cs %] ([% states.$cs %]) [% END; END %]</td> [% IF include_subdiv %] <td> diff --git a/templates/web/zurich/admin/report_edit-sdm.html b/templates/web/zurich/admin/report_edit-sdm.html index e41fb6060..98092815c 100644 --- a/templates/web/zurich/admin/report_edit-sdm.html +++ b/templates/web/zurich/admin/report_edit-sdm.html @@ -67,7 +67,11 @@ </li> [% IF problem.photo %] -<li><img alt="" src="[% c.cobrand.base_url %]/photo/[% problem.photo %].temp.jpeg"></li> +[% FOR photo IN problem.get_photoset(c).images %] +<li> + <img alt="Photo of this report" src="[% c.cobrand.base_url %]/photo/[% photo.0 %].temp.jpeg"> +</li> +[% END %] [% END %] </ul> diff --git a/templates/web/zurich/admin/report_edit.html b/templates/web/zurich/admin/report_edit.html index b788c139c..95aa5d311 100644 --- a/templates/web/zurich/admin/report_edit.html +++ b/templates/web/zurich/admin/report_edit.html @@ -10,6 +10,8 @@ [% map_html %] </div> +[% pstate = problem.get_extra_metadata('closure_status') || problem.state %] + [% status_message %] <form method="post" action="[% c.uri_for( 'report_edit', problem.id ) %]" enctype="application/x-www-form-urlencoded" accept-charset="utf-8"> @@ -23,7 +25,7 @@ <li class="report-edit-action">» <a href="http://webgis.intra.stzh.ch/AV_Online/Direct.asp?Map=AV&Search=Koord&West=[% problem.local_coords.0 %]&Nord=[% problem.local_coords.1 %]&B=300" target="_blank">Standort in AV-Online anzeigen</a></li> -[% IF problem.state == 'fixed - council' OR problem.state == 'closed' %] +[% IF problem_is_closed %] <li><span class="mock-label">[% loc('Details:') %]</span> [% problem.detail | html %] [% IF problem.extra.original_detail %] <br>[% @@ -134,19 +136,14 @@ <p><span class="mock-label">[% loc('State:') %]</span> <select name="state" id="state"> <option value="">--</option> [% FOREACH s IN states %] - <option [% 'selected ' IF s.state == problem.state %] value="[% s.state %]">[% s.trans %]</option> + <option [% 'selected ' IF s.state == pstate %] value="[% s.state %]">[% s.trans %]</option> [% END %] </select></p> -<p id="automatic-reply" class="report-edit-action"> - <span class="mock-label">Automatische Antwort</span> - <input type="checkbox" name="send_rejected_email" id="send_rejected_email" value="1" /> -</p> - <script type="text/javascript"> $(function(){ - $('.assignation select').change(function(){ + $('.assignation__select').change(function(){ if (this.value == "") { $('.assignation').css('color', '#000'); } else { @@ -159,11 +156,6 @@ $(function(){ $('#state').change(function(){ // Show or hide the automatic reply field var state = $(this).val(); - if (state === 'hidden') { - $('#automatic-reply').show(); - } else { - $('#automatic-reply').hide(); - } // Show or hide the categories if (state === 'confirmed') { @@ -183,6 +175,19 @@ $(function(){ $('#assignation__external').hide(); } + // disable the templates, public_response, publish if we've selected a + // different state to the one we started on + if ((state === '[% pstate %]')) { + $('input[name=publish_response]').show(); + $('.response_templates_select').show(); + $('#status_update').show(); + } + else { + $('input[name=publish_response]').hide(); + $('.response_templates_select').hide(); + $('#status_update').hide(); + } + }).change(); }); </script> @@ -196,7 +201,7 @@ $(function(){ <div id="assignation__category"> [% loc('Assign to different category:') %]</label> - <select name="category" id="category"> + <select name="category" id="category" class="assignation__select"> <option value="">--</option> [% FOREACH cat IN categories %] <option value="[% cat %]">[% cat %]</option> @@ -212,7 +217,7 @@ $(function(){ [% IF admin_type != 'super' AND list %] <li class="assignation report-edit-action" id="assignation__subdivision"> <label for="body_subdivision">[% loc('Assign to subdivision:') %]</label> - <select name="body_subdivision" id="body_subdivision"> + <select name="body_subdivision" id="body_subdivision" class="assignation__select"> <option value="">--</option> [% list %] </select> @@ -222,12 +227,12 @@ $(function(){ [% END %] [%# 3rd party messages sent for Extern/Wunsch states %] -[% SWITCH problem.state %] +[% SWITCH pstate %] [% CASE ['closed','investigating'] %] <ul class="no-bullets"> <li class="assignation report-edit-action" id="assignation__external"> <label for="body_external"> - [% IF problem.state == 'closed' %] + [% IF pstate == 'closed' %] [% loc('Assign to external body:') %] [% ELSE %] [% loc('Assign to competent body:') %] @@ -241,19 +246,19 @@ $(function(){ [% END %] </select> <br> - [% IF problem.state == 'closed' %] + [% IF pstate == 'closed' %] <input type="checkbox" name="third_personal" id="third_personal" value="1"[% ' checked' IF problem.extra.third_personal %]> <label for="third_personal" class="inline">[% loc('Include reporter personal details') %]</label> [% END %] [% INCLUDE 'admin/response_templates_select.html' for='external_body' %] - <textarea name='external_message' id='external_body' cols=60 rows=5></textarea> + <textarea name='external_message' id='external_body' cols=60 rows=5>[% problem.get_extra_metadata('external_message') | html %]</textarea> </li> </ul> [% END %] [%# Public response field shown for Ruckmeldung ausstehend/Extern/ # Zustandigkeit unbekannt/Wunsch/Nicht kontaktierbar/Unsichtbar %] -[% SWITCH problem.state %] +[% SWITCH pstate %] [% CASE ['planned','closed','unable to fix','investigating','partial','hidden'] %] <ul class="no-bullets report-edit-action"> <li><label for="status_update">[% loc('Public response:') %]</label> @@ -266,7 +271,7 @@ $(function(){ [% END %] <p align="right" class="report-edit-action"> -[% IF problem.state == 'planned' %] +[% IF show_publish_response %] <input type="submit" name="publish_response" value="[% loc('Publish the response') %]"> [% END %] <input type="submit" name="Submit changes" value="[% loc('Submit changes') %]" > diff --git a/templates/web/zurich/admin/response_templates_select.html b/templates/web/zurich/admin/response_templates_select.html index a16032790..4ae517578 100644 --- a/templates/web/zurich/admin/response_templates_select.html +++ b/templates/web/zurich/admin/response_templates_select.html @@ -8,7 +8,7 @@ <option value="[% t.id %]"> [% t.title | html %] </option> [% END %] </select> -</p> +</div> <script> $(function () { var response_template_texts = { |