Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FMS] Add parent categories to dashboard categories view #4700

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion bin/csv-export
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,12 @@ my $user = FixMyStreet::DB->resultset("User")->find($opts->user) if $opts->user;
my $body = FixMyStreet::DB->resultset("Body")->find($opts->body) if $opts->body;
my $wards = $opts->wards ? [split',', $opts->wards] : [];

my $category = $opts->category ? [split'::', $opts->category] : [];

my $reporting = FixMyStreet::Reporting->new(
type => $opts->type,
user => $user,
category => $opts->category,
category => $category,
state => $opts->state,
role_id => $opts->role_id,
wards => $wards,
Expand Down
21 changes: 19 additions & 2 deletions perllib/FixMyStreet/App/Controller/Dashboard.pm
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +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('category');
$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 @@ -187,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
5 changes: 3 additions & 2 deletions perllib/FixMyStreet/Cobrand/TfL.pm
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,9 @@ sub dashboard_export_problems_add_columns {

my @contacts = $csv->body->contacts->search(undef, { order_by => [ 'category' ] } )->all;
my %extra_columns;
if ($csv->category) {
@contacts = grep { $_->category eq $csv->category } @contacts;
if (@{$csv->category}) {
my %picked_cats = map { $_ => 1} @{$csv->category};
@contacts = grep { $picked_cats{$_->category} } @contacts;
}
foreach my $contact (@contacts) {
foreach (@{$contact->get_metadata_for_storage}) {
Expand Down
11 changes: 6 additions & 5 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[Str] );
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 @@ -90,12 +90,12 @@ has csv_extra_data => ( is => 'rw', isa => CodeRef );
has filename => ( is => 'rw', isa => Str, lazy => 1, default => sub {
my $self = shift;
my %where = (
category => $self->category,
state => $self->state,
ward => join(',', @{$self->wards}),
start_date => $self->start_date,
end_date => $self->end_date,
);
$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 @@ -121,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;
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 @@ -375,9 +375,10 @@ sub kick_off_process {
my $cmd = FixMyStreet->path_to('bin/csv-export');
$cmd .= ' --cobrand ' . $self->cobrand->moniker;
$cmd .= " --out \Q$out\E";
foreach (qw(type category state start_date end_date)) {
foreach (qw(type state start_date end_date)) {
$cmd .= " --$_ " . quotemeta($self->$_) if $self->$_;
}
$cmd .= " --category " . join('::', map { quotemeta } @{$self->category}) if @{$self->category};
foreach (qw(body user)) {
$cmd .= " --$_ " . $self->$_->id if $self->$_;
}
Expand Down Expand Up @@ -490,7 +491,7 @@ sub filter_premade_csv {
}

my $category = $row->{Subcategory} || $row->{Category};
next if $self->category && $category ne $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
57 changes: 43 additions & 14 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,45 +160,73 @@ FixMyStreet::override_config {

subtest 'The correct categories and totals shown by default' => sub {
$mech->get_ok("/dashboard");
my $expected_cats = [ 'All', '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, 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");
};

subtest 'csv for multiple categories' => sub {
$mech->get_ok("/dashboard?category=Litter&category=Potholes&export=2");
$mech->content_contains('www.example.org-body-' . $body->id . '-category-Litter,Potholes-start_date-2014-01-02.csv');
$mech->get_ok("/dashboard?category=Litter&category=Potholes&category=Traffic+lights+&amp;+bells&export=2");
$mech->content_contains('www.example.org-body-' . $body->id . '-category-multiple-categories-start_date-2014-01-02.csv');
$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 {
$mech->create_problems_for_body(1, $body->id, 'Title', {
detail => "this report\nis split across\nseveral lines",
Expand All @@ -206,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 @@ -240,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
7 changes: 4 additions & 3 deletions templates/web/base/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ <h1>[% loc('Summary statistics') %]</h1>

<p>
<label for="category">[% loc('Category:') %]</label>
<select class="form-control" name="category" id="category"><option value=''>[% loc('All') %]</option>
<select class="form-control js-multiple" multiple name="category" id="category">
[% BLOCK category_option %]
<option value='[% cat.category | html %]'[% ' selected' IF category == cat.category %]>[% cat.category_display | html %]</option>
[% 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>
dracos marked this conversation as resolved.
Show resolved Hide resolved
[% ELSIF group.name %]
<optgroup label="[% group.name %]">
[% END %]
[%~ FOREACH cat IN group.categories ~%]
[% INCLUDE category_option %]
[%~ END ~%]
Expand Down
Loading