diff options
-rw-r--r-- | CHANGELOG.md | 3 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin.pm | 49 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin/Bodies.pm | 5 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Admin/Stats.pm | 46 | ||||
-rwxr-xr-x | perllib/FixMyStreet/App/Controller/Status.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/UKCouncils.pm | 2 | ||||
-rw-r--r-- | perllib/FixMyStreet/DB/ResultSet/Problem.pm | 9 | ||||
-rw-r--r-- | perllib/Open311/PopulateServiceList.pm | 5 | ||||
-rwxr-xr-x | script/bootstrap | 14 | ||||
-rw-r--r-- | t/app/controller/admin.t | 10 | ||||
-rw-r--r-- | t/app/controller/admin/bodies.t | 11 | ||||
-rw-r--r-- | t/app/controller/report_new_staff.t | 8 | ||||
-rw-r--r-- | t/open311/populate-service-list.t | 46 | ||||
-rw-r--r-- | templates/web/base/admin/bodies/contact-form.html | 7 | ||||
-rw-r--r-- | templates/web/base/admin/index.html | 9 | ||||
-rw-r--r-- | templates/web/base/admin/stats/index.html | 8 | ||||
-rw-r--r-- | templates/web/base/report/new/form_user_loggedin.html | 4 | ||||
-rw-r--r-- | templates/web/base/status/stats.html | 2 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/fixmystreet.js | 2 |
19 files changed, 168 insertions, 74 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b74a669..3fb3a88ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ * Unreleased - Admin improvements: - order unsent reports by confirmed date + - Disable staff private tickbox on new reports if category is private. #2961 + - Move stats from main admin index to stats index. - Bugfixes - Application user in Docker container can't install packages. #2914 - Look at all categories when sending reports. @@ -15,6 +17,7 @@ - Add fetch script that does combined job of fetch-comments and fetch-reports. - Open311 improvements: - match response templates on external status code over state + - Add flag to protect category/group names from Open311 overwrite. - UK: - Added junction lookup, so you can search for things like "M60, Junction 2" diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm index f3d1b2e63..038cba9e5 100644 --- a/perllib/FixMyStreet/App/Controller/Admin.pm +++ b/perllib/FixMyStreet/App/Controller/Admin.pm @@ -61,12 +61,15 @@ Displays some summary information for the requests. sub index : Path : Args(0) { my ( $self, $c ) = @_; - if ($c->cobrand->moniker eq 'zurich' && $c->stash->{admin_type} ne 'super') { - return $c->cobrand->admin(); + if ($c->cobrand->moniker eq 'zurich') { + if ($c->stash->{admin_type} eq 'super') { + $c->forward('/admin/stats/gather'); + return 1; + } else { + return $c->cobrand->admin(); + } } - $c->forward('/admin/stats/state'); - my @unsent = $c->cobrand->problems->search( { state => [ FixMyStreet::DB::Result::Problem::open_states() ], whensent => undef, @@ -79,44 +82,6 @@ sub index : Path : Args(0) { } )->all; $c->stash->{unsent_reports} = \@unsent; - my $alerts = $c->model('DB::Alert')->summary_report_alerts( $c->cobrand->restriction ); - - my %alert_counts = - map { $_->confirmed => $_->get_column('confirmed_count') } $alerts->all; - - $alert_counts{0} ||= 0; - $alert_counts{1} ||= 0; - - $c->stash->{alerts} = \%alert_counts; - - my $contacts = $c->model('DB::Contact')->summary_count(); - - my %contact_counts = - map { $_->state => $_->get_column('state_count') } $contacts->all; - - $contact_counts{confirmed} ||= 0; - $contact_counts{unconfirmed} ||= 0; - $contact_counts{total} = $contact_counts{confirmed} + $contact_counts{unconfirmed}; - - $c->stash->{contacts} = \%contact_counts; - - my $questionnaires = $c->model('DB::Questionnaire')->summary_count( $c->cobrand->restriction ); - - my %questionnaire_counts = map { - $_->get_column('answered') => $_->get_column('questionnaire_count') - } $questionnaires->all; - $questionnaire_counts{1} ||= 0; - $questionnaire_counts{0} ||= 0; - - $questionnaire_counts{total} = - $questionnaire_counts{0} + $questionnaire_counts{1}; - $c->stash->{questionnaires_pc} = - $questionnaire_counts{total} - ? sprintf( '%.1f', - $questionnaire_counts{1} / $questionnaire_counts{total} * 100 ) - : _('n/a'); - $c->stash->{questionnaires} = \%questionnaire_counts; - $c->forward('fetch_all_bodies'); return 1; diff --git a/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm b/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm index 4bfca21ae..6ae068cd9 100644 --- a/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm +++ b/perllib/FixMyStreet/App/Controller/Admin/Bodies.pm @@ -272,6 +272,11 @@ sub update_contact : Private { } else { $contact->unset_extra_metadata( 'photo_required' ); } + if ( $c->get_param('open311_protect') ) { + $contact->set_extra_metadata( open311_protect => 1 ); + } else { + $contact->unset_extra_metadata( 'open311_protect' ); + } if ( my @group = $c->get_param_list('group') ) { @group = grep { $_ } @group; if (scalar @group == 0) { diff --git a/perllib/FixMyStreet/App/Controller/Admin/Stats.pm b/perllib/FixMyStreet/App/Controller/Admin/Stats.pm index 5f82094d6..03b529a55 100644 --- a/perllib/FixMyStreet/App/Controller/Admin/Stats.pm +++ b/perllib/FixMyStreet/App/Controller/Admin/Stats.pm @@ -7,6 +7,52 @@ BEGIN { extends 'Catalyst::Controller'; } sub index : Path : Args(0) { my ( $self, $c ) = @_; return $c->cobrand->admin_stats() if $c->cobrand->moniker eq 'zurich'; + $c->forward('gather'); +} + +sub gather : Private { + my ($self, $c) = @_; + + $c->forward('state'); # Problem/update stats used on that page + $c->forward('/admin/fetch_all_bodies'); # For body stat + + my $alerts = $c->model('DB::Alert')->summary_report_alerts( $c->cobrand->restriction ); + + my %alert_counts = + map { $_->confirmed => $_->get_column('confirmed_count') } $alerts->all; + + $alert_counts{0} ||= 0; + $alert_counts{1} ||= 0; + + $c->stash->{alerts} = \%alert_counts; + + my $contacts = $c->model('DB::Contact')->summary_count(); + + my %contact_counts = + map { $_->state => $_->get_column('state_count') } $contacts->all; + + $contact_counts{confirmed} ||= 0; + $contact_counts{unconfirmed} ||= 0; + $contact_counts{total} = $contact_counts{confirmed} + $contact_counts{unconfirmed}; + + $c->stash->{contacts} = \%contact_counts; + + my $questionnaires = $c->model('DB::Questionnaire')->summary_count( $c->cobrand->restriction ); + + my %questionnaire_counts = map { + $_->get_column('answered') => $_->get_column('questionnaire_count') + } $questionnaires->all; + $questionnaire_counts{1} ||= 0; + $questionnaire_counts{0} ||= 0; + + $questionnaire_counts{total} = + $questionnaire_counts{0} + $questionnaire_counts{1}; + $c->stash->{questionnaires_pc} = + $questionnaire_counts{total} + ? sprintf( '%.1f', + $questionnaire_counts{1} / $questionnaire_counts{total} * 100 ) + : _('n/a'); + $c->stash->{questionnaires} = \%questionnaire_counts; } sub state : Local : Args(0) { diff --git a/perllib/FixMyStreet/App/Controller/Status.pm b/perllib/FixMyStreet/App/Controller/Status.pm index 57c8f362e..e56a7930a 100755 --- a/perllib/FixMyStreet/App/Controller/Status.pm +++ b/perllib/FixMyStreet/App/Controller/Status.pm @@ -31,7 +31,7 @@ sub index : Path : Args(0) { # superusers. It doesn't have anything sensitive $c->stash->{admin_type} = 'super'; # Fetch summary stats from admin front page - $c->forward('/admin/index'); + $c->forward('/admin/stats/gather'); # Fetch git version $c->forward('/admin/config_page'); diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm index 290f46d9e..21dd2d455 100644 --- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm +++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm @@ -279,6 +279,8 @@ sub admin_allow_user { return $user->from_body->areas->{$self->council_area_id}; } +sub admin_show_creation_graph { 0 } + sub available_permissions { my $self = shift; diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm index 5b2079831..3e48170d8 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm @@ -241,12 +241,9 @@ sub unique_users { return $rs->search( { state => [ FixMyStreet::DB::Result::Problem->visible_states() ], }, { - select => [ { distinct => 'user_id' } ], - as => [ 'user_id' ] - } )->as_subselect_rs->search( undef, { - select => [ { count => 'user_id' } ], - as => [ 'count' ] - } )->first->get_column('count'); + columns => [ 'user_id' ], + distinct => 1, + } ); } sub categories_summary { diff --git a/perllib/Open311/PopulateServiceList.pm b/perllib/Open311/PopulateServiceList.pm index eb1d76da4..9be17946e 100644 --- a/perllib/Open311/PopulateServiceList.pm +++ b/perllib/Open311/PopulateServiceList.pm @@ -143,6 +143,7 @@ sub _handle_existing_contact { my ( $self, $contact ) = @_; my $service_name = $self->_normalize_service_name; + my $protected = $contact->get_extra_metadata("open311_protect"); print $self->_current_body->id . " already has a contact for service code " . $self->_current_service->{service_code} . "\n" if $self->verbose >= 2; @@ -150,7 +151,7 @@ sub _handle_existing_contact { eval { $contact->update( { - category => $service_name, + $protected ? () : (category => $service_name), email => $self->_current_service->{service_code}, state => 'confirmed', %{ $self->_action_params("undeleted") }, @@ -178,7 +179,7 @@ sub _handle_existing_contact { $contact->update; } - $self->_set_contact_group($contact); + $self->_set_contact_group($contact) unless $protected; $self->_set_contact_non_public($contact); push @{ $self->found_contacts }, $self->_current_service->{service_code}; diff --git a/script/bootstrap b/script/bootstrap index 10dc94bdf..f40e97b18 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -5,16 +5,16 @@ cd "$(dirname "$0")/.." git submodule --quiet update --init --recursive --rebase -# Let's see if we can't work out where we might be running. -if cut -d/ -f2 /proc/self/cgroup | sort -u | grep -q docker ; then - if [ -z ${SKIP_PACKAGES_INSTALL:+x} ] ; then +if [ -z ${SKIP_PACKAGES_INSTALL:+x} ] ; then + # Let's see if we can't work out where we might be running. + if cut -d/ -f2 /proc/self/cgroup | sort -u | grep -q docker ; then echo "==> Installing Docker packages..." sudo bin/install_packages docker + else + # Fallback + echo "==> Installing generic packages..." + sudo bin/install_packages generic fi -else - # Fallback - echo "==> Installing generic packages..." - sudo bin/install_packages generic fi bin/install_perl_modules diff --git a/t/app/controller/admin.t b/t/app/controller/admin.t index b170633fc..5607f2dc3 100644 --- a/t/app/controller/admin.t +++ b/t/app/controller/admin.t @@ -84,10 +84,10 @@ subtest 'check summary counts' => sub { FixMyStreet::override_config { ALLOWED_COBRANDS => [ 'fixmystreet' ], }, sub { - $mech->get_ok('/admin'); + $mech->get_ok('/admin/stats'); }; - $mech->title_like(qr/Summary/); + $mech->title_like(qr/Stats/); $mech->content_contains( "$problem_count</strong> live problems" ); $mech->content_contains( "$a_count confirmed alerts" ); @@ -102,8 +102,8 @@ subtest 'check summary counts' => sub { }, sub { ok $mech->host('oxfordshire.fixmystreet.com'); - $mech->get_ok('/admin'); - $mech->title_like(qr/Summary/); + $mech->get_ok('/admin/stats'); + $mech->title_like(qr/Stats/); my ($num_live) = $mech->content =~ /(\d+)<\/strong> live problems/; my ($num_alerts) = $mech->content =~ /(\d+) confirmed alerts/; @@ -116,7 +116,7 @@ subtest 'check summary counts' => sub { $alert->cobrand('oxfordshire'); $alert->update; - $mech->get_ok('/admin'); + $mech->get_ok('/admin/stats'); $mech->content_contains( ($num_live+1) . "</strong> live problems" ); $mech->content_contains( ($num_alerts+1) . " confirmed alerts" ); diff --git a/t/app/controller/admin/bodies.t b/t/app/controller/admin/bodies.t index 340351473..c73a90da1 100644 --- a/t/app/controller/admin/bodies.t +++ b/t/app/controller/admin/bodies.t @@ -250,6 +250,17 @@ subtest 'disable form message editing' => sub { }], 'right message added'; }; +subtest 'open311 protection editing' => sub { + $mech->get_ok('/admin/body/' . $body->id . '/test%20category'); + $mech->submit_form_ok( { with_fields => { + open311_protect => 1, + note => 'Protected from Open311 changes', + } } ); + $mech->content_contains('Values updated'); + my $contact = $body->contacts->find({ category => 'test category' }); + is $contact->get_extra_metadata('open311_protect'), 1, 'Open311 protect flag set'; +}; + }; # END of override wrap diff --git a/t/app/controller/report_new_staff.t b/t/app/controller/report_new_staff.t index 422b154ed..3817cdf3a 100644 --- a/t/app/controller/report_new_staff.t +++ b/t/app/controller/report_new_staff.t @@ -45,6 +45,14 @@ subtest "report_mark_private allows users to mark reports as private" => sub { "follow 'skip this step' link" ); + my $edin_cats = $mech->create_contact_ok( body_id => $body_ids{2651}, category => 'Cats', email => 'cats@example.com', non_public => 1 ); + $mech->submit_form_ok({ + button => 'submit_category_part_only', + with_fields => { category => 'Cats' } + }); + $mech->content_contains('id="form_non_public" value="1" checked disabled'); + $edin_cats->delete; + $mech->submit_form_ok( { with_fields => { diff --git a/t/open311/populate-service-list.t b/t/open311/populate-service-list.t index 59f8b7b65..bd837f203 100644 --- a/t/open311/populate-service-list.t +++ b/t/open311/populate-service-list.t @@ -349,6 +349,52 @@ subtest 'check new category marked non_public' => sub { is $contact->non_public, 1, 'contact marked as non_public'; }; +subtest 'check protected categories do not have name/group overwritten' => sub { + my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first; + $contact->set_extra_metadata('open311_protect', 1); + $contact->set_extra_metadata('group', [ 'sanitation' ]); + $contact->non_public(0); + $contact->update; + + my $services_xml = '<?xml version="1.0" encoding="utf-8"?> + <services> + <service> + <service_code>100</service_code> + <service_name>Cans left out constantly</service_name> + <description>Garbage or recycling cans that have been left out for more than 24 hours after collection. Violators will be cited.</description> + <metadata>false</metadata> + <type>realtime</type> + <keywords>private</keywords> + <group>cleansing</group> + </service> + </services> + '; + + my $service_list = get_xml_simple_object( $services_xml ); + + FixMyStreet::override_config { + ALLOWED_COBRANDS => [ 'tester' ], + COBRAND_FEATURES => { + category_groups => { tester => 1 }, + } + }, sub { + my $processor = Open311::PopulateServiceList->new(); + $processor->_current_body( $body ); + $processor->process_services( $service_list ); + }; + + my $contact_count = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->count(); + is $contact_count, 1, 'correct number of contacts'; + + $contact->discard_changes; + is $contact->email, '100', 'email correct'; + is $contact->category, 'Cans left out 24x7', 'category unchanged'; + is_deeply $contact->groups, ['sanitation'], 'group unchanged'; + # test that something did change + is $contact->non_public, 1, 'contact marked as non_public'; +}; + + subtest 'check existing category marked non_public' => sub { my $contact = FixMyStreet::DB->resultset('Contact')->search( { body_id => $body->id } )->first; $contact->update({ diff --git a/templates/web/base/admin/bodies/contact-form.html b/templates/web/base/admin/bodies/contact-form.html index b698fcea2..35fab4541 100644 --- a/templates/web/base/admin/bodies/contact-form.html +++ b/templates/web/base/admin/bodies/contact-form.html @@ -63,6 +63,13 @@ <textarea id="disabled-message" name="disable_message" class="form-control">[% contact.disable_form_field.description %]</textarea> </p> + [% IF body.send_method == 'Open311' %] + <p class="form-check"> + <input type="checkbox" name="open311_protect" value="1" id="open311_protect"[% ' checked' IF contact.get_extra_metadata('open311_protect') %]> + <label for="open311_protect">[% loc("Protect this category's name and group(s) from Open311 changes") %]</label> + </p> + [% END %] + [% IF body.can_be_devolved %] <div class="admin-hint"> <p> diff --git a/templates/web/base/admin/index.html b/templates/web/base/admin/index.html index 5a469b08e..88c7ff959 100644 --- a/templates/web/base/admin/index.html +++ b/templates/web/base/admin/index.html @@ -74,13 +74,4 @@ and to receive notices of updates. </table> [% END %] -<h2>[% loc('Stats') %]</h2> -[% INCLUDE 'status/stats.html' admin_include_users=1 %] - -[% IF c.cobrand.admin_show_creation_graph -%] - <p> - <a href="[% c.config.BASE_URL %]/fms-live-creation.png" class="admin-offsite-link">[% loc('Graph of problem creation by status over time') %]</a> - </p> -[% END -%] - [% INCLUDE 'admin/footer.html' %] diff --git a/templates/web/base/admin/stats/index.html b/templates/web/base/admin/stats/index.html index 452af001e..e6ba5e054 100644 --- a/templates/web/base/admin/stats/index.html +++ b/templates/web/base/admin/stats/index.html @@ -1,5 +1,13 @@ [% INCLUDE 'admin/header.html' title=loc('Stats') %] +[% INCLUDE 'status/stats.html' admin_include_users=1 %] + +[% IF c.cobrand.admin_show_creation_graph -%] + <p> + <a href="[% c.config.BASE_URL %]/fms-live-creation.png" class="admin-offsite-link">[% loc('Graph of problem creation by status over time') %]</a> + </p> +[% END -%] + <ul> <li><a href="[% c.uri_for_action('admin/stats/questionnaire') %]">[% loc('Survey Results') %]</a></li> <li><a href="[% c.uri_for_action('admin/stats/state') %]">[% loc('Problem breakdown by state') %]</a></li> diff --git a/templates/web/base/report/new/form_user_loggedin.html b/templates/web/base/report/new/form_user_loggedin.html index d657be450..0d259e695 100644 --- a/templates/web/base/report/new/form_user_loggedin.html +++ b/templates/web/base/report/new/form_user_loggedin.html @@ -63,7 +63,9 @@ [% IF c.user.has_permission_to("report_inspect", bodies_ids) OR c.user.has_permission_to("report_mark_private", bodies_ids) %] <div class="checkbox-group"> - <input type="checkbox" name="non_public" id="form_non_public" value="1"[% ' checked' IF report.non_public %]> + <input type="checkbox" name="non_public" id="form_non_public" value="1" + [%~ ' checked' IF report.non_public OR non_public_categories.$category %] + [%~ ' disabled' IF non_public_categories.$category %]> <label class="inline" for="form_non_public">[% loc('Private') %] </label> </div> [% END %] diff --git a/templates/web/base/status/stats.html b/templates/web/base/status/stats.html index 02f9de904..90904abaa 100644 --- a/templates/web/base/status/stats.html +++ b/templates/web/base/status/stats.html @@ -2,7 +2,6 @@ [%- total_problems_live = total_problems_live | format_number; - total_problems_users = total_problems_users | format_number; comments_confirmed = (comments.confirmed || 0) | format_number; alerts_1 = alerts.1 | format_number; alerts_0 = alerts.0 | format_number; @@ -17,6 +16,7 @@ <ul> <li>[% tprintf( loc('<strong>%s</strong> live problems'), decode(total_problems_live) ) %] [% IF admin_include_users %] + [% total_problems_users = total_problems_users | format_number ~%] [% tprintf( loc('from %s different users'), decode(total_problems_users) ) %] [% END %] </li> diff --git a/web/cobrands/fixmystreet/fixmystreet.js b/web/cobrands/fixmystreet/fixmystreet.js index f0b4cbb84..cd98b233b 100644 --- a/web/cobrands/fixmystreet/fixmystreet.js +++ b/web/cobrands/fixmystreet/fixmystreet.js @@ -454,9 +454,11 @@ $.extend(fixmystreet.set_up, { if (data && data.non_public) { $(".js-hide-if-private-category").hide(); $(".js-hide-if-public-category").removeClass("hidden-js").show(); + $('#form_non_public').prop('checked', true).prop('disabled', true); } else { $(".js-hide-if-private-category").show(); $(".js-hide-if-public-category").hide(); + $('#form_non_public').prop('checked', false).prop('disabled', false); } if (data && data.allow_anonymous) { $('.js-show-if-anonymous').removeClass('hidden-js'); |