Skip to content

Commit

Permalink
[FMS] Add parent categories to dashboard categories view
Browse files Browse the repository at this point in the history
Add an 'All' subcategories checkbox to select all
the categories in one group

Arbitrary decision to choose the first parent category from
the groups method of a contact.

mysociety/societyworks#1458
  • Loading branch information
MorayMySoc committed Dec 6, 2023
1 parent 0f7ddeb commit 5b34f3c
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 28 deletions.
16 changes: 15 additions & 1 deletion perllib/FixMyStreet/App/Controller/Dashboard.pm
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,25 @@ sub index : Path : Args(0) {
$c->stash->{contacts} = [ $c->stash->{contacts}->all ];
$c->forward('/report/stash_category_groups', [ $c->stash->{contacts} ]);

my %group_names = map { $_->{name} => $_->{categories} } @{$c->stash->{category_groups}};
# See if we've had anything from the body dropdowns
$c->stash->{category} = [ $c->get_param_list('category') ];
my @remove_from_display;

foreach (@{$c->stash->{category}}) {
next unless /^group-(.*)/;
for my $contact (@{$group_names{$1}}) {
push @{ $c->stash->{category} }, $contact->category;
push @remove_from_display, $contact->category;
}
}

my %display_categories = map { $_ => 1 } @{$c->stash->{category}};
delete $display_categories{$_} for (@remove_from_display);
$c->stash->{display_categories} = \%display_categories;

@{$c->stash->{category}} = grep { $_ !~ /^group-/} @{$c->stash->{category}};

$c->stash->{ward} = [ $c->get_param_list('ward') ];

if ($c->user_exists) {
Expand Down Expand Up @@ -190,7 +204,7 @@ sub construct_rs_filter : Private {

my $reporting = FixMyStreet::Reporting->new(
type => $updates ? 'updates' : 'problems',
category => $c->stash->{category},
category => $c->stash->{category} || [],
state => $c->stash->{q_state},
wards => $c->stash->{ward},
body => $c->stash->{body} || undef,
Expand Down
12 changes: 5 additions & 7 deletions perllib/FixMyStreet/Reporting.pm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ has on_updates => ( is => 'lazy', default => sub { $_[0]->type eq 'updates' } );

has body => ( is => 'ro', isa => Maybe[InstanceOf['FixMyStreet::DB::Result::Body']] );
has wards => ( is => 'ro', isa => ArrayRef[Int], default => sub { [] } );
has category => ( is => 'ro', isa => Maybe[ArrayRef[Maybe[Str]]], default => sub { [] } );
has category => ( is => 'ro', isa => ArrayRef[Str], default => sub { [] } );
has state => ( is => 'ro', isa => Maybe[Str] );
has start_date => ( is => 'ro',
isa => Str,
Expand Down Expand Up @@ -95,9 +95,7 @@ has filename => ( is => 'rw', isa => Str, lazy => 1, default => sub {
start_date => $self->start_date,
end_date => $self->end_date,
);
if ($self->category) {
$where{category} = @{$self->category} < 3 ? join(',', @{$self->category}) : 'multiple-categories';
}
$where{category} = @{$self->category} < 3 ? join(',', @{$self->category}) : 'multiple-categories';
$where{body} = $self->body->id if $self->body;
$where{role} = $self->role_id if $self->role_id;
my $host = URI->new($self->cobrand->base_url)->host;
Expand All @@ -123,7 +121,7 @@ sub construct_rs_filter {
$where{areas} = [ map { { 'like', "%,$_,%" } } @{$self->wards} ]
if @{$self->wards};
$where{"$table_name.category"} = $self->category
if $self->category && @{$self->category};
if @{$self->category};

my $all_states = $self->cobrand->call_hook('dashboard_export_include_all_states');
if ( $self->state && FixMyStreet::DB::Result::Problem->fixed_states->{$self->state} ) { # Probably fixed - council
Expand Down Expand Up @@ -380,7 +378,7 @@ sub kick_off_process {
foreach (qw(type state start_date end_date)) {
$cmd .= " --$_ " . quotemeta($self->$_) if $self->$_;
}
$cmd .= " --category " . join('::', map { quotemeta } @{$self->category}) if ($self->category && @{$self->category});
$cmd .= " --category " . join('::', map { quotemeta } @{$self->category}) if @{$self->category};
foreach (qw(body user)) {
$cmd .= " --$_ " . $self->$_->id if $self->$_;
}
Expand Down Expand Up @@ -493,7 +491,7 @@ sub filter_premade_csv {
}

my $category = $row->{Subcategory} || $row->{Category};
next if ($self->category && @{$self->category}) && !grep { /$category/ } @{$self->category};
next if @{$self->category} && !grep { /$category/ } @{$self->category};

if ( $self->state && $fixed_states->{$self->state} ) { # Probably fixed - council
next unless $fixed_states->{$row->{$state_column}};
Expand Down
9 changes: 6 additions & 3 deletions t/app/controller/admin/report_edit.t
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ my $superuser = $mech->create_user_ok('[email protected]', name => 'Super Us

my $oxfordshire = $mech->create_body_ok(2237, 'Oxfordshire County Council');
my $user3 = $mech->create_user_ok('[email protected]', name => 'Body User', from_body => $oxfordshire);
my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => '[email protected]' );
my $oxfordshirecontact = $mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Potholes', email => '[email protected]', extra => { group => 'Road' } );
$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Traffic lights', email => '[email protected]' );
$mech->create_contact_ok( body_id => $oxfordshire->id, category => 'Yellow lines', email => '[email protected]', extra => { group => 'Road' } );


my $oxford = $mech->create_body_ok(2421, 'Oxford City Council');
$mech->create_contact_ok( body_id => $oxford->id, category => 'Graffiti', email => '[email protected]' );
Expand Down Expand Up @@ -58,7 +60,7 @@ my $log_entries = FixMyStreet::DB->resultset('AdminLog')->search(
object_type => 'problem',
object_id => $report->id
},
{
{
order_by => { -desc => 'id' },
}
);
Expand Down Expand Up @@ -455,7 +457,8 @@ subtest 'change report category' => sub {
whensent => \'current_timestamp',
});
$mech->get_ok("/admin/report_edit/" . $ox_report->id);

$mech->content_contains('<optgroup label="Road">');
$mech->content_lacks('<option value="group-Road"');
$mech->submit_form_ok( { with_fields => { category => 'Traffic lights' } }, 'form_submitted' );
$ox_report->discard_changes;
is $ox_report->category, 'Traffic lights';
Expand Down
47 changes: 32 additions & 15 deletions t/app/controller/dashboard.t
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ my $mech = FixMyStreet::TestMech->new;

my $other_body = $mech->create_body_ok(1234, 'Some Other Council');
my $body = $mech->create_body_ok(2651, 'City of Edinburgh Council');
my @cats = ('Litter', 'Other', 'Potholes', 'Traffic lights & bells');
my @cats = ('Litter', 'Other', 'Potholes', 'Traffic lights & bells', 'White lines');
for my $contact ( @cats ) {
my $c = $mech->create_contact_ok(body_id => $body->id, category => $contact, email => "$contact\@example.org");
if ($contact eq 'Potholes') {
if ($contact eq 'Potholes' || $contact eq 'White lines') {
$c->set_extra_metadata(group => ['Road']);
$c->update;
}
Expand All @@ -61,6 +61,7 @@ my $last_month = DateTime->now->subtract(months => 2);
$mech->create_problems_for_body(2, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'no2fat' });
$mech->create_problems_for_body(3, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights & bells', cobrand => 'no2fa', dt => $last_month });
$mech->create_problems_for_body(1, $body->id, 'Title', { areas => ",$alt_area_id,2651,", category => 'Litter', cobrand => 'no2fa' });
$mech->create_problems_for_body(1, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'White lines', cobrand => 'no2fat' });

my @scheduled_problems = $mech->create_problems_for_body(7, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Traffic lights & bells', cobrand => 'no2fa' });
my @fixed_problems = $mech->create_problems_for_body(4, $body->id, 'Title', { areas => ",$area_id,2651,", category => 'Potholes', cobrand => 'no2fa' });
Expand Down Expand Up @@ -159,43 +160,50 @@ FixMyStreet::override_config {

subtest 'The correct categories and totals shown by default' => sub {
$mech->get_ok("/dashboard");
my $expected_cats = [ 'Litter', 'Other', 'Traffic lights & bells', 'Potholes' ];
my $expected_cats = [ 'Litter', 'Other', 'Traffic lights & bells', 'All Road', 'Potholes', 'White lines' ];
my $res = $categories->scrape( $mech->content );
$mech->content_contains('<optgroup label="Road">');
$mech->content_contains('<option value="group-Road"');
is_deeply( $res->{cats}, $expected_cats, 'correct list of categories' );
# Three missing as more than a month ago
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 7, 3, 0, 10, 10, 3, 4, 17);
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 7, 3, 0, 10, 1, 0, 0, 1, 11, 3, 4, 18);
};

subtest 'test filters' => sub {
$mech->get_ok("/dashboard");
$mech->submit_form_ok({ with_fields => { category => 'Litter' } });
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1);
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1);
$mech->submit_form_ok({ with_fields => { category => '', state => 'fixed - council' } });
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 4, 4);
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4);
$mech->submit_form_ok({ with_fields => { state => 'action scheduled' } });
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 7, 0, 0, 7);
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 0, 0, 7, 0, 0, 7);
my $start = DateTime->now->subtract(months => 3)->strftime('%Y-%m-%d');
my $end = DateTime->now->subtract(months => 1)->strftime('%Y-%m-%d');
$mech->submit_form_ok({ with_fields => { state => '', start_date => $start, end_date => $end } });
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 3, 0, 0, 3);
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 3);
$mech->get_ok("/dashboard?category=Litter&category=Potholes");
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 0, 0, 0, 0, 3, 0, 4, 7);
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 4, 7);
$mech->get_ok("/dashboard?category=group-Road");
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 6, 0, 0, 0, 0, 1, 0, 0, 1, 3, 0, 4, 7);
$mech->get_ok("/dashboard?category=group-Road&category=Potholes");
test_table($mech->content, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 6, 0, 0, 0, 0, 1, 0, 0, 1, 3, 0, 4, 7);
$mech->get_ok("/dashboard?category=group-Road&category=Litter");
test_table($mech->content, 1, 0, 0, 1, 0, 0, 0, 0, 2, 0, 4, 6, 0, 0, 0, 0, 1, 0, 0, 1, 4, 0, 4, 8);
};

subtest 'test grouping' => sub {
$mech->get_ok("/dashboard?group_by=category");
test_table($mech->content, 1, 0, 6, 10, 17);
test_table($mech->content, 1, 0, 6, 10, 1, 18);
$mech->get_ok("/dashboard?group_by=state");
test_table($mech->content, 3, 7, 4, 3, 17);
test_table($mech->content, 4, 7, 4, 3, 18);
$mech->get_ok("/dashboard?start_date=2000-01-01&group_by=month");
test_table($mech->content, 0, 17, 17, 3, 0, 3, 3, 17, 20);
test_table($mech->content, 0, 18, 18, 3, 0, 3, 3, 18, 21);
};

subtest 'test roles' => sub {
# All the fixed (Pothole) reports only
$mech->get_ok("/dashboard?group_by=category&role=" . $role->id);
test_table($mech->content, 0, 0, 4, 0, 4);
test_table($mech->content, 0, 0, 4, 0, 0, 4);
$mech->get_ok("/dashboard?export=2&group_by=category&role=" . $role->id);
$mech->content_contains('role-' . $role->id, "File link created with role");
};
Expand All @@ -208,6 +216,15 @@ FixMyStreet::override_config {
$mech->get_ok("/dashboard?category=Litter&category=Potholes&export=1");
my @rows = $mech->content_as_csv;
is scalar @rows, 8, '1 (header) + 7 (reports) found = 8 lines';
$mech->get_ok("/dashboard?category=group-Road&export=1");
@rows = $mech->content_as_csv;
is scalar @rows, 8, '1 (header) + 7 (reports) found = 8 lines';
$mech->get_ok("/dashboard?category=group-Road&category=Potholes&export=1");
@rows = $mech->content_as_csv;
is scalar @rows, 8, '1 (header) + 7 (reports) found = 8 lines';
$mech->get_ok("/dashboard?category=group-Road&category=Litter&export=1");
@rows = $mech->content_as_csv;
is scalar @rows, 9, '1 (header) + 8 (reports) found = 9 lines';
};

subtest 'export as csv' => sub {
Expand All @@ -218,7 +235,7 @@ FixMyStreet::override_config {
});
$mech->get_ok('/dashboard?export=1');
my @rows = $mech->content_as_csv;
is scalar @rows, 19, '1 (header) + 18 (reports) = 19 lines';
is scalar @rows, 20, '1 (header) + 19 (reports) = 20 lines';

is scalar @{$rows[0]}, 22, '22 columns present';

Expand Down Expand Up @@ -252,7 +269,7 @@ FixMyStreet::override_config {
is $rows[5]->[15], 'Trowbridge', 'Ward column is name not ID';
is $rows[5]->[16], '529025', 'Correct Easting conversion';
is $rows[5]->[17], '179716', 'Correct Northing conversion';
is $rows[18]->[15], 'Bishops Cannings', 'Can see old ward';
is $rows[19]->[15], 'Bishops Cannings', 'Can see old ward';
};

subtest 'export updates as csv' => sub {
Expand Down
2 changes: 1 addition & 1 deletion templates/web/base/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ <h1>[% loc('Summary statistics') %]</h1>
[% SET category = cat.category | html %]
<option value='[% cat.category | html %]'[% ' selected' IF display_categories.$category %]>[% cat.category_display | html %]</option>
[% END %]
[%~ INCLUDE 'report/new/_category_select.html' ~%]
[%~ INCLUDE 'report/new/_category_select.html' include_group_option=1 ~%]
</select>
</p>

Expand Down
7 changes: 6 additions & 1 deletion templates/web/base/report/new/_category_select.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
[%~ FOREACH group IN category_groups ~%]
[% IF group.name %]<optgroup label="[% group.name %]">[% END %]
[% IF group.name AND include_group_option %]<optgroup label="[% group.name %]">
[% SET pseudo_category = "group-" _ group.name %]
<option value="group-[% group.name %]" [% ' selected' IF display_categories.$pseudo_category %]>All [% group.name %]</option>
[% ELSIF group.name %]
<optgroup label="[% group.name %]">
[% END %]
[%~ FOREACH cat IN group.categories ~%]
[% INCLUDE category_option %]
[%~ END ~%]
Expand Down

0 comments on commit 5b34f3c

Please sign in to comment.