From 0bce81dcafbe1116a7dcd3254d58ebbebaf18ae9 Mon Sep 17 00:00:00 2001 From: mark Date: Fri, 15 Apr 2011 23:54:52 +0000 Subject: [PATCH] CSV download, #10855 --- rt/FREESIDE_MODIFIED | 3 + rt/share/html/Search/Elements/ResultViews | 3 +- rt/share/html/Search/Results.csv | 172 ++++++++++++++++++++++++++++++ rt/share/html/Search/Results.tsv | 4 +- 4 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 rt/share/html/Search/Results.csv diff --git a/rt/FREESIDE_MODIFIED b/rt/FREESIDE_MODIFIED index 5ab5b1d74..3c22f0da4 100644 --- a/rt/FREESIDE_MODIFIED +++ b/rt/FREESIDE_MODIFIED @@ -129,3 +129,6 @@ share/html/RTx/Statistics/* share/html/Callbacks/Results-XLS/* share/html/Search/Results.xls lib/RT/Extension/SearchResults/XLS.pm + +share/html/Search/Results.csv +share/html/Search/Elements/ResultViews diff --git a/rt/share/html/Search/Elements/ResultViews b/rt/share/html/Search/Elements/ResultViews index c146e6736..7f6d7de86 100644 --- a/rt/share/html/Search/Elements/ResultViews +++ b/rt/share/html/Search/Elements/ResultViews @@ -57,10 +57,11 @@ $ShortQueryString => undef diff --git a/rt/share/html/Search/Results.csv b/rt/share/html/Search/Results.csv new file mode 100644 index 000000000..8551c9b80 --- /dev/null +++ b/rt/share/html/Search/Results.csv @@ -0,0 +1,172 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# +%# +%# (Except where explicitly superseded by other copyright notices) +%# +%# +%# LICENSE: +%# +%# This work is made available to you under the terms of Version 2 of +%# the GNU General Public License. A copy of that license should have +%# been provided with this software, but in any event can be snarfed +%# from www.gnu.org. +%# +%# This work is distributed in the hope that it will be useful, but +%# WITHOUT ANY WARRANTY; without even the implied warranty of +%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%# General Public License for more details. +%# +%# You should have received a copy of the GNU General Public License +%# along with this program; if not, write to the Free Software +%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +%# 02110-1301 or visit their web page on the internet at +%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +%# +%# +%# CONTRIBUTION SUBMISSION POLICY: +%# +%# (The following paragraph is not intended to limit the rights granted +%# to you to modify and distribute this software under the terms of +%# the GNU General Public License and is only of importance to you if +%# you choose to contribute your changes and enhancements to the +%# community by submitting them to Best Practical Solutions, LLC.) +%# +%# By intentionally submitting any modifications, corrections or +%# derivatives to this work, or any other work intended for use with +%# Request Tracker, to Best Practical Solutions, LLC, you confirm that +%# you are the copyright holder for those contributions and you grant +%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, +%# royalty-free, perpetual, license to use, copy, create derivative +%# works based on those contributions, and sublicense and distribute +%# those contributions and any derivatives thereof. +%# +%# END BPS TAGGED BLOCK }}} +<%ARGS> +$Query => '' +$OrderBy => 'id' +$Order => 'ASC' + +<%INIT> + +eval "use Text::CSV_XS"; +if ( $@ ) { + $m->comp('/Error', Why => "Error loading Text::CSV_XS.\n$@"); + $m->abort; + return; +} + +my $csv = Text::CSV_XS->new( { eol => "\n" } ); + +my $Tickets = RT::Tickets->new( $session{'CurrentUser'} ); +$Tickets->FromSQL( $Query ); +if ( $OrderBy =~ /\|/ ) { + # Multiple Sorts + my @OrderBy = split /\|/, $OrderBy; + my @Order = split /\|/, $Order; + $Tickets->OrderByCols( + map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } } + ( 0 .. $#OrderBy ) + ); +} +else { + $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); +} + +my %cf_id_to_name; +my %cf_name_to_pos; +{ + my $cfs = RT::SQL::PossibleCustomFields( + Query => $Query, CurrentUser => $session{'CurrentUser'}, + ); + while ( my $cf = $cfs->Next ) { + my $name = $cf->Name; + $cf_id_to_name{ $cf->id } = $name; + next if $cf_name_to_pos{ $name }; + + $cf_name_to_pos{ $name } = + (sort { $b <=> $a } values %cf_name_to_pos)[0] + 1; + } +} + +my @attrs = qw( + id QueueObj->Name Subject Status + TimeEstimated TimeWorked TimeLeft + Priority FinalPriority + OwnerObj->Name + Requestors->MemberEmailAddressesAsString + Cc->MemberEmailAddressesAsString + AdminCc->MemberEmailAddressesAsString + DueObj->ISO ToldObj->ISO CreatedObj->ISO + ResolvedObj->ISO LastUpdatedObj->ISO LastUpdatedByObj->Name +); + +$r->content_type('text/csv'); +$r->header_out('Content-Disposition' => 'attachment;filename="Results.csv"'); +{ + my @header; + foreach my $attr (@attrs) { + my $label = $attr; + $label =~ s'Obj-.(?:AsString|Name|ISO)''g; + $label =~ s'-\>MemberEmailAddressesAsString''g; + push @header, $label; + } + + $_ += @header - 1 foreach values %cf_name_to_pos; + + foreach my $name ( sort { $cf_name_to_pos{$a} <=> $cf_name_to_pos{$b} } keys %cf_name_to_pos ) { + push @header, "CF-". $name; + } + $csv->combine(@header); + $m->out($csv->string()); + $m->flush_buffer; +} + +my $i = 0; +while ( my $Ticket = $Tickets->Next()) { + my @row; + foreach my $attr (@attrs) { + my $value; + if ($attr =~ /(.*)->ISO$/ and $Ticket->$1->Unix <= 0) { + $value = ''; + } else { + my $method = '$Ticket->'.$attr.'()'; + $method =~ s/->ISO\(\)$/->ISO( Timezone => 'user' )/; + $value = eval $method; + if ($@) {die "Failed to find $attr - ". $@}; + } + push @row, $value; + } + + my $values = $Ticket->CustomFieldValues; + $values->OrderByCols; # don't sort them + while (my $value = $values->Next) { + my $pos = $cf_name_to_pos{ $cf_id_to_name{ $value->CustomField } }; + next unless $pos; + + $row[$pos] = '' unless defined $row[$pos]; + $row[$pos] .= ', ' if $row[$pos]; + $row[$pos] .= $value->Content; + } + + # remove tabs from all field values, they screw up the tsv + for (@row) { + $_ = '' unless defined; + $_ =~ s/(?:\n|\r)//g; + $_ =~ s{\t}{ }g; + } + + $csv->combine(@row); + $m->out($csv->string()); + + unless (++$i%10) { + $i = 0; + $m->flush_buffer; + } +} + +$m->abort(); + diff --git a/rt/share/html/Search/Results.tsv b/rt/share/html/Search/Results.tsv index 2a0de14e6..cdf1ebad0 100644 --- a/rt/share/html/Search/Results.tsv +++ b/rt/share/html/Search/Results.tsv @@ -95,8 +95,8 @@ my @attrs = qw( ResolvedObj->ISO LastUpdatedObj->ISO LastUpdatedByObj->Name ); -$r->content_type('text/csv'); -$r->header_out('Content-Disposition' => 'attachment;filename="Results.csv"'); +$r->content_type('text/tab-separated-values'); +$r->header_out('Content-Disposition' => 'attachment;filename="Results.tsv"'); { my @header; foreach my $attr (@attrs) { -- 2.11.0