diff options
-rw-r--r-- | cpanfile | 1 | ||||
-rw-r--r-- | cpanfile.snapshot | 11 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/Controller/Dashboard.pm | 110 | ||||
-rw-r--r-- | t/app/controller/dashboard.t | 7 | ||||
-rw-r--r-- | templates/web/default/dashboard/index.html | 1 | ||||
-rw-r--r-- | web/cobrands/fixmystreet/dashboard.scss | 5 |
6 files changed, 129 insertions, 6 deletions
@@ -70,6 +70,7 @@ requires 'SOAP::Lite'; requires 'Statistics::Distributions'; requires 'Storable'; requires 'Template::Plugin::Comma'; +requires 'Text::CSV'; requires 'URI'; requires 'URI::Escape'; requires 'URI::QueryParam'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 0d57aaea2..16f4f3b95 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -5589,6 +5589,17 @@ DISTRIBUTIONS Test::Builder 0 Test::Builder::Tester 0.09 perl 5.007003 + Text-CSV-1.32 + pathname: M/MA/MAKAMAKA/Text-CSV-1.32.tar.gz + provides: + Text::CSV 1.32 + Text::CSV::ErrorDiag 1.31 + Text::CSV_PP 1.31 + requirements: + ExtUtils::MakeMaker 0 + IO::Handle 0 + Test::Harness 0 + Test::More 0 Text-Diff-1.41 pathname: O/OV/OVID/Text-Diff-1.41.tar.gz provides: diff --git a/perllib/FixMyStreet/App/Controller/Dashboard.pm b/perllib/FixMyStreet/App/Controller/Dashboard.pm index 4f9b783c7..b47a1f54b 100644 --- a/perllib/FixMyStreet/App/Controller/Dashboard.pm +++ b/perllib/FixMyStreet/App/Controller/Dashboard.pm @@ -121,7 +121,7 @@ sub index : Path : Args(0) { if $c->stash->{category}; $c->stash->{where} = \%where; my $prob_where = { %where }; - $prob_where->{state} = $prob_where->{'problem.state'}; + $prob_where->{'me.state'} = $prob_where->{'problem.state'}; delete $prob_where->{'problem.state'}; $c->stash->{prob_where} = $prob_where; @@ -144,17 +144,19 @@ sub index : Path : Args(0) { $c->stash->{q_state} = $c->req->param('state') || ''; if ( $c->stash->{q_state} eq 'fixed' ) { - $prob_where->{state} = [ FixMyStreet::DB::Result::Problem->fixed_states() ]; + $prob_where->{'me.state'} = [ FixMyStreet::DB::Result::Problem->fixed_states() ]; } elsif ( $c->stash->{q_state} ) { - $prob_where->{state} = $c->stash->{q_state}; - $prob_where->{state} = { IN => [ 'planned', 'action scheduled' ] } - if $prob_where->{state} eq 'action scheduled'; + $prob_where->{'me.state'} = $c->stash->{q_state}; + $prob_where->{'me.state'} = { IN => [ 'planned', 'action scheduled' ] } + if $prob_where->{'me.state'} eq 'action scheduled'; } my $params = { %$prob_where, 'me.confirmed' => { '>=', $dtf->format_datetime( DateTime->now->subtract( days => 30 ) ) }, }; - my @problems = $c->cobrand->problems->search( $params )->all; + my $problems_rs = $c->cobrand->problems->search( $params ); + my @problems = $problems_rs->all; + my %problems; foreach (@problems) { if ($_->confirmed >= DateTime->now->subtract(days => 7)) { @@ -166,6 +168,102 @@ sub index : Path : Args(0) { } } $c->stash->{lists} = \%problems; + + if ( $c->req->params->{export} ) { + $self->export_as_csv($c, $problems_rs, $body); + } +} + +sub export_as_csv { + my ($self, $c, $problems_rs, $body) = @_; + require Text::CSV; + my $problems = $problems_rs->search( + {}, { prefetch => 'comments' }); + + my $filename = do { + my %where = ( + body => $body->id, + category => $c->stash->{category}, + state => $c->stash->{q_state}, + ward => $c->stash->{ward}, + ); + join '-', + $c->req->uri->host, + map { + my $value = $where{$_}; + (defined $value and length $value) ? ($_, $value) : () + } sort keys %where }; + + my $csv = Text::CSV->new(); + $csv->combine( + 'Report ID', + 'Title', + 'Detail', + 'User Name', + 'Category', + 'Created', + 'Confirmed', + 'Acknowledged', + 'Fixed', + 'Closed', + 'Status', + 'Latitude', 'Longitude', + 'Nearest Postcode', + 'Report URL', + ); + my @body = ($csv->string); + + my $fixed_states = FixMyStreet::DB::Result::Problem->fixed_states; + my $closed_states = FixMyStreet::DB::Result::Problem->closed_states; + + while ( my $report = $problems->next ) { + my $external_body; + my $body_name = ""; + if ( $external_body = $report->body($c) ) { + # seems to be a zurich specific thing + $body_name = $external_body->name if ref $external_body; + } + my $hashref = $report->as_hashref($c); + + $hashref->{user_name_display} = $report->anonymous? + '(anonymous)' : $report->user->name; + + for my $comment ($report->comments) { + my $problem_state = $comment->problem_state or next; + next if $problem_state eq 'confirmed'; + $hashref->{acknowledged_pp} //= $c->cobrand->prettify_dt( $comment->created ); + $hashref->{fixed_pp} //= $fixed_states->{ $problem_state } ? + $c->cobrand->prettify_dt( $comment->created ): undef; + if ($closed_states->{ $problem_state }) { + $hashref->{closed_pp} = $c->cobrand->prettify_dt( $comment->created ); + last; + } + } + + $csv->combine( + @{$hashref}{ + 'id', + 'title', + 'detail', + 'user_name_display', + 'category', + 'created_pp', + 'confirmed_pp', + 'acknowledged_pp', + 'fixed_pp', + 'closed_pp', + 'state', + 'latitude', 'longitude', + 'postcode', + }, + (join '', $c->cobrand->base_url_for_report($report), $report->url), + ); + + push @body, $csv->string; + } + $c->res->content_type('text/csv; charset=utf-8'); + $c->res->header('content-disposition' => "attachment; filename=${filename}.csv"); + $c->res->body( join "\n", @body ); } sub updates_search : Private { diff --git a/t/app/controller/dashboard.t b/t/app/controller/dashboard.t index fa94097a7..5e4b4cbeb 100644 --- a/t/app/controller/dashboard.t +++ b/t/app/controller/dashboard.t @@ -602,8 +602,15 @@ FixMyStreet::override_config { check_report_counts( $res, $test->{report_counts_after} ); }; } + + subtest 'export as csv' => sub { + $mech->get_ok('/dashboard?export=1'); + my @lines = split /\n/, $mech->content; + is scalar @lines, 6, '1 (header) + 5 (reports) = 6 lines'; + }; }; + sub make_problem { my $args = shift; diff --git a/templates/web/default/dashboard/index.html b/templates/web/default/dashboard/index.html index f5a3cfba3..b3e1e8426 100644 --- a/templates/web/default/dashboard/index.html +++ b/templates/web/default/dashboard/index.html @@ -146,6 +146,7 @@ [% END %] </select> <input type="submit" value="Look up"> +<a class="export_as_csv" href="[% c.req.uri_with({ export => 1 }) %]">Export as CSV</a> <table width="100%" id="reports"> <tr> diff --git a/web/cobrands/fixmystreet/dashboard.scss b/web/cobrands/fixmystreet/dashboard.scss index bd241617e..ca862aaa4 100644 --- a/web/cobrands/fixmystreet/dashboard.scss +++ b/web/cobrands/fixmystreet/dashboard.scss @@ -95,3 +95,8 @@ font-size:2.25em; } } + + .export_as_csv { + font-size: 0.75em; + font-weight: bold; + } |