aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md3
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm49
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin/Bodies.pm5
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin/Stats.pm46
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Status.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/UKCouncils.pm2
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm9
-rw-r--r--perllib/Open311/PopulateServiceList.pm5
-rwxr-xr-xscript/bootstrap14
-rw-r--r--t/app/controller/admin.t10
-rw-r--r--t/app/controller/admin/bodies.t11
-rw-r--r--t/app/controller/report_new_staff.t8
-rw-r--r--t/open311/populate-service-list.t46
-rw-r--r--templates/web/base/admin/bodies/contact-form.html7
-rw-r--r--templates/web/base/admin/index.html9
-rw-r--r--templates/web/base/admin/stats/index.html8
-rw-r--r--templates/web/base/report/new/form_user_loggedin.html4
-rw-r--r--templates/web/base/status/stats.html2
-rw-r--r--web/cobrands/fixmystreet/fixmystreet.js2
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');