diff options
Diffstat (limited to 'rt/share/html/Search')
37 files changed, 635 insertions, 450 deletions
diff --git a/rt/share/html/Search/Article.html b/rt/share/html/Search/Article.html new file mode 100644 index 000000000..a50990598 --- /dev/null +++ b/rt/share/html/Search/Article.html @@ -0,0 +1,52 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# <sales@bestpractical.com> +%# +%# (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 }}} +<%init> +RT::Interface::Web::Redirect(RT->Config->Get('WebURL'). + 'Articles/Article/Search.html?' . $m->comp( '/Elements/QueryString', + %ARGS, Load => 'Load', CurrentSearch => $ARGS{LoadSavedSearch} ) ); +</%init> diff --git a/rt/share/html/Search/Build.html b/rt/share/html/Search/Build.html index 506384c4b..b200f9050 100644 --- a/rt/share/html/Search/Build.html +++ b/rt/share/html/Search/Build.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -53,7 +53,7 @@ %# Build/Edit.html (Advanced).) %# %# After doing some stuff with default arguments and saved searches, the ParseQuery -%# function (which is similar to, but not the same as, _parser in RT/Tickets_Overlay_SQL) +%# function (which is similar to, but not the same as, _parser in lib/RT/Tickets_SQL.pm) %# converts the Query into a RT::Interface::Web::QueryBuilder::Tree. This mason file %# then adds stuff to or modifies the tree based on the actions that had been requested %# by clicking buttons. It then calls GetQueryAndOptionList on the tree to generate @@ -66,15 +66,9 @@ %# action does quote it (this breaks SQLite). %# <& /Elements/Header, Title => $title &> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Build.html?".$QueryString, - Title => $title, - %query, - SavedSearchId => $saved_search{'Id'}, - SavedChartSearchId => $ARGS{SavedChartSearchId}, -&> +<& /Elements/Tabs, %TabArgs &> -<form method="post" action="Build.html" name="BuildQuery"> +<form method="post" action="Build.html" name="BuildQuery" id="BuildQuery"> <input type="hidden" class="hidden" name="SavedSearchId" value="<% $saved_search{'Id'} %>" /> <input type="hidden" class="hidden" name="SavedChartSearchId" value="<% $ARGS{'SavedChartSearchId'} %>" /> <input type="hidden" class="hidden" name="Query" value="<% $query{'Query'} %>" /> @@ -84,9 +78,9 @@ <div id="pick-criteria"> - <& Elements/PickCriteria, query => $query{'Query'}, cfqueues => $queues &> -<& /Elements/Submit, Label => loc('Add these terms'), Name => 'AddClause'&> -<& /Elements/Submit, Label => loc('Add these terms and Search'), Name => 'DoSearch'&> + <& Elements/PickCriteria, query => $query{'Query'}, queues => $queues &> +<& /Elements/Submit, Label => loc('Add these terms'), SubmitId => 'AddClause', Name => 'AddClause'&> +<& /Elements/Submit, Label => loc('Add these terms and Search'), SubmitId => 'DoSearch', Name => 'DoSearch'&> </div> @@ -108,8 +102,8 @@ AvailableColumns => $AvailableColumns, CurrentFormat => $CurrentFormat, &> -<& /Elements/Submit, Label => loc('Update format and Search'), Name => 'DoSearch', id=>"formatbuttons"&> </span> +<& /Elements/Submit, Label => loc('Update format and Search'), Name => 'DoSearch', id=>"formatbuttons"&> </form> <%INIT> @@ -179,14 +173,22 @@ my $tree = $ParseQuery->( $query{'Query'}, \@parse_results ); # if parsing went poorly, send them to the edit page to fix it if ( @parse_results ) { - return $m->comp( "Edit.html", Query => $query{'Query'}, actions => \@actions ); + push @actions, @parse_results; + return $m->comp( + "Edit.html", + Query => $query{'Query'}, + Format => $query{'Format'}, + SavedSearchId => $saved_search{'Id'}, + SavedChartSearchId => $ARGS{'SavedChartSearchId'}, + actions => \@actions, + ); } my @options = $tree->GetDisplayedNodes; my @current_values = grep defined, @options[@clauses]; my @new_values = (); -# {{{ Try to find if we're adding a clause +# Try to find if we're adding a clause foreach my $arg ( keys %ARGS ) { next unless $arg =~ m/^ValueOf([\w\.]+|'CF.{.*?}')$/ && ( ref $ARGS{$arg} eq "ARRAY" @@ -226,14 +228,16 @@ foreach my $arg ( keys %ARGS ) { elsif ( $op eq '!=' ) { $op = "IS NOT"; } - - # This isn't "right", but... - # It has to be this way until #5182 is fixed - $value = "'NULL'"; } - else { - $value =~ s/'/\\'/g; - $value = "'$value'" unless $value =~ /^\d+$/; + elsif ($value =~ /\D/) { + $value =~ s/(['\\])/\\$1/g; + $value = "'$value'"; + } + + if ($keyword =~ /^'CF\.{(.*)}'/) { + my $cf = $1; + $cf =~ s/(['\\])/\\$1/g; + $keyword = "'CF.{$cf}'"; } my $clause = { @@ -246,7 +250,6 @@ foreach my $arg ( keys %ARGS ) { } } -# }}} push @actions, $m->comp('Elements/EditQuery:Process', %ARGS, @@ -255,7 +258,7 @@ push @actions, $m->comp('Elements/EditQuery:Process', New => \@new_values, ); -# {{{ Rebuild $Query based on the additions / movements +# Rebuild $Query based on the additions / movements my $optionlist_arrayref; ($query{'Query'}, $optionlist_arrayref) = $tree->GetQueryAndOptionList(\@current_values); @@ -264,25 +267,29 @@ my $optionlist = join "\n", map { qq(<option value="$_->{INDEX}" $_->{SELECTED}> . (" " x (5 * $_->{DEPTH})) . $m->interp->apply_escapes($_->{TEXT}, 'h') . qq(</option>) } @$optionlist_arrayref; -# }}} my $queues = $tree->GetReferencedQueues; -# {{{ Deal with format changes +# Deal with format changes my ( $AvailableColumns, $CurrentFormat ); ( $query{'Format'}, $AvailableColumns, $CurrentFormat ) = $m->comp( 'Elements/BuildFormatString', %ARGS, - cfqueues => $queues, + queues => $queues, Format => $query{'Format'}, ); -# }}} # if we're asked to save the current search, save it push @actions, $m->comp( 'Elements/EditSearches:Save', %ARGS, Query => \%query, SavedSearch => \%saved_search); -# {{{ Push the updates into the session so we don't loose 'em +# Populate the "query" context with saved search data + +if ($ARGS{SavedSearchSave}) { + $query{'SavedSearchId'} = $saved_search{'Id'}; +} + +# Push the updates into the session so we don't lose 'em $session{'CurrentSearchHash'} = { %query, @@ -291,30 +298,31 @@ $session{'CurrentSearchHash'} = { Description => $saved_search{'Description'}, }; -# }}} -# {{{ Show the results, if we were asked. +# Show the results, if we were asked. if ( $ARGS{'DoSearch'} ) { - $m->comp( 'Results.html', %query, SavedChartSearchId => $ARGS{'SavedChartSearchId'}, ); - $m->comp( '/Elements/Footer' ); + my $redir_query_string = $m->comp( + '/Elements/QueryString', + %query, + SavedChartSearchId => $ARGS{'SavedChartSearchId'}, + SavedSearchId => $saved_search{'Id'}, + ); + RT::Interface::Web::Redirect(RT->Config->Get('WebURL') . 'Search/Results.html?' . $redir_query_string); $m->abort; } -# }}} -# {{{ Build a querystring for the tabs +# Build a querystring for the tabs -my $QueryString = ''; +my %TabArgs = (); if ($NewQuery) { - $QueryString = 'NewQuery=1'; + $TabArgs{QueryString} = 'NewQuery=1'; } elsif ( $query{'Query'} ) { - $QueryString = $m->comp('/Elements/QueryString', %query ); + $TabArgs{QueryArgs} = \%query; } -# }}} - </%INIT> <%ARGS> diff --git a/rt/share/html/Search/Bulk.html b/rt/share/html/Search/Bulk.html index 9f58789ab..250f6135d 100755 --- a/rt/share/html/Search/Bulk.html +++ b/rt/share/html/Search/Bulk.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,20 +46,10 @@ %# %# END BPS TAGGED BLOCK }}} <& /Elements/Header, Title => $title &> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Bulk.html", - Title => $title, - Format => $ARGS{'Format'}, # we don't want the locally modified one - Query => $Query, - Rows => $Rows, - OrderBy => $OrderBy, - Order => $Order, - SavedSearchId => $SavedSearchId, - SavedChartSearchId => $SavedChartSearchId, - &> +<& /Elements/Tabs &> <& /Elements/ListActions, actions => \@results &> -<form method="post" action="<% RT->Config->Get('WebPath') %>/Search/Bulk.html" enctype="multipart/form-data"> +<form method="post" action="<% RT->Config->Get('WebPath') %>/Search/Bulk.html" enctype="multipart/form-data" name="BulkUpdate" id="BulkUpdate"> % foreach my $var (qw(Query Format OrderBy Order Rows Page SavedChartSearchId)) { <input type="hidden" class="hidden" name="<%$var%>" value="<%$ARGS{$var} || ''%>" /> %} @@ -81,7 +71,7 @@ <hr /> -<& /Elements/Submit, Label => loc('Update'), CheckAll => 1, ClearAll => 1 &> +<& /Elements/Submit, Label => loc('Update'), CheckboxNameRegex => '/^UpdateTicket\d+$/', CheckAll => 1, ClearAll => 1 &> <br /> <&|/Widgets/TitleBox, title => $title &> <table> @@ -142,7 +132,7 @@ <table> <tr><td align="right"><&|/l&>Update Type</&>:</td> <td><select name="UpdateType"> - <option value="private" <% $ARGS{UpdateType} && $ARGS{UpdateType} eq 'private' ? 'selected="selected"' : '' %> ><&|/l&>Comments (not sent to requestors)</&></option> + <option value="private" <% $ARGS{UpdateType} && $ARGS{UpdateType} eq 'private' ? 'selected="selected"' : '' %> ><&|/l&>Comments (Not sent to requestors)</&></option> <option value="response" <% $ARGS{UpdateType} && $ARGS{UpdateType} eq 'response' ? 'selected="selected"' : '' %>><&|/l&>Reply to requestors</&></option> </select> </td></tr> @@ -159,20 +149,9 @@ size="60" value="<% $ARGS{UpdateSubject} || "" %>" /></td></tr> &><em><% $CF->FriendlyType %></em></td> </td></tr> % } # end if while -% if (exists $session{'Attachments'}) { -<tr><td><&|/l&>Attached file</&>:</td> -<td> -<&|/l&>Check box to delete</&><br /> -% foreach my $attach_name (keys %{$session{'Attachments'}}) { -<input type="checkbox" class="checkbox" name="DeleteAttach-<%$attach_name%>" value="1" /><%$attach_name%><br /> -% } # end of foreach -</td> -</tr> -% } # end of if - <tr><td align="right"><&|/l&>Attach</&>:</td><td><input name="Attach" type="file" /> - <input type="submit" class="button" name="AddMoreAttach" value="<&|/l&>Add More Files</&>" /> - <input type="hidden" class="hidden" name="UpdateAttach" value="1" /></td></tr> +<& /Ticket/Elements/AddAttachments, %ARGS &> + <tr><td class="labeltop"><&|/l&>Message</&>:</td><td> %# Currently, bulk update always starts with Comment not Reply selected, so we check this unconditionally % my $IncludeSignature = RT->Config->Get('MessageBoxIncludeSignatureOnComment'); @@ -255,17 +234,16 @@ map ( $ARGS{$_} =~ /^$/ && ( delete $ARGS{$_} ), keys %ARGS ); my (@results); -# {{{ deal with deleting uploaded attachments +# deal with deleting uploaded attachments foreach my $key (keys %ARGS) { if ($key =~ m/^DeleteAttach-(.+)$/) { delete $session{'Attachments'}{$1}; } $session{'Attachments'} = { %{$session{'Attachments'} || {}} }; } -# }}} -# {{{ store the uploaded attachment in session -if ($ARGS{'Attach'}) { # attachment? +# store the uploaded attachment in session +if ( defined $ARGS{'Attach'} && length $ARGS{'Attach'} ) { # attachment? my $attachment = MakeMIMEEntity( AttachmentFieldName => 'Attach' ); @@ -276,13 +254,11 @@ if ($ARGS{'Attach'}) { # attachment? $file_path => $attachment, }; } -# }}} # delete temporary storage entry to make WebUI clean unless (keys %{$session{'Attachments'}} and $ARGS{'UpdateAttach'}) { delete $session{'Attachments'}; } -# }}} $Page ||= 1; diff --git a/rt/share/html/Search/Calendar.html b/rt/share/html/Search/Calendar.html index 9d2b6f546..8a1b79609 100644 --- a/rt/share/html/Search/Calendar.html +++ b/rt/share/html/Search/Calendar.html @@ -10,9 +10,8 @@ $NewQuery => 0 </%args> <& /Elements/Header, Title => $title &> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Calendar.html?$QueryString", - Title => $title &> +<& /Elements/Tabs &> + <&| /Widgets/TitleBox, title => loc('Calendar for ') . $rtdate->GetMonth($Month) . " $Year" , title_class=> 'inverse', @@ -195,7 +194,7 @@ my $set = DateTime::Set->from_recurrence( next => sub { $_[0]->truncate( to => 'day' )->add( days => 1 ) } ); -my $QueryString = +my $QueryString = $m->comp( '/Elements/QueryString', Query => $Query, @@ -212,7 +211,7 @@ $QueryString ||= 'NewQuery=1'; my $TempFormat = "__Starts__ __Due__"; my $TempQuery = "( Status = 'new' OR Status = 'open' OR Status = 'stalled') AND ( Owner = '" . $session{CurrentUser}->Id ."' OR Owner = 'Nobody' ) - AND ( Type = 'reminder' OR 'Type' = 'ticket' )"; + AND ( Type = 'reminder' OR 'Type' = 'ticket' )"; if ( my $Search = RTx::Calendar::SearchDefaultCalendar($session{CurrentUser}) ) { $TempFormat = $Search->SubValue('Format'); diff --git a/rt/share/html/Search/Chart b/rt/share/html/Search/Chart index 7bcb8d0d9..2709eb9c2 100644 --- a/rt/share/html/Search/Chart +++ b/rt/share/html/Search/Chart @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -48,7 +48,6 @@ <%args> $Query => "id > 0" $PrimaryGroupBy => 'Queue' -$SecondaryGroupBy => undef $ChartStyle => 'bars' </%args> <%init> @@ -170,9 +169,8 @@ if ($chart_class eq "GD::Graph::bars") { # refine values' colors, with both Color::Scheme's help and my own tweak $chart->{dclrs} = [ '66cc66', 'ff6666', 'ffcc66', '663399', - '3333cc', - '339933', '993333', '996633', '663399', - '33cc33', 'cc3333', 'cc9933', '6633cc' + '3333cc', '339933', '993333', '996633', + '33cc33', 'cc3333', 'cc9933', '6633cc', ]; { diff --git a/rt/share/html/Search/Chart.html b/rt/share/html/Search/Chart.html index 1a80ee385..070ce7cf7 100644 --- a/rt/share/html/Search/Chart.html +++ b/rt/share/html/Search/Chart.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -47,12 +47,10 @@ %# END BPS TAGGED BLOCK }}} <%args> $PrimaryGroupBy => 'Queue' -$SecondaryGroupBy => '' $ChartStyle => 'bars' $Description => undef </%args> <%init> -$ARGS{SecondaryGroupBy} ||= ''; $ARGS{Query} ||= 'id > 0'; # FIXME: should be factored with RT::Report::Tickets::Label :( @@ -74,25 +72,64 @@ my $title = loc( "Search results grouped by [_1]", $PrimaryGroupByLabel ); my $saved_search = $m->comp( '/Widgets/SavedSearch:new', SearchType => 'Chart', - SearchFields => [qw(Query PrimaryGroupBy SecondaryGroupBy ChartStyle)] ); + SearchFields => [qw(Query PrimaryGroupBy ChartStyle)] ); my @actions = $m->comp( '/Widgets/SavedSearch:process', args => \%ARGS, self => $saved_search ); +my %query; + +{ + if ($saved_search->{'CurrentSearch'}->{'Object'}) { + foreach my $search_field (@{ $saved_search->{'SearchFields'} }) { + $query{$search_field} = $saved_search->{'CurrentSearch'}->{'Object'}->Content->{$search_field}; + } + } + + my $current = $session{'CurrentSearchHash'}; + + my @session_fields = qw( + Query + SavedChartSearchId + SavedSearchDescription + SavedSearchLoad + SavedSearchLoadButton + SavedSearchOwner + ); + + for(@session_fields) { + $query{$_} = $current->{$_} unless defined $query{$_}; + $query{$_} = $m->request_args->{$_} unless defined $query{$_}; + } + + if ($m->request_args->{'SavedSearchLoadSubmit'}) { + $query{'SavedChartSearchId'} = $m->request_args->{'SavedSearchLoad'}; + } + + if ($m->request_args->{'SavedSearchSave'}) { + $query{'SavedChartSearchId'} = $saved_search->{'SearchId'}; + } + +} + </%init> <& /Elements/Header, Title => $title &> -<& /Ticket/Elements/Tabs, Title => $title, Query => $ARGS{Query}, - SavedChartSearchId => $saved_search->{SearchId} &> +<& /Elements/Tabs, QueryArgs => \%query &> <& /Elements/ListActions, actions => \@actions &> <& /Search/Elements/Chart, %ARGS &> -<br /> -<&| /Widgets/TitleBox, title => loc('Graph Properties')&> +<div class="chart-meta"> +<div class="chart-type"> +<&| /Widgets/TitleBox, title => loc('Chart Properties')&> <form method="get" action="<%RT->Config->Get('WebPath')%>/Search/Chart.html"> <input type="hidden" class="hidden" name="Query" value="<% $ARGS{Query} %>" /> <input type="hidden" class="hidden" name="SavedChartSearchId" value="<% $saved_search->{SearchId} || 'new' %>" /> -<&|/l, $m->scomp('Elements/SelectChartType', Name => 'ChartStyle', Default => $ChartStyle), $m->scomp('Elements/SelectGroupBy', Name => 'PrimaryGroupBy', Query => $ARGS{Query}, Default => $PrimaryGroupBy) -&>[_1] chart by [_2]</&><input type="submit" class="button" value="<%loc('Update Graph')%>" /> + +<&|/l_unsafe, $m->scomp('Elements/SelectChartType', Name => 'ChartStyle', Default => $ChartStyle), $m->scomp('Elements/SelectGroupBy', Name => 'PrimaryGroupBy', Query => $ARGS{Query}, Default => $PrimaryGroupBy) +&>[_1] chart by [_2]</&><input type="submit" class="button" value="<%loc('Update Chart')%>" /> </form> </&> - -<& /Widgets/SavedSearch:show, %ARGS, Action => 'Chart.html', self => $saved_search, Title => loc('Saved charts') &> +</div> +<div class="saved-search"> + <& /Widgets/SavedSearch:show, %ARGS, Action => 'Chart.html', self => $saved_search, Title => loc('Saved charts') &> +</div> +</div> diff --git a/rt/share/html/Search/Edit.html b/rt/share/html/Search/Edit.html index 76993f138..2459be0e4 100755 --- a/rt/share/html/Search/Edit.html +++ b/rt/share/html/Search/Edit.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,21 +46,11 @@ %# %# END BPS TAGGED BLOCK }}} <& /Elements/Header, Title => $title&> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Edit.html?".$QueryString, - Title => $title, - Format => $Format, - Query => $Query, - Rows => $Rows, - OrderBy => $OrderBy, - Order => $Order, - SavedSearchId => $SavedSearchId, - SavedChartSearchId => $SavedChartSearchId, -&> +<& /Elements/Tabs &> <& Elements/NewListActions, actions => \@actions &> -<form method="post" action="Build.html"> +<form method="post" action="Build.html" id="BuildQueryAdvanced" name="BuildQueryAdvanced"> <input type="hidden" class="hidden" name="SavedSearchId" value="<% $SavedSearchId %>" /> <input type="hidden" class="hidden" name="SavedChartSearchId" value="<% $SavedChartSearchId %>" /> <&|/Widgets/TitleBox, title => loc('Query'), &> diff --git a/rt/share/html/Search/Elements/Article b/rt/share/html/Search/Elements/Article new file mode 100644 index 000000000..46c13d79e --- /dev/null +++ b/rt/share/html/Search/Elements/Article @@ -0,0 +1,64 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# <sales@bestpractical.com> +%# +%# (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 }}} +<& /Elements/CollectionList, %ARGS, + Collection => $articles, + Class => 'RT::Articles', + Format => q{ + '<a href="/Articles/Article/Display.html?id=__id__">__id__</a>/TITLE:#', + '<a href="/Articles/Article/Display.html?id=__id__">__Name__</a>/TITLE:Name', + '__ClassName__', + '__CreatedRelative__', + '__LastUpdatedRelative__', + '__Summary__', + '__Topics__', } + &> +<%INIT> +my $QueryString = "?".$m->comp('/Elements/QueryString', %{$ARGS{args}}); +my $articles = RT::Articles->new( $session{CurrentUser} ); +$articles->Search( %{$ARGS{args}} ); +</%INIT> diff --git a/rt/share/html/Search/Elements/BuildFormatString b/rt/share/html/Search/Elements/BuildFormatString index 57c767911..a39287bff 100644 --- a/rt/share/html/Search/Elements/BuildFormatString +++ b/rt/share/html/Search/Elements/BuildFormatString @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -48,7 +48,7 @@ <%ARGS> $Format => RT->Config->Get('DefaultSearchResultFormat') -%cfqueues => () +%queues => () $Face => undef $Size => undef @@ -104,23 +104,18 @@ my @fields = ( Bookmark NEWLINE + NBSP ) ); # loc_qw $m->callback( CallbackOnce => 1, CallbackName => 'SetFieldsOnce', Fields => \@fields ); my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'}); -foreach my $id (keys %cfqueues) { +foreach my $id (keys %queues) { # Gotta load up the $queue object, since queues get stored by name now. my $id my $queue = RT::Queue->new($session{'CurrentUser'}); $queue->Load($id); - unless ($queue->id) { - # XXX TODO: This ancient code dates from a former developer - # we have no idea what it means or why cfqueues are so encoded. - $id =~ s/^.'*(.*).'*$/$1/; - $queue->Load($id); - } - $CustomFields->LimitToQueue($queue->Id); + $CustomFields->LimitToQueue($queue->Id) if $queue->Id; } $CustomFields->LimitToGlobal; diff --git a/rt/share/html/Search/Elements/Chart b/rt/share/html/Search/Elements/Chart index e25a9efd0..be05da315 100644 --- a/rt/share/html/Search/Elements/Chart +++ b/rt/share/html/Search/Elements/Chart @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -48,7 +48,6 @@ <%args> $Query => "id > 0" $PrimaryGroupBy => 'Queue' -$SecondaryGroupBy => undef $ChartStyle => 'bars' </%args> <%init> @@ -89,65 +88,66 @@ my %loc_keys; foreach my $key (@keys) { $data{$key} = shift @values; $loc_keys{$key} = loc($key); } my @sorted_keys = map { $loc_keys{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys; my @sorted_values = map { $data{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys; - - my $query_string = $m->comp('/Elements/QueryString', %ARGS); -</%init> - -<% loc('Query:') %> <% $Query %><br /> +my ($i,$total); +</%init> +<div class="chart-wrapper"> +<span class="chart image"> % if (RT->Config->Get('DisableGD')) { <% loc('Graphical charts are not available.') %><br /> % } else { -<img src="<%RT->Config->Get('WebPath')%>/Search/Chart?<%$query_string|n%>" /><br /> +<img src="<%RT->Config->Get('WebPath')%>/Search/Chart?<%$query_string|n%>" /> % } - -<table class="collection-as-table"> +</span> +<table class="collection-as-table chart"> <tr> <th class="collection-as-table"><% loc($tix->Label($PrimaryGroupBy)) %> </th> <th class="collection-as-table"><&|/l&>Tickets</&> </th> </tr> -% my ($i,$total); -% while (my $key = shift @sorted_keys) { -% $i++; -% my $value = shift @sorted_values; -% $total += $value; -<tr class="<%$i%2 ? 'evenline' : 'oddline' %>"> +<%perl> + while (my $key = shift @sorted_keys) { + $i++; + my $value = shift @sorted_values; + $total += $value; +</%perl> +<tr class="<% $i%2 ? 'evenline' : 'oddline' %>"> +<%perl> +# TODO sadly we don't have "creator.city is null" or alike support yet +# so no link if the key is undef for now + if ( $PrimaryGroupBy !~ /(Hourly|Daily|Monthly|Annually)$/ + && $key ne loc('(no value)') ) { + my $group = $PrimaryGroupBy; $group =~ s! !.!; + my %orig_keys = reverse %loc_keys; + my $QueryString = $m->comp('/Elements/QueryString', + Query => "$Query and $group = '$orig_keys{$key}'", + Format => $ARGS{Format}, + Rows => $ARGS{Rows}, + OrderBy => $ARGS{OrderBy}, + Order => $ARGS{Order}, + ); +</%perl> <td class="label collection-as-table"> -%# TODO sadly we don't have "creator.city is null" or alike support yet -%# so no link if the key is undef for now -% if ( $PrimaryGroupBy !~ /(Hourly|Daily|Monthly|Annually)$/ -% && $key ne loc('(no value)') ) { -% my $group = $PrimaryGroupBy; $group =~ s! !.!; -% my %orig_keys = reverse %loc_keys; -% my $QueryString = $m->comp('/Elements/QueryString', -% Query => "$Query and $group = '$orig_keys{$key}'", -% Format => $ARGS{Format}, -% Rows => $ARGS{Rows}, -% OrderBy => $ARGS{OrderBy}, -% Order => $ARGS{Order}, -% ); -<a href=<% RT->Config->Get('WebURL') %>Search/Results.html?<%$QueryString%>><%$key%></a> -% } else { -<% $key %> -% } +<a href=<% RT->Config->Get('WebPath') %>/Search/Results.html?<%$QueryString%>><%$key%></a> </td> <td class="value collection-as-table"> -<%$value%> +<a href=<% RT->Config->Get('WebPath') %>/Search/Results.html?<%$QueryString%>><%$value%></a> </td> +% } else { +<td class="label collection-as-table"><% $key %></td> +<td class="value collection-as-table"><% $value %></td> +% } </tr> % } %$i++; -<tr class="<%$i%2 ? 'evenline' : 'oddline' %>"> -<td class="label collection-as-table"> -<%loc('Total')%> -</td> -<td class="value collection-as-table"> -<%$total||''%> -</td> +<tr class="<%$i%2 ? 'evenline' : 'oddline' %> total"> +<td class="label collection-as-table"><%loc('Total')%></td> +<td class="value collection-as-table"><%$total||'0'%></td> </tr> </table> +<div class="query"><span class="label"><% loc('Query') %>:</span><span class="value"><% $Query %></span></div> +</div> diff --git a/rt/share/html/Search/Elements/ConditionRow b/rt/share/html/Search/Elements/ConditionRow index 65e217639..9d68b0925 100644 --- a/rt/share/html/Search/Elements/ConditionRow +++ b/rt/share/html/Search/Elements/ConditionRow @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/DisplayOptions b/rt/share/html/Search/Elements/DisplayOptions index c83035884..fbd497eb8 100644 --- a/rt/share/html/Search/Elements/DisplayOptions +++ b/rt/share/html/Search/Elements/DisplayOptions @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,91 +46,8 @@ %# %# END BPS TAGGED BLOCK }}} <&| /Widgets/TitleBox, title => loc("Sorting"), id => 'sorting' &> -<table valign="top"> - -% for my $o (0..3) { -% $Order[$o] ||= ''; $OrderBy[$o] ||= ''; -<tr> -<td class="label"> -% if ($o == 0) { -<&|/l&>Order by</&>: -% } -</td> -<td class="value"> -<select name="OrderBy"> -% if ($o > 0) { -<option value=""><&|/l&>~[none~]</&></option> -% } -% foreach my $field (sort keys %fields) { -% next unless $field; -<option value="<%$field%>" -% if (defined $OrderBy[$o] and $field eq $OrderBy[$o]) { -selected="selected" -% } -><% loc($field) %></option> -% } -</select> -<select name="Order"> -<option value="ASC" -% unless ( ($Order[$o]||'') eq "DESC" ) { -selected="selected" -% } -><&|/l&>Asc</&></option> -<option value="DESC" -% if ( ($Order[$o]||'') eq "DESC" ) { -selected="selected" -% } -><&|/l&>Desc</&></option> -</select> -</td> -</tr> -% } -<tr> -<td class="label"> -<&|/l&>Rows per page</&>: -</td><td class="value"> -<& /Elements/SelectResultsPerPage, - Name => "RowsPerPage", - Default => $RowsPerPage &> -</td> -</tr> -</table> +<& EditSort, %ARGS &> </&> <&| /Widgets/TitleBox, title => loc("Display Columns"), id => 'columns' &> <& EditFormat, %ARGS &> </&> - -<%INIT> -my $tickets = new RT::Tickets($session{'CurrentUser'}); -my %fields = %{$tickets->FIELDS}; -map { $fields{$_}->[0] =~ /^(?:ENUM|INT|DATE|STRING|ID)$/ || delete $fields{$_} } keys %fields; -delete $fields{'EffectiveId'}; -$fields{'Owner'} = 1; -$fields{ $_ . '.EmailAddress' } = 1 foreach( qw(Requestor Cc AdminCc) ); - -# Add all available CustomFields to the list of sortable columns. -my @cfs = grep /^CustomField/, @{$ARGS{AvailableColumns}}; -$fields{$_}=1 for @cfs; - -# Add PAW sort -$fields{'Custom.Ownership'} = 1; - -$fields{"Customer.$_"} = 1 foreach qw( Number Name ); #Freeside - -my @Order = split /\|/, $Order; -my @OrderBy = split /\|/, $OrderBy; -if ($Order =~ /\|/) { - @Order = split /\|/, $Order; -} else { - @Order = ( $Order ); -} - -</%INIT> - -<%ARGS> -$Order => undef -$OrderBy => undef -$RowsPerPage => undef -$Format => undef -$GroupBy => 'id' -</%ARGS> diff --git a/rt/share/html/Search/Elements/EditFormat b/rt/share/html/Search/Elements/EditFormat index bb869fe66..3eb5a9100 100644 --- a/rt/share/html/Search/Elements/EditFormat +++ b/rt/share/html/Search/Elements/EditFormat @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -45,7 +45,7 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} -<table> +<table class="edit-columns"> <tr> <th><&|/l&>Add Columns</&>:</th> @@ -62,8 +62,10 @@ <option value="<% $field %>"><% loc($field) %></option> % } </select></td> - -<td><&|/l&>Link</&>: +<td> +<div class="row"> +<span class="label"><&|/l&>Link</&>:</span> +<span class="value"> <select name="Link"> <option value="None">-</option> <option value="Display"><&|/l&>Display</&></option> @@ -72,19 +74,30 @@ <option value="Comment"><&|/l&>Comment</&></option> <option value="Resolve"><&|/l&>Resolve</&></option> </select> -<br /><&|/l&>Title</&>: <input name="Title" size="10" /> -<br /><&|/l&>Size</&>: -<select name="Size"> +</span> +</div> +<div class="row"> +<span class="label"><&|/l&>Title</&>:</span> +<span class="value"><input name="Title" size="10" /></span> +</div> +<div class="row"> +<span class="label"><&|/l&>Size</&>:</span> +<span class="value"><select name="Size"> <option value="">-</option> <option value="Small"><&|/l&>Small</&></option> <option value="Large"><&|/l&>Large</&></option> </select> -<br /><&|/l&>Style</&>: -<select name="Face"> +</span> +</div> +<div class="row"> +<span class="label"><&|/l&>Style</&>:</span> +<span class="value"><select name="Face"> <option value="">-</option> <option value="Bold"><&|/l&>Bold</&></option> <option value="Italic"><&|/l&>Italic</&></option> </select> +</span> +</div> </td> <td><input type="submit" class="button" name="AddCol" value=" → " /></td> diff --git a/rt/share/html/Search/Elements/EditQuery b/rt/share/html/Search/Elements/EditQuery index e6f649ea8..cfa8e0d1b 100644 --- a/rt/share/html/Search/Elements/EditQuery +++ b/rt/share/html/Search/Elements/EditQuery @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/EditSearches b/rt/share/html/Search/Elements/EditSearches index 08f84c70c..64309cb00 100644 --- a/rt/share/html/Search/Elements/EditSearches +++ b/rt/share/html/Search/Elements/EditSearches @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -45,14 +45,15 @@ %# those contributions and any derivatives thereof. %# %# END BPS TAGGED BLOCK }}} +<div class="edit-saved-searches"> <&| /Widgets/TitleBox, title => loc($Title)&> %# Hide all the save functionality if the user shouldn't see it. % if ( $can_modify ) { -<&|/l&>Privacy:</&> +<span class="label"><&|/l&>Privacy</&>:</span> <& SelectSearchObject, Name => 'SavedSearchOwner', Objects => \@Objects, Object => ( $Object && $Object->id ) ? $Object->Object : '' &> <br /> -<&|/l&>Description</&>: +<span class="label"><&|/l&>Description</&>:</span> <input size="25" name="SavedSearchDescription" value="<% $Description || '' %>" /> % if ($Id ne 'new') { @@ -67,19 +68,19 @@ </nobr> % } % if ( $Object && $Object->Id ) { -<input type="submit" class="button" name="SavedSearchSave" value="<%loc('Update')%>" /> +<input type="submit" class="button" id="SavedSearchSave" name="SavedSearchSave" value="<%loc('Update')%>" /> % } else { -<input type="submit" class="button" name="SavedSearchSave" value="<%loc('Save')%>" /> +<input type="submit" class="button" id="SavedSearchSave" name="SavedSearchSave" value="<%loc('Save')%>" /> %} % } <br /> <hr /> -<&|/l&>Load saved search:</&> +<span class="label"><&|/l&>Load saved search</&>:</span> <& SelectSearchesForObjects, Name => 'SavedSearchLoad', Objects => \@Objects, SearchType => $Type &> -<input type="submit" value="<% loc('Load') %>" class="button" /> +<input type="submit" value="<% loc('Load') %>" id="SavedSearchLoadSubmit" name="SavedSearchLoadSubmit" class="button" /> </&> - +</div> <%INIT> return unless $session{'CurrentUser'}->HasRight( Right => 'LoadSavedSearch', @@ -91,8 +92,8 @@ my $can_modify = $session{'CurrentUser'}->HasRight( Object => $RT::System, ); -use RT::SavedSearches; -my @Objects = RT::SavedSearches->new($session{CurrentUser})->_PrivacyObjects; +use RT::SavedSearch; +my @Objects = RT::SavedSearch->new($session{CurrentUser})->_PrivacyObjects; push @Objects, RT::System->new( $session{'CurrentUser'} ) if $session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser' ); diff --git a/rt/share/html/Search/Elements/EditSort b/rt/share/html/Search/Elements/EditSort new file mode 100644 index 000000000..497611e13 --- /dev/null +++ b/rt/share/html/Search/Elements/EditSort @@ -0,0 +1,142 @@ +%# BEGIN BPS TAGGED BLOCK {{{ +%# +%# COPYRIGHT: +%# +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC +%# <sales@bestpractical.com> +%# +%# (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 }}} +<table valign="top"> + +% for my $o (0..3) { +% $Order[$o] ||= ''; $OrderBy[$o] ||= ''; +<tr> +<td class="label"> +% if ($o == 0) { +<&|/l&>Order by</&>: +% } +</td> +<td class="value"> +<select name="OrderBy"> +% if ($o > 0) { +<option value=""><&|/l&>~[none~]</&></option> +% } +% # %fields maps display name to SQL column/function +% foreach my $field (sort keys %fields) { +% next unless $field; +% my $fieldval = $fields{$field}; +<option value="<%$fieldval%>" +% if (defined $OrderBy[$o] and $fieldval eq $OrderBy[$o]) { +selected="selected" +% } +><% loc($field) %></option> +% } +</select> +<select name="Order"> +<option value="ASC" +% unless ( ($Order[$o]||'') eq "DESC" ) { +selected="selected" +% } +><&|/l&>Asc</&></option> +<option value="DESC" +% if ( ($Order[$o]||'') eq "DESC" ) { +selected="selected" +% } +><&|/l&>Desc</&></option> +</select> +</td> +</tr> +% } +<tr> +<td class="label"> +<&|/l&>Rows per page</&>: +</td><td class="value"> +<& /Elements/SelectResultsPerPage, + Name => "RowsPerPage", + Default => $RowsPerPage &> +</td> +</tr> +</table> + +<%INIT> +my $tickets = RT::Tickets->new($session{'CurrentUser'}); +my %FieldDescriptions = %{$tickets->FIELDS}; +my %fields; + +for my $field (keys %FieldDescriptions) { + next if $field eq 'EffectiveId'; + next unless $FieldDescriptions{$field}->[0] =~ /^(?:ENUM|INT|DATE|STRING|ID)$/; + $fields{$field} = $field; +} + +$fields{'Owner'} = 'Owner'; +$fields{ $_ . '.EmailAddress' } = $_ . '.EmailAddress' + for qw(Requestor Cc AdminCc); + +# Add all available CustomFields to the list of sortable columns. +my @cfs = grep /^CustomField/, @{$ARGS{AvailableColumns}}; +$fields{$_} = $_ for @cfs; + +# Add PAW sort +$fields{'Custom.Ownership'} = 'Custom.Ownership'; + +$fields{"Customer.$_"} = 1 foreach qw( Number Name ); #Freeside + +$m->callback(CallbackName => 'MassageSortFields', Fields => \%fields ); + +my @Order = split /\|/, $Order; +my @OrderBy = split /\|/, $OrderBy; +if ($Order =~ /\|/) { + @Order = split /\|/, $Order; +} else { + @Order = ( $Order ); +} + +</%INIT> + +<%ARGS> +$Order => '' +$OrderBy => '' +$RowsPerPage => undef +$Format => undef +$GroupBy => 'id' +</%ARGS> diff --git a/rt/share/html/Search/Elements/Graph b/rt/share/html/Search/Elements/Graph index 1cf1f1baa..ba2f4dbb8 100644 --- a/rt/share/html/Search/Elements/Graph +++ b/rt/share/html/Search/Elements/Graph @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/NewListActions b/rt/share/html/Search/Elements/NewListActions index 8c7846a19..db185da3b 100644 --- a/rt/share/html/Search/Elements/NewListActions +++ b/rt/share/html/Search/Elements/NewListActions @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/PickBasics b/rt/share/html/Search/Elements/PickBasics index e9534237b..db7d9f5c1 100644 --- a/rt/share/html/Search/Elements/PickBasics +++ b/rt/share/html/Search/Elements/PickBasics @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -103,7 +103,7 @@ my @lines = ( Value => { Type => 'component', Path => '/Elements/SelectStatus', - Arguments => { SkipDeleted => 1 }, + Arguments => { SkipDeleted => 1, Queues => \%queues }, }, }, { @@ -124,7 +124,7 @@ my @lines = ( Value => { Type => 'component', Path => '/Elements/SelectOwner', - Arguments => { ValueAttribute => 'Name' }, + Arguments => { ValueAttribute => 'Name', Queues => \%queues }, }, }, { @@ -214,3 +214,6 @@ my @lines = ( $m->callback( Conditions => \@lines ); </%INIT> +<%ARGS> +%queues => () +</%ARGS> diff --git a/rt/share/html/Search/Elements/PickCFs b/rt/share/html/Search/Elements/PickCFs index 9abab4443..f2dc21f68 100644 --- a/rt/share/html/Search/Elements/PickCFs +++ b/rt/share/html/Search/Elements/PickCFs @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -50,21 +50,11 @@ % } <%INIT> my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'}); -foreach my $id (keys %cfqueues) { - # Gotta load up the $queue object, since queues get stored by name now. my $id +foreach my $id (keys %queues) { + # Gotta load up the $queue object, since queues get stored by name now. my $queue = RT::Queue->new($session{'CurrentUser'}); $queue->Load($id); - unless ($queue->id) { - # XXX TODO: This ancient code dates from a former developer - # we have no idea what it means or why cfqueues are so encoded. - $id =~ s/^.'*(.*).'*$/$1/; - - # unescape internal quotes - $id =~ s/(\\(.))/$2 eq "'" ? "'" : $1/eg; - - $queue->Load($id); - } - $CustomFields->LimitToQueue($queue->Id); + $CustomFields->LimitToQueue($queue->Id) if $queue->Id; } $CustomFields->LimitToGlobal; $m->callback( @@ -80,12 +70,19 @@ while ( my $CustomField = $CustomFields->Next ) { $line{'Field'} = $CustomField->Name; # Op - if ($CustomField->Type eq 'Date') { + if ($CustomField->Type =~ /^Date(Time)?$/ ) { $line{'Op'} = { Type => 'component', Path => '/Elements/SelectDateRelation', Arguments => {}, }; + } + elsif ($CustomField->Type =~ /^IPAddress(Range)?$/ ) { + $line{'Op'} = { + Type => 'component', + Path => '/Elements/SelectIPRelation', + Arguments => {}, + }; } else { $line{'Op'} = { Type => 'component', @@ -99,11 +96,12 @@ while ( my $CustomField = $CustomFields->Next ) { } # Value - if ($CustomField->Type eq 'Date') { + if ($CustomField->Type =~ /^Date(Time)?$/) { + my $is_datetime = $1 ? 1 : 0; $line{'Value'} = { Type => 'component', Path => '/Elements/SelectDate', - Arguments => {}, + Arguments => { $is_datetime ? (ShowTime => 1) : (ShowTime => 0), }, }; } else { $line{'Value'} = { @@ -116,10 +114,10 @@ while ( my $CustomField = $CustomFields->Next ) { push @lines, \%line; } -$m->callback( Conditions => \@lines, Queues => \%cfqueues ); +$m->callback( Conditions => \@lines, Queues => \%queues ); </%INIT> <%ARGS> -%cfqueues => undef +%queues => () </%ARGS> diff --git a/rt/share/html/Search/Elements/PickCriteria b/rt/share/html/Search/Elements/PickCriteria index 5eb112d17..74547c7da 100644 --- a/rt/share/html/Search/Elements/PickCriteria +++ b/rt/share/html/Search/Elements/PickCriteria @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -53,7 +53,7 @@ <& PickBasics &> <& PickCustomerFields &> -<& PickCFs, cfqueues => \%cfqueues &> +<& PickCFs, queues => \%queues &> <tr class="separator"><td colspan="3"><hr /></td></tr> <tr> @@ -69,5 +69,5 @@ <%ARGS> $addquery => 0 $query => undef -%cfqueues => undef +%queues => () </%ARGS> diff --git a/rt/share/html/Search/Elements/ResultsRSSView b/rt/share/html/Search/Elements/ResultsRSSView index f3b416a4e..5033c8c64 100644 --- a/rt/share/html/Search/Elements/ResultsRSSView +++ b/rt/share/html/Search/Elements/ResultsRSSView @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -70,7 +70,7 @@ if ( $m->request_comp->path =~ RT->Config->Get('WebNoAuthRegex') ) { # convert to perl strings $name = Encode::decode_utf8($name); - my $user = RT::User->new($RT::SystemUser); + my $user = RT::User->new(RT->SystemUser); $user->Load($name); $notfound->("Invalid user: $user") unless $user->id; @@ -102,7 +102,7 @@ $r->content_type('application/rss+xml'); # create an RSS 1.0 file (http://purl.org/rss/1.0/) use XML::RSS; - my $rss = new XML::RSS (version => '1.0'); + my $rss = XML::RSS->new(version => '1.0'); $rss->channel( title => RT->Config->Get('rtname').": Search " . $ARGS{'Query'}, link => RT->Config->Get('WebURL'), diff --git a/rt/share/html/Search/Elements/SearchPrivacy b/rt/share/html/Search/Elements/SearchPrivacy index f943af143..f36c1c894 100644 --- a/rt/share/html/Search/Elements/SearchPrivacy +++ b/rt/share/html/Search/Elements/SearchPrivacy @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SearchesForObject b/rt/share/html/Search/Elements/SearchesForObject index 35007bde5..efbf22078 100644 --- a/rt/share/html/Search/Elements/SearchesForObject +++ b/rt/share/html/Search/Elements/SearchesForObject @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectAndOr b/rt/share/html/Search/Elements/SelectAndOr index a644a71d8..ec19271b2 100644 --- a/rt/share/html/Search/Elements/SelectAndOr +++ b/rt/share/html/Search/Elements/SelectAndOr @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectChartType b/rt/share/html/Search/Elements/SelectChartType index 42cd4e4b2..aeee7cdbc 100644 --- a/rt/share/html/Search/Elements/SelectChartType +++ b/rt/share/html/Search/Elements/SelectChartType @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectGroup b/rt/share/html/Search/Elements/SelectGroup index 2ed965d42..ff5fc0786 100644 --- a/rt/share/html/Search/Elements/SelectGroup +++ b/rt/share/html/Search/Elements/SelectGroup @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -55,7 +55,7 @@ </select> <%INIT> -my $groups = new RT::Groups($session{'CurrentUser'}); +my $groups = RT::Groups->new($session{'CurrentUser'}); $groups->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => $Domain); </%INIT> diff --git a/rt/share/html/Search/Elements/SelectGroupBy b/rt/share/html/Search/Elements/SelectGroupBy index fbf19addb..9a6951a82 100644 --- a/rt/share/html/Search/Elements/SelectGroupBy +++ b/rt/share/html/Search/Elements/SelectGroupBy @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectLinks b/rt/share/html/Search/Elements/SelectLinks index 20c0dd311..0b7ce1251 100644 --- a/rt/share/html/Search/Elements/SelectLinks +++ b/rt/share/html/Search/Elements/SelectLinks @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectPersonType b/rt/share/html/Search/Elements/SelectPersonType index 6454acff3..d07e49c22 100644 --- a/rt/share/html/Search/Elements/SelectPersonType +++ b/rt/share/html/Search/Elements/SelectPersonType @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectSearchObject b/rt/share/html/Search/Elements/SelectSearchObject index d1b38abf0..6a511027e 100644 --- a/rt/share/html/Search/Elements/SelectSearchObject +++ b/rt/share/html/Search/Elements/SelectSearchObject @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Elements/SelectSearchesForObjects b/rt/share/html/Search/Elements/SelectSearchesForObjects index eafe88843..5f3169bbd 100644 --- a/rt/share/html/Search/Elements/SelectSearchesForObjects +++ b/rt/share/html/Search/Elements/SelectSearchesForObjects @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -51,10 +51,11 @@ $Name => undef $SearchType => 'Ticket', </%args> <select id="<%$Name%>" name="<%$Name%>"> -<option value="" selected> </option> +<option value="">-</option> % foreach my $object (@Objects) { -<optgroup label="<& SearchPrivacy, Object => $object &>"> % my @searches = $object->Attributes->Named('SavedSearch'); +% if ( @searches ) { +<optgroup label="<& SearchPrivacy, Object => $object &>"> % foreach my $search (@searches) { % # Skip it if it is not of search type we want. % next if ($search->SubValue('SearchType') @@ -63,4 +64,5 @@ $SearchType => 'Ticket', % } </optgroup> % } +% } </select> diff --git a/rt/share/html/Search/Graph.html b/rt/share/html/Search/Graph.html index 483aaae3d..c85181c3a 100644 --- a/rt/share/html/Search/Graph.html +++ b/rt/share/html/Search/Graph.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Results.html b/rt/share/html/Search/Results.html index 8aea1fc58..171b38d92 100755 --- a/rt/share/html/Search/Results.html +++ b/rt/share/html/Search/Results.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,22 +46,12 @@ %# %# END BPS TAGGED BLOCK }}} <& /Elements/Header, Title => $title, - Refresh => $session{'tickets_refresh_interval'} || RT->Config->Get('SearchResultsRefreshInterval', $session{'CurrentUser'} ), - RSSAutoDiscovery => $RSSFeedURL, + Refresh => $refresh, LinkRel => \%link_rel &> -<& /Ticket/Elements/Tabs, - current_tab => "Search/Results.html".$QueryString, - Title => $title, - Format => $Format, - Query => $Query, - Rows => $Rows, - OrderBy => $OrderBy, - Order => $Order, - SavedSearchId => $SavedSearchId, - SavedChartSearchId => $SavedChartSearchId, - &> +<& /Elements/Tabs &> <& /Elements/CollectionList, Query => $Query, + TotalFound => $ticketcount, AllowSorting => 1, OrderBy => $OrderBy, Order => $Order, @@ -82,22 +72,9 @@ <input type="submit" class="button" value="<&|/l&>Change</&>" /> </form> </div> -<div align="right" class="search-result-actions"> -<& Elements/ResultViews, - Collection => $session{'tickets'}, - QueryString => $QueryString, - Query => $Query, - Format => $Format, - Rows => $Rows, - OrderBy => $OrderBy, - Order => $Order, - RSSFeedURL => $RSSFeedURL, - ShortQueryString => $ShortQueryString, -&> - -% $m->callback( QueryString => $QueryString, CallbackName => 'SearchActions' ); -</div> <%INIT> +$m->callback( ARGSRef => \%ARGS, CallbackName => 'Initial' ); + # Read from user preferences my $prefs = $session{'CurrentUser'}->UserObj->Preferences("SearchDisplay") || {}; @@ -124,7 +101,9 @@ $Page = 1 unless $Page && $Page > 0; my ($title, $ticketcount); $session{'i'}++; $session{'tickets'} = RT::Tickets->new($session{'CurrentUser'}) ; -$session{'tickets'}->FromSQL($Query) if ($Query); +my ($ok, $msg) = $Query ? $session{'tickets'}->FromSQL($Query) : (1, "Vacuously OK"); +# Provide an empty search if parsing failed +$session{'tickets'}->FromSQL("id < 0") unless ($ok); if ($OrderBy =~ /\|/) { # Multiple Sorts @@ -164,16 +143,21 @@ my $QueryString = "?".$m->comp('/Elements/QueryString', Order => $Order, Page => $Page); my $ShortQueryString = "?".$m->comp('/Elements/QueryString', Query => $Query); -my $RSSQueryString = "?".$m->comp('/Elements/QueryString', Query => $Query, Order => $Order, OrderBy => $OrderBy); -my $RSSPath = join '/', map $m->interp->apply_escapes($_, 'u'), - $session{'CurrentUser'}->UserObj->Name, - $session{'CurrentUser'}->UserObj->GenerateAuthString( $Query.$Order.$OrderBy ); -my $RSSFeedURL = RT->Config->Get('WebPath')."/NoAuth/rss/$RSSPath/$RSSQueryString"; if ($ARGS{'TicketsRefreshInterval'}) { $session{'tickets_refresh_interval'} = $ARGS{'TicketsRefreshInterval'}; } +my $refresh = $session{'tickets_refresh_interval'} + || RT->Config->Get('SearchResultsRefreshInterval', $session{'CurrentUser'} ); + +if (RT->Config->Get('RestrictReferrer') and $refresh and not $m->request_args->{CSRF_Token}) { + my $token = RT::Interface::Web::StoreRequestToken( $session{'CurrentSearchHash'} ); + $m->notes->{RefreshURL} = RT->Config->Get('WebURL') + . "Search/Results.html?CSRF_Token=" + . $token; +} + my %link_rel; my $genpage = sub { return $m->comp( @@ -186,6 +170,15 @@ my $genpage = sub { Page => shift(@_), ); }; + +if ( RT->Config->Get('SearchResultsAutoRedirect') && $ticketcount == 1 && + $session{tickets}->First ) { +# $ticketcount is not always precise unless $UseSQLForACLChecks is set to true, +# check $session{tickets}->First here is to make sure the ticket is there. + RT::Interface::Web::Redirect( RT->Config->Get('WebURL') + ."Ticket/Display.html?id=". $session{tickets}->First->id ); +} + my $BaseURL = RT->Config->Get('WebPath')."/Search/Results.html?"; $link_rel{first} = $BaseURL . $genpage->(1) if $Page > 1; $link_rel{prev} = $BaseURL . $genpage->($Page - 1) if $Page > 1; diff --git a/rt/share/html/Search/Results.rdf b/rt/share/html/Search/Results.rdf index 8356d027a..1c64b9a84 100644 --- a/rt/share/html/Search/Results.rdf +++ b/rt/share/html/Search/Results.rdf @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) diff --git a/rt/share/html/Search/Results.tsv b/rt/share/html/Search/Results.tsv index cdf1ebad0..977b1ea7b 100644 --- a/rt/share/html/Search/Results.tsv +++ b/rt/share/html/Search/Results.tsv @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,12 +46,64 @@ %# %# END BPS TAGGED BLOCK }}} <%ARGS> +$Format => undef $Query => '' $OrderBy => 'id' $Order => 'ASC' +$PreserveNewLines => 0 </%ARGS> <%INIT> +$r->content_type('text/tab-separated-values'); +$r->header_out('Content-Disposition' => 'attachment;filename="Results.tsv"'); + +my $DisplayFormat = $m->comp('/Elements/ScrubHTML', Content => $Format); + +my @Format = $m->comp('/Elements/CollectionAsTable/ParseFormat', Format => $DisplayFormat); + +my @columns; + +my $should_loc = { map { $_ => 1 } qw(Status) }; + +my $col_entry = sub { + my $col = shift; + # in tsv output, "#" is often a comment character but we use it for "id" + delete $col->{title} + if $col->{title} and $col->{title} =~ /^\s*#\s*$/; + return { + header => Encode::encode_utf8(loc($col->{title} || $col->{attribute})), + map => $m->comp( + "/Elements/ColumnMap", + Name => $col->{attribute}, + Attr => 'value' + ), + should_loc => $should_loc->{$col->{attribute}}, + } +}; + +if ($PreserveNewLines) { + my $col = []; + push @columns, $col; + for (@Format) { + if ($_->{title} eq 'NEWLINE') { + $col = []; + push @columns, $col; + } + else { + push @$col, $col_entry->($_); + } + } +} +else { + push @columns, [map { $_->{attribute} + ? $col_entry->($_) + : () } @Format]; +} + +for (@columns) { + $m->out(join("\t", map { $_->{header} } @$_)."\n"); +} + my $Tickets = RT::Tickets->new( $session{'CurrentUser'} ); $Tickets->FromSQL( $Query ); if ( $OrderBy =~ /\|/ ) { @@ -67,97 +119,19 @@ 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 $ii = 0; +while (my $row = $Tickets->Next) { + for my $col (@columns) { + $m->out(join("\t", map { + my $val = ProcessColumnMapValue($_->{map}, Arguments => [$row, $ii++], Escape => 0); + $val = loc($val) if $_->{should_loc}; + # remove tabs from all field values, they screw up the tsv + $val = '' unless defined $val; + $val =~ s/(?:\n|\r)//g; $val =~ s{\t}{ }g; + Encode::encode_utf8($val); + } @$col)."\n"); } } - -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/tab-separated-values'); -$r->header_out('Content-Disposition' => 'attachment;filename="Results.tsv"'); -{ - 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; - } - $m->out(join("\t", @header)); - $m->out("\n"); - $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; - } - - $m->out(join("\t",@row)); - $m->out("\n"); - - unless (++$i%10) { - $i = 0; - $m->flush_buffer; - } -} - $m->abort(); + </%INIT> diff --git a/rt/share/html/Search/Simple.html b/rt/share/html/Search/Simple.html index dc5c14d10..4d7b1e3c5 100644 --- a/rt/share/html/Search/Simple.html +++ b/rt/share/html/Search/Simple.html @@ -2,7 +2,7 @@ %# %# COPYRIGHT: %# -%# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +%# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC %# <sales@bestpractical.com> %# %# (Except where explicitly superseded by other copyright notices) @@ -46,9 +46,7 @@ %# %# END BPS TAGGED BLOCK }}} <& /Elements/Header, Title => $title &> -<& /Elements/Tabs, - current_toptab => "Search/Simple.html", - Title => $title +<& /Elements/Tabs &> % $m->callback( %ARGS, CallbackName => 'PreForm' ); @@ -56,17 +54,42 @@ <div id="SimpleSearchForm"> <form action="Simple.html" method="get"> -<p><&|/l&>Search for tickets. Enter <strong>id</strong> numbers, <strong>queues</strong> by name, Owners by <strong>username</strong> and Requestors by <strong>email address</strong>.</&></p> - -<p><&|/l&>Searching the full text of every ticket can take a long time, but if you need to do it, you can search for any word in full ticket history for any word by typing <b>fulltext:<i>word</i></b>.</&></p> -<p><&|/l&>RT will look for anything else you enter in ticket subjects.</&></p> - -<br /> -<br /> <div align="center"> <input name="q" size="60" /><input type="submit" class="button" value="<&|/l&>Search</&>" /> </div> +% my @strong = qw(<strong> </strong>); + +<p><&|/l_unsafe, @strong &>Search for tickets by entering [_1]id[_2] numbers, subject words [_1]"in quotes"[_2], [_1]queues[_2] by name, Owners by [_1]username[_2], Requestors by [_1]email address[_2], and ticket [_1]statuses[_2].</&></p> + +<p><&|/l&>Any word not recognized by RT is searched for in ticket subjects.</&></p> + +% my $config = RT->Config->Get('FullTextSearch') || {}; +% my $fulltext_keyword = 'fulltext:'; +% if ( $config->{'Enable'} ) { +% if ( $config->{'Indexed'} ) { +<p><&|/l, $fulltext_keyword &>You can search for any word in full ticket history by typing <b>[_1]<i>word</i></b>.</&></p> +% } else { +<p><&|/l, $fulltext_keyword &>Searching the full text of every ticket can take a long time, but if you need to do it, you can search for any word in full ticket history by typing <b>[_1]<i>word</i></b>.</&></p> +% } +% } + +<p><&|/l_unsafe, map { "<strong>$_</strong>" } qw(initial active inactive any) &>Entering [_1], [_2], [_3], or [_4] limits results to tickets with one of the respective types of statuses. Any individual status name limits results to just the statuses named.</&> + +% if (RT->Config->Get('OnlySearchActiveTicketsInSimpleSearch', $session{'CurrentUser'})) { +% my $status_str = join ', ', map { loc($_) } RT::Queue->ActiveStatusArray; +<&|/l, $status_str &>Unless you specify a specific status, only tickets with active statuses ([_1]) are searched.</&> +% } +</p> + +<p><&|/l_unsafe, map { "<strong>$_</strong>" } 'queue:"Example Queue"', 'owner:email@example.com' &>Start the search term with the name of a supported field followed by a colon, as in [_1] and [_2], to explicitly specify the search type.</&></p> + +<p><&|/l_unsafe, '<strong>cf.Name:value</strong>' &>CFs may be searched using a similar syntax as above with [_1].</&></p> + +% my $link_start = '<a href="' . RT->Config->Get('WebPath') . '/Search/Build.html">'; +% my $link_end = '</a>'; +<p><&|/l_unsafe, $link_start, $link_end &>For the full power of RT's searches, please visit the [_1]search builder interface[_2].</&></p> + </form> % $m->callback( %ARGS, CallbackName => 'PostForm' ); @@ -78,7 +101,7 @@ my $title = loc("Search for tickets"); use RT::Search::Googleish; if ($q) { - my $tickets = new RT::Tickets( $session{'CurrentUser'} ); + my $tickets = RT::Tickets->new( $session{'CurrentUser'} ); $m->callback( %ARGS, query => \$q, CallbackName => 'ModifyQuery' ); if ($q =~ /^#?(\d+)$/) { |