[Rt-commit] rt branch, records_history, updated. rt-3.8.8-121-gd45e999

Ruslan Zakirov ruz at bestpractical.com
Wed Jun 30 00:13:47 EDT 2010


The branch, records_history has been updated
       via  d45e999606c7240ea7fbedf33706735b0f6b567b (commit)
       via  42d043c4d3727c7793b60b93d75271d8f1247990 (commit)
       via  5d4a0aa59c4b9c7460b142a357fc87bb142be526 (commit)
       via  ec8e1b524edecc661bf1c030e4604d9dc8c2ceff (commit)
       via  69bf96411391811ddd71af85c4a2be9df73f4889 (commit)
       via  6766e82221b4a5ded461db462acd784638ade65a (commit)
       via  2f3eebe69e5d5e71a663560496d8daf3a4c594a8 (commit)
       via  cd03dfc8f272ec8a6c0798dc0b829f5e81d5adc2 (commit)
       via  9a9cef1dbebd5f544bc024488d0f86c41690bf53 (commit)
       via  2c0f47b9ebeae8fda06984e10bbe80b03d0bb8ab (commit)
       via  c03aa80c28d310d5e4a37a986f554a8bafd6e7ef (commit)
       via  8230eb42c12914cda4f870f3063adc8bf133db71 (commit)
       via  61c48792ec527eb8e843b15d183a71f8cc0a41d5 (commit)
       via  16bd33996926c8dd8c8165d57b2bee88e0b82e21 (commit)
       via  79bd5d384ae6526de24b159b763f06bade341067 (commit)
       via  c0d9bf842f091ebed2afd4d13e2df6b7dcd05008 (commit)
       via  2f0c6bc2f641449478c37cfa904a57cb09487b18 (commit)
      from  be54c4a037648121263eb199557061d3e128bc6d (commit)

Summary of changes:
 etc/RT_Config.pm.in                                |   23 +++-
 lib/RT/Config.pm                                   |   25 +++-
 lib/RT/Interface/Email.pm                          |    2 +-
 lib/RT/Record.pm                                   |   73 +++++++++-
 lib/RT/SavedSearches.pm                            |   23 +++
 lib/RT/Ticket_Overlay.pm                           |   78 ++++++++++
 share/html/Admin/CustomFields/Modify.html          |    9 ++
 share/html/Admin/Queues/Modify.html                |    2 -
 .../{RT__Template => RT__SavedSearch}/ColumnMap    |   63 ++++----
 share/html/Elements/SavedSearches                  |   29 ++++
 share/html/Elements/SelectNewTicketQueue           |    7 +
 share/html/Elements/ShowHistory                    |  151 ++++++++++++++++++++
 share/html/Ticket/Create.html                      |    1 +
 share/html/Ticket/Elements/FindAttachments         |   61 ++++----
 share/html/Ticket/Elements/LoadTextAttachments     |   41 +-----
 share/html/Ticket/Elements/ShowHistory             |   80 +++++------
 share/html/Tools/Elements/Tabs                     |   14 ++-
 share/html/Tools/index.html                        |   16 ++-
 share/html/Widgets/ComboBox                        |    6 +-
 19 files changed, 533 insertions(+), 171 deletions(-)
 copy share/html/Elements/{RT__Template => RT__SavedSearch}/ColumnMap (73%)
 create mode 100644 share/html/Elements/SavedSearches
 create mode 100644 share/html/Elements/ShowHistory

- Log -----------------------------------------------------------------
commit 2f0c6bc2f641449478c37cfa904a57cb09487b18
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Thu Jun 17 16:21:59 2010 -0400

    $RememberDefaultQueue for "sticky" default queue

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index de268bb..621297f 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1524,6 +1524,15 @@ queue selection boxes on the web interface.
 
 #Set($DefaultQueue, 'General');
 
+=item C<$RememberDefaultQueue>
+
+When a queue is selected in the new ticket dropdown, make it the new default
+for the new ticket dropdown.
+
+=cut
+
+#Set($RememberDefaultQueue, 1);
+
 =item C<$DefaultTimeUnitsToHours>
 
 Use this to set the default units for time entry to hours instead of minutes.
diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index 051117a..25755d6 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -151,10 +151,19 @@ our %META = (
             },
         }
     },
+    RememberDefaultQueue => {
+        Section     => 'General',
+        Overridable => 1,
+        SortOrder   => 2,
+        Widget      => '/Widgets/Form/Boolean',
+        WidgetArguments => {
+            Description => 'Remember default queue' # loc
+        }
+    },
     UsernameFormat => {
         Section         => 'General',
         Overridable     => 1,
-        SortOrder       => 2,
+        SortOrder       => 3,
         Widget          => '/Widgets/Form/Select',
         WidgetArguments => {
             Description => 'Username format', # loc
@@ -168,7 +177,7 @@ our %META = (
     WebDefaultStylesheet => {
         Section         => 'General',                #loc
         Overridable     => 1,
-        SortOrder       => 3,
+        SortOrder       => 4,
         Widget          => '/Widgets/Form/Select',
         WidgetArguments => {
             Description => 'Theme',                  #loc
@@ -179,7 +188,7 @@ our %META = (
     MessageBoxRichText => {
         Section => 'General',
         Overridable => 1,
-        SortOrder => 4,
+        SortOrder => 5,
         Widget => '/Widgets/Form/Boolean',
         WidgetArguments => {
             Description => 'WYSIWYG message composer' # loc
@@ -188,7 +197,7 @@ our %META = (
     MessageBoxRichTextHeight => {
         Section => 'General',
         Overridable => 1,
-        SortOrder => 5,
+        SortOrder => 6,
         Widget => '/Widgets/Form/Integer',
         WidgetArguments => {
             Description => 'WYSIWYG composer height', # loc
@@ -197,7 +206,7 @@ our %META = (
     MessageBoxWidth => {
         Section         => 'General',
         Overridable     => 1,
-        SortOrder       => 6,
+        SortOrder       => 7,
         Widget          => '/Widgets/Form/Integer',
         WidgetArguments => {
             Description => 'Message box width',           #loc
@@ -206,7 +215,7 @@ our %META = (
     MessageBoxHeight => {
         Section         => 'General',
         Overridable     => 1,
-        SortOrder       => 7,
+        SortOrder       => 8,
         Widget          => '/Widgets/Form/Integer',
         WidgetArguments => {
             Description => 'Message box height',          #loc
@@ -215,7 +224,7 @@ our %META = (
     SearchResultsRefreshInterval => {
         Section         => 'General',                       #loc
         Overridable     => 1,
-        SortOrder       => 8,
+        SortOrder       => 9,
         Widget          => '/Widgets/Form/Select',
         WidgetArguments => {
             Description => 'Search results refresh interval',                            #loc
@@ -234,7 +243,7 @@ our %META = (
     ResolveDefaultUpdateType => {
         Section         => 'General',                                      #loc
         Overridable     => 1,
-        SortOrder       => 9,
+        SortOrder       => 10,
         Widget          => '/Widgets/Form/Select',
         WidgetArguments => {
             Description => 'Default Update Type when Resolving',           #loc
diff --git a/share/html/Elements/SelectNewTicketQueue b/share/html/Elements/SelectNewTicketQueue
index 403b1f6..949faca 100755
--- a/share/html/Elements/SelectNewTicketQueue
+++ b/share/html/Elements/SelectNewTicketQueue
@@ -50,5 +50,12 @@
 </label>
 <%INIT>
 my $queue = RT->Config->Get("DefaultQueue", $session{'CurrentUser'});
+
+if (RT->Config->Get("RememberDefaultQueue", $session{'CurrentUser'})) {
+    if (my $session_default = $session{'DefaultQueue'}) {
+        $queue = $session_default;
+    }
+}
+
 $m->callback(Queue => \$queue, CallbackName => 'DefaultQueue');
 </%INIT>
diff --git a/share/html/Ticket/Create.html b/share/html/Ticket/Create.html
index 2c8e357..b46a3b4 100755
--- a/share/html/Ticket/Create.html
+++ b/share/html/Ticket/Create.html
@@ -250,6 +250,7 @@
 <%INIT>
 $m->callback( CallbackName => "Init", ARGSRef => \%ARGS );
 my $Queue = $ARGS{Queue};
+$session{DefaultQueue} = $Queue;
 
 my $CloneTicketObj;
 if ($CloneTicket) {

commit c0d9bf842f091ebed2afd4d13e2df6b7dcd05008
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Fri Jun 18 16:29:45 2010 -0400

    Add some stubby methods to make CollectionList happier

diff --git a/lib/RT/SavedSearches.pm b/lib/RT/SavedSearches.pm
index 0848fc8..7f5aabe 100644
--- a/lib/RT/SavedSearches.pm
+++ b/lib/RT/SavedSearches.pm
@@ -146,6 +146,29 @@ sub Count {
     return scalar @{$self->{'objects'}};
 }
 
+=head2 CountAll
+
+Returns the number of search objects found
+
+=cut
+
+sub CountAll {
+    my $self = shift;
+    return $self->Count;
+}
+
+=head2 GotoPage
+
+Act more like a normal L<DBIx::SearchBuilder> collection.
+Moves the internal index around
+
+=cut
+
+sub GotoPage {
+    my $self = shift;
+    $self->{idx} = shift;
+}
+
 ### Internal methods
 
 # _GetObject: helper routine to load the correct object whose parameters

commit 79bd5d384ae6526de24b159b763f06bade341067
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Fri Jun 18 13:00:01 2010 -0400

    Add a SavedSearch Homepage element
    
    Uses a basic CollectionList to show all your personal and
    group SavedSearches as clickable result links on your homepage.

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 621297f..11e6c0b 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1351,7 +1351,7 @@ customized homepage ("RT at a glance").
 
 =cut
 
-Set($HomepageComponents, [qw(QuickCreate Quicksearch MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards)]);
+Set($HomepageComponents, [qw(QuickCreate Quicksearch MyAdminQueues MySupportQueues MyReminders RefreshHomepage Dashboards SavedSearches)]);
 
 =item C<@MasonParameters>
 
diff --git a/share/html/Elements/RT__SavedSearch/ColumnMap b/share/html/Elements/RT__SavedSearch/ColumnMap
new file mode 100644
index 0000000..795b5a2
--- /dev/null
+++ b/share/html/Elements/RT__SavedSearch/ColumnMap
@@ -0,0 +1,86 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
+%#                                          <jesse at 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 }}}
+<%ARGS>
+$Name
+$Attr => undef
+</%ARGS>
+<%ONCE>
+my $COLUMN_MAP = {
+    id => {
+        title     => '#', # loc
+        attribute => 'id',
+        align     => 'right',
+        value     => sub { return $_[0]->Id },
+    },
+    Name => {
+        title     => sub { return "foo" }, #'Name', # loc
+        attribute => 'Name',
+        value     => sub { return $_[0]->Name()||loc("Unnamed search") },
+    },
+    Query => {
+        title     => 'Query', # loc
+        attribute => 'Query',
+        value     => sub { return $_[0]->GetParameter('Query') },
+    },
+    ResultsURL => {
+        title     => '',
+        attribute => 'ResultsURL',
+        value     => sub { my $search = shift;
+                           return join('&', sort
+                            map { $m->interp->apply_escapes($_,'u') .
+                                  '=' .
+                                  $m->interp->apply_escapes($search->GetParameter($_),'u') }
+                            qw(Query Format Rows Order OrderBy)) },
+    }
+};
+
+</%ONCE>
+<%INIT>
+$m->callback( COLUMN_MAP => $COLUMN_MAP, CallbackName => 'ColumnMap', CallbackOnce => 1 );
+return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
+</%INIT>
diff --git a/share/html/Elements/SavedSearches b/share/html/Elements/SavedSearches
new file mode 100644
index 0000000..e7b7d1e
--- /dev/null
+++ b/share/html/Elements/SavedSearches
@@ -0,0 +1,29 @@
+<&|/Widgets/TitleBox, title => loc('Saved Searches') &>
+% foreach my $Object (@Objects) {
+%   my $SavedSearches = RT::SavedSearches->new($session{CurrentUser});
+%   $SavedSearches->LimitToPrivacy(join('-',ref($Object),$Object->Id),'Ticket');
+%   my $title;
+%   if (ref $Object eq 'RT::User' && $Object->Id == $session{CurrentUser}->Id) {
+%       $title = loc("My saved searches");
+%   } else {
+%       $title = loc("[_1]'s saved searches",$Object->Name);
+%   }
+%   $title = $m->interp->apply_escapes($title, 'h');
+<& /Elements/CollectionList,
+    %ARGS,
+    Class => 'RT::SavedSearch',
+    Format => qq{'<a href="__WebPath__/Search/Results.html?__ResultsURL__">__Name__</a>/TITLE:$title'},
+    Collection => $SavedSearches,
+    PassArguments => [qw(Format Name id)],
+&>
+% }
+</&>
+<%init>
+my @Objects = RT::SavedSearches->new($session{CurrentUser})->_PrivacyObjects;
+push @Objects, RT::System->new( $session{'CurrentUser'} )
+    if $session{'CurrentUser'}->HasRight( Object=> $RT::System,
+                                          Right => 'SuperUser' );
+</%init>
+<%ARGS>
+$user_attrs => undef
+</%ARGS>

commit 16bd33996926c8dd8c8165d57b2bee88e0b82e21
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Fri Jun 18 16:51:03 2010 -0400

    Remove old cache cleaning code
    
    This cache has been irrelevant since
    36bf6181f1e4d867bcfec27bd29ad16d000898ec

diff --git a/share/html/Admin/Queues/Modify.html b/share/html/Admin/Queues/Modify.html
index c6ffe17..906ee39 100755
--- a/share/html/Admin/Queues/Modify.html
+++ b/share/html/Admin/Queues/Modify.html
@@ -153,7 +153,6 @@ if ($Create) {
     if ( defined $id && $id eq 'new' ) {
         my ($val, $msg) = $QueueObj->Create( Name => $Name );
         Abort("$msg") unless $val;
-        delete $session{'create_in_queues'};
 		push @results, $msg;
     }
     else {
@@ -164,7 +163,6 @@ if ($Create) {
     $current_tab = 'Admin/Queues/Modify.html?id='.$QueueObj->id;
 }
 if ( $QueueObj->Id ) {
-    delete $session{'create_in_queues'};
     my @attribs= qw(Description CorrespondAddress CommentAddress Name
         InitialPriority FinalPriority DefaultDueIn Sign Encrypt SubjectTag Disabled);
 

commit 61c48792ec527eb8e843b15d183a71f8cc0a41d5
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Mon Jun 28 14:34:36 2010 -0400

    Only show dashboards tab if you can see or subscribe to dashboards

diff --git a/share/html/Tools/Elements/Tabs b/share/html/Tools/Elements/Tabs
index 4e49795..aa75222 100644
--- a/share/html/Tools/Elements/Tabs
+++ b/share/html/Tools/Elements/Tabs
@@ -54,10 +54,6 @@
 
 <%INIT>
 my $tabs = {
-    a => {
-        title => loc('Dashboards'),
-        path  => 'Dashboards/index.html',
-    },
     b => {
         title => loc('Offline'),
         path  => 'Tools/Offline.html',
@@ -72,6 +68,16 @@ my $tabs = {
     },
 };
 
+my $can_see_dashboards = $session{CurrentUser}->HasRight(Right => 'SubscribeDashboard', Object => $RT::System)
+                       || RT::Dashboard->new($session{CurrentUser})->_PrivacyObjects;
+
+if ($can_see_dashboards) {
+    $tabs->{a} = {
+        title => loc('Dashboards'),
+        path  => 'Dashboards/index.html',
+    };
+}
+
 $m->callback( %ARGS, tabs => $tabs );
 
 foreach my $tab ( sort keys %{$tabs} ) {
diff --git a/share/html/Tools/index.html b/share/html/Tools/index.html
index 8e5e02b..26e0f47 100644
--- a/share/html/Tools/index.html
+++ b/share/html/Tools/index.html
@@ -54,11 +54,6 @@
 <%init>
 
 my $tabs = {
-    A => {
-        title       => loc('Dashboards'),
-        path        => '/Dashboards/index.html',
-        description => loc('Named, shared collection of portlets'),
-    },
     B => {
         title       => loc('Offline'),
         path        => '/Tools/Offline.html',
@@ -76,6 +71,17 @@ my $tabs = {
     },
 };
 
+my $can_see_dashboards = $session{CurrentUser}->HasRight(Right => 'SubscribeDashboard', Object => $RT::System)
+                       || RT::Dashboard->new($session{CurrentUser})->_PrivacyObjects;
+
+if ($can_see_dashboards) {
+    $tabs->{A} = {
+        title       => loc('Dashboards'),
+        path        => '/Dashboards/index.html',
+        description => loc('Named, shared collection of portlets'),
+    };
+}
+
 $m->callback( %ARGS, tabs => $tabs );
 
 </%init>

commit 8230eb42c12914cda4f870f3063adc8bf133db71
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 23 23:44:45 2010 +0400

    don't encode folded headers and tabs in EncodeToMIME
    
    * rfc822 allows you to put whole ascii into header field body,
      let's allow tab as well
    * if field is folded then do nothing special
    * use B encoding in other cases

diff --git a/lib/RT/Interface/Email.pm b/lib/RT/Interface/Email.pm
index f618c40..35a56a7 100755
--- a/lib/RT/Interface/Email.pm
+++ b/lib/RT/Interface/Email.pm
@@ -890,7 +890,7 @@ sub EncodeToMIME {
         return ($value);
     }
 
-    return ($value) unless $value =~ /[^\x20-\x7e]/;
+    return ($value) if $value =~ /^(?:[\t\x20-\x7e]|\x0D*\x0A[ \t])+$/s;
 
     $value =~ s/\s+$//;
 

commit c03aa80c28d310d5e4a37a986f554a8bafd6e7ef
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Tue Jun 29 18:11:52 2010 -0400

    Allow specifying different label and name for ComboBox values

diff --git a/share/html/Widgets/ComboBox b/share/html/Widgets/ComboBox
index 04f7b25..969ad71 100644
--- a/share/html/Widgets/ComboBox
+++ b/share/html/Widgets/ComboBox
@@ -59,7 +59,11 @@ my $z_index = 9999;
 <br style="display: none" /><span id="<% $Name %>_Button" class="combo-button">&#9660;</span><select name="List-<% $Name %>" id="<% $Name %>_List" class="combo-list" onchange="ComboBox_SimpleAttach(this, this.form['<% $Name %>']); " size="<% $Rows %>">
 <option style="display: none" value="">-</option>
 % foreach my $value (@Values) {
-        <option value="<%$value%>"><% $value%></option>
+%     if (ref($value) eq 'HASH') {
+          <option value="<%$value->{name}%>"><% $value->{label}%></option>
+%     } else {
+          <option value="<%$value%>"><% $value%></option>
+%     }
 % }
 </select>
 </div>

commit 2c0f47b9ebeae8fda06984e10bbe80b03d0bb8ab
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Tue Jun 29 18:15:05 2010 -0400

    POD likes newlines

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 11e6c0b..fbd0d59 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1323,6 +1323,7 @@ Set($PlainTextPre, 0);
 
 
 =item C<$PlainTextMono> 
+
 To display plaintext attachments,
 Set C<$PlainTextMono> to 1 to use monospaced font and preserve
 formatting, but unlike PlainTextPre, the text will wrap to fit into the

commit 9a9cef1dbebd5f544bc024488d0f86c41690bf53
Author: Shawn M Moore <sartak at bestpractical.com>
Date:   Tue Jun 29 18:19:49 2010 -0400

    New config $HideCustomFieldValidator
    
        This lets you hide the regular expression used to validate custom
        field values by using the regex's comment as a label.

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index fbd0d59..0e5405d 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1542,6 +1542,17 @@ Use this to set the default units for time entry to hours instead of minutes.
 
 Set($DefaultTimeUnitsToHours, 0);
 
+=item C<$HideCustomFieldValidator>
+
+Use this to hide the regular expression used to validate custom field values.
+This applies only to the custom field admin interface. The regular expression's
+first comment will be used as the label for that validator. For example, the
+validator C<(?#Digits)^[\d.]+$> will display as just C<Digits>.
+
+=cut
+
+Set($HideCustomFieldValidator, 0);
+
 =back
 
 =head1 L<Net::Server> (rt-server) Configuration
diff --git a/share/html/Admin/CustomFields/Modify.html b/share/html/Admin/CustomFields/Modify.html
index 5662226..d202988 100644
--- a/share/html/Admin/CustomFields/Modify.html
+++ b/share/html/Admin/CustomFields/Modify.html
@@ -234,6 +234,15 @@ my @CFvalidations = (
 
 $m->callback(CallbackName => 'ValidationPatterns', Values => \@CFvalidations);
 
+if (RT->Config->Get('HideCustomFieldValidator')) {
+    for my $pattern (@CFvalidations) {
+        next if ref($pattern);
+        if (my ($name) = $pattern =~ /\(\?\#(\w+)\)/) {
+            $pattern = { name => $pattern, label => $name };
+        }
+    }
+}
+
 </%INIT>
 <%ARGS>
 $id => undef

commit cd03dfc8f272ec8a6c0798dc0b829f5e81d5adc2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 29 03:35:14 2010 +0400

    indent and minor refactoring

diff --git a/share/html/Ticket/Elements/ShowHistory b/share/html/Ticket/Elements/ShowHistory
index d859483..2846f0f 100755
--- a/share/html/Ticket/Elements/ShowHistory
+++ b/share/html/Ticket/Elements/ShowHistory
@@ -50,17 +50,14 @@
 #   be generalized at some point.
 </%doc>
 <%perl>
-if ($ShowDisplayModes or $ShowTitle) {
+if ( $ShowDisplayModes or $ShowTitle ) {
     my $title = $ShowTitle
                     ? loc('History')
                     : '&nbsp;';
 
-    my $titleright;
-
-    if ($ShowDisplayModes) {
-        $titleright = '';
-        
-        if ($ShowHeaders) {
+    my $titleright = '';
+    if ( $ShowDisplayModes ) {
+        if ( $ShowHeaders ) {
             $titleright .= qq{<a href="$URIFile?id=} .
                            $Ticket->id.qq{">} .
                            loc("Brief headers") .
@@ -85,6 +82,7 @@ if ($ShowDisplayModes or $ShowTitle) {
 my @attachments = @{$Attachments->ItemsArrayRef()};
 my @attachment_content = @{$AttachmentContent->ItemsArrayRef()};
 
+my $i = 1;
 while ( my $Transaction = $Transactions->Next ) {
     my $skip = 0;
     $m->callback(
@@ -95,37 +93,36 @@ while ( my $Transaction = $Transactions->Next ) {
     );
     next if $skip;
 
-    $i++;
-
     my @trans_attachments = grep { $_->TransactionId == $Transaction->Id } @attachments;
 
     my $trans_content = {};
     grep { ($_->TransactionId == $Transaction->Id ) && ($trans_content->{$_->Id} = $_)  } @attachment_content;
 
-   
     my $IsLastTransaction = 0;
     if ( $OldestFirst ) {
         $IsLastTransaction = $Transactions->IsLast;
     } else {
-        $IsLastTransaction = 1 if ( $i == 1 );
+        $IsLastTransaction = 1 if $i == 1;
     }
 
     #Args is first because we're clobbering the "Attachments" parameter 
     $m->comp( 'ShowTransaction',
-            %ARGS,
+        %ARGS,
 
-              Ticket               => $Ticket,
-              Transaction          => $Transaction,
-              ShowHeaders          => $ShowHeaders,
-              RowNum               => $i,
-              Attachments          => \@trans_attachments,
-              AttachmentContent    => $trans_content,
-              LastTransaction      => $IsLastTransaction
- );
+        Ticket            => $Ticket,
+        Transaction       => $Transaction,
+        ShowHeaders       => $ShowHeaders,
+        RowNum            => $i,
+        Attachments       => \@trans_attachments,
+        AttachmentContent => $trans_content,
+        LastTransaction   => $IsLastTransaction
+    );
 
-# manually flush the content buffer after each txn, so the user sees
-# some update
-$m->flush_buffer(); 
+    # manually flush the content buffer after each txn,
+    # so the user sees some update
+    $m->flush_buffer;
+
+    $i++;
 }
 
 </%perl>
@@ -136,7 +133,7 @@ $m->flush_buffer();
 % }
 <%INIT>
 my $Transactions = new RT::Transactions($session{'CurrentUser'});
-if ($Tickets) {
+if ( $Tickets ) {
     while (my $t = $Tickets->Next) {
         $Transactions->LimitToTicket($t->id);
     }
@@ -144,18 +141,19 @@ if ($Tickets) {
     $Transactions = $Ticket->Transactions;
 }
 
-
 my $OldestFirst = RT->Config->Get( 'OldestTransactionsFirst', $session{'CurrentUser'} );
 my $SortOrder = $OldestFirst? 'ASC': 'DESC';
-$Transactions->OrderByCols( { FIELD => 'Created',
-                              ORDER => $SortOrder },
-                            { FIELD => 'id',
-                              ORDER => $SortOrder },
-                          );
-
-my $i;
-$Attachments ||=  $m->comp('/Ticket/Elements/FindAttachments', Ticket => $Ticket, Tickets => $Tickets || undef);
-$AttachmentContent ||= $m->comp('/Ticket/Elements/LoadTextAttachments', Ticket => $Ticket);
+$Transactions->OrderByCols(
+    { FIELD => 'Created', ORDER => $SortOrder },
+    { FIELD => 'id', ORDER => $SortOrder },
+);
+
+$Attachments ||= $m->comp('/Ticket/Elements/FindAttachments',
+    Ticket => $Ticket, Tickets => $Tickets,
+);
+$AttachmentContent ||= $m->comp('/Ticket/Elements/LoadTextAttachments',
+    Ticket => $Ticket
+);
 
 </%INIT>
 <%ARGS>

commit 2f3eebe69e5d5e71a663560496d8daf3a4c594a8
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Jun 29 06:57:09 2010 +0400

    prepare attachments only once for whole history

diff --git a/share/html/Ticket/Elements/ShowHistory b/share/html/Ticket/Elements/ShowHistory
index 2846f0f..f8c7101 100755
--- a/share/html/Ticket/Elements/ShowHistory
+++ b/share/html/Ticket/Elements/ShowHistory
@@ -79,9 +79,6 @@ if ( $ShowDisplayModes or $ShowTitle ) {
 
 <div id="ticket-history">
 <%perl>
-my @attachments = @{$Attachments->ItemsArrayRef()};
-my @attachment_content = @{$AttachmentContent->ItemsArrayRef()};
-
 my $i = 1;
 while ( my $Transaction = $Transactions->Next ) {
     my $skip = 0;
@@ -93,11 +90,6 @@ while ( my $Transaction = $Transactions->Next ) {
     );
     next if $skip;
 
-    my @trans_attachments = grep { $_->TransactionId == $Transaction->Id } @attachments;
-
-    my $trans_content = {};
-    grep { ($_->TransactionId == $Transaction->Id ) && ($trans_content->{$_->Id} = $_)  } @attachment_content;
-
     my $IsLastTransaction = 0;
     if ( $OldestFirst ) {
         $IsLastTransaction = $Transactions->IsLast;
@@ -113,8 +105,8 @@ while ( my $Transaction = $Transactions->Next ) {
         Transaction       => $Transaction,
         ShowHeaders       => $ShowHeaders,
         RowNum            => $i,
-        Attachments       => \@trans_attachments,
-        AttachmentContent => $trans_content,
+        Attachments       => $attachments{ $Transaction->id } || [],
+        AttachmentContent => \%attachment_content,
         LastTransaction   => $IsLastTransaction
     );
 
@@ -155,6 +147,12 @@ $AttachmentContent ||= $m->comp('/Ticket/Elements/LoadTextAttachments',
     Ticket => $Ticket
 );
 
+my %attachments;
+push @{ $attachments{ $_->TransactionId } ||= [] }, $_
+    foreach @{ $Attachments->ItemsArrayRef };
+my %attachment_content = map { $_->id => $_ }
+    @{ $AttachmentContent->ItemsArrayRef };
+
 </%INIT>
 <%ARGS>
 $URIFile => RT->Config->Get('WebPath')."/Ticket/Display.html"

commit 6766e82221b4a5ded461db462acd784638ade65a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 03:43:32 2010 +0400

    minor refactoring

diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index 9ecad76..0d5a0e3 100755
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -1493,7 +1493,7 @@ sub _NewTransaction {
 
 =head2 Transactions
 
-  Returns an RT::Transactions object of all transactions on this record object
+Returns an L<RT::Transactions> object of all transactions on this record object
 
 =cut
 
@@ -1502,8 +1502,6 @@ sub Transactions {
 
     use RT::Transactions;
     my $transactions = RT::Transactions->new( $self->CurrentUser );
-
-    #If the user has no rights, return an empty object
     $transactions->Limit(
         FIELD => 'ObjectId',
         VALUE => $self->id,
@@ -1513,9 +1511,10 @@ sub Transactions {
         VALUE => ref($self),
     );
 
-    return ($transactions);
+    return $transactions;
 }
 
+
 # }}}
 # }}}
 #

commit 69bf96411391811ddd71af85c4a2be9df73f4889
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 03:44:24 2010 +0400

    Attachments and TextAttachments for all records in the system

diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index 0d5a0e3..299f11f 100755
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -1514,6 +1514,72 @@ sub Transactions {
     return $transactions;
 }
 
+=head2 Attachments
+
+Returns an L<RT::Attachments> object of all attachments on this record object
+(for all its L</Transactions>).
+
+By default Content and Headers of attachments are not fetched right away from
+database. Use C<WithContent> and C<WithHeaders> options to override this.
+
+=cut
+
+sub Attachments {
+    my $self = shift;
+    my %args = (
+        WithHeaders => 0,
+        WithContent => 0,
+        @_
+    );
+    my @columns = qw(
+        id TransactionId Parent MessageId
+        Subject Filename
+        ContentType ContentEncoding
+        Creator Created
+    );
+    push @columns, 'Headers' if $args{'WithHeaders'};
+    push @columns, 'Content' if $args{'WithContent'};
+
+    my $res = RT::Attachments->new( $self->CurrentUser );
+    $res->Columns( @columns );
+    my $txn_alias = $res->TransactionAlias;
+    $res->Limit(
+        ALIAS => $txn_alias,
+        FIELD => 'ObjectType',
+        VALUE => ref($self),
+    );
+    $res->Limit(
+        ALIAS => $txn_alias,
+        FIELD => 'ObjectId',
+        VALUE => $self->id,
+    );
+    return $res;
+}
+
+=head2 TextAttachments
+
+Returns an L<RT::Attachments> object of all attachments, like L<Attachments>,
+but only those that are text.
+
+By default Content and Headers are fetched. Use C<WithContent> and
+C<WithHeaders> options to override this.
+
+=cut
+
+sub TextAttachments {
+    my $self = shift;
+    my $res = $self->Attachments(
+        WithHeaders => 1,
+        WithContent => 1,
+        @_
+    );
+    $res->Limit( FIELD => 'ContentType', OPERATOR => '=', VALUE => 'text/plain');
+    $res->Limit( FIELD => 'ContentType', OPERATOR => 'STARTSWITH', VALUE => 'message/');
+    $res->Limit( FIELD => 'ContentType', OPERATOR => '=', VALUE => 'text');
+    $res->Limit( FIELD => 'Filename', OPERATOR => 'IS', VALUE => 'NULL')
+        if RT->Config->Get( 'SuppressInlineTextFiles', $self->CurrentUser );
+    return $res;
+}
 
 # }}}
 # }}}

commit ec8e1b524edecc661bf1c030e4604d9dc8c2ceff
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 03:49:17 2010 +0400

    Attachments and TextAttachments customizations for tickets

diff --git a/lib/RT/Ticket_Overlay.pm b/lib/RT/Ticket_Overlay.pm
index 2c54a22..470f2fb 100755
--- a/lib/RT/Ticket_Overlay.pm
+++ b/lib/RT/Ticket_Overlay.pm
@@ -3554,6 +3554,84 @@ sub Transactions {
 
 # }}}
 
+=head2 Attachments
+
+Customization of L<RT::Record/Attachments> for tickets.
+
+=cut
+
+sub Attachments {
+    my $self = shift;
+    my %args = (
+        WithHeaders => 0,
+        WithContent => 0,
+        @_
+    );
+    my $res = RT::Attachments->new( $self->CurrentUser );
+    unless ( $self->CurrentUserHasRight('ShowTicket') ) {
+        $res->Limit(
+            SUBCLAUSE => 'acl',
+            FIELD    => 'id',
+            VALUE    => 0,
+            ENTRYAGGREGATOR => 'AND'
+        );
+        return $res;
+    }
+
+    my @columns = qw(
+        id TransactionId Parent MessageId
+        Subject Filename
+        ContentType ContentEncoding
+        Creator Created
+    );
+    push @columns, 'Headers' if $args{'WithHeaders'};
+    push @columns, 'Content' if $args{'WithContent'};
+
+    $res->Columns( @columns );
+    my $txn_alias = $res->TransactionAlias;
+    $res->Limit(
+        ALIAS => $txn_alias,
+        FIELD => 'ObjectType',
+        VALUE => ref($self),
+    );
+    my $ticket_alias = $res->Join(
+        ALIAS1 => $txn_alias,
+        FIELD1 => 'id',
+        TABLE2 => 'Tickets',
+        FIELD2 => 'EffectiveId',
+    );
+    $res->Limit(
+        ALIAS => $ticket_alias,
+        FIELD => 'EffectiveId',
+        VALUE => $self->id,
+    );
+    return $res;
+}
+
+=head2 Attachments
+
+Customization of L<RT::Record/TextAttachments> for tickets.
+
+=cut
+
+sub TextAttachments {
+    my $self = shift;
+
+    my $res = $self->SUPER::TextAttachments( @_ );
+    unless ( $self->CurrentUserHasRight('ShowTicketComments') ) {
+        # if the user may not see comments do not return them
+        $res->Limit(
+            SUBCLAUSE => 'ACL',
+            ALIAS     => $res->TransactionAlias,
+            FIELD     => 'Type',
+            OPERATOR  => '!=',
+            VALUE     => 'Comment',
+        );
+    }
+
+    return $res;
+}
+
 
 # {{{ TransactionCustomFields
 

commit 5d4a0aa59c4b9c7460b142a357fc87bb142be526
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 03:51:58 2010 +0400

    replace mason comp with new methods

diff --git a/share/html/Ticket/Elements/LoadTextAttachments b/share/html/Ticket/Elements/LoadTextAttachments
index 84732b9..4b1e68c 100644
--- a/share/html/Ticket/Elements/LoadTextAttachments
+++ b/share/html/Ticket/Elements/LoadTextAttachments
@@ -47,47 +47,10 @@
 %# END BPS TAGGED BLOCK }}}
 <%INIT>
 
-my $attachments = RT::Attachments->new( $session{'CurrentUser'} );
+# DON'T USE IT. it's here for backwards
 
-$attachments->Columns( qw(id Content ContentType TransactionId ContentEncoding));
-
-if ( $Ticket->CurrentUserHasRight('ShowTicket') ) {
-    my $transactions = $attachments->NewAlias('Transactions');
-    $attachments->Join( ALIAS1 => 'main',
-                                           FIELD1 => 'TransactionId',
-                                           ALIAS2 => $transactions,
-                                           FIELD2 => 'id' );
-    
-    my $tickets = $attachments->NewAlias('Tickets');
-
-
-    $attachments->Join( ALIAS1 => $transactions,
-                        FIELD1 => 'ObjectId',
-                        ALIAS2 => $tickets,
-                        FIELD2 => 'id' );
-
-    $attachments->Limit( ALIAS => $transactions,
-                         FIELD => 'ObjectType',
-                        VALUE => 'RT::Ticket');
-
-
-    $attachments->Limit( ALIAS => $tickets,
-                         FIELD => 'EffectiveId',
-                         VALUE => $Ticket->id() );
-    # if the user may not see comments do not return them
-    unless ( $Ticket->CurrentUserHasRight('ShowTicketComments') ) {
-        $attachments->Limit( ALIAS    => $transactions, FIELD    => 'Type', OPERATOR => '!=', VALUE    => "Comment" );
-    }
-
-    $attachments->Limit ( FIELD => 'ContentType', OPERATOR => '=', VALUE => 'text/plain');
-    $attachments->Limit ( FIELD => 'ContentType', OPERATOR => 'STARTSWITH', VALUE => 'message/');
-    $attachments->Limit ( FIELD => 'ContentType', OPERATOR => '=', VALUE => 'text');
-    $attachments->Limit ( FIELD => 'Filename', OPERATOR => 'IS', VALUE => 'NULL')
-        if RT->Config->Get('SuppressInlineTextFiles', $Ticket->CurrentUser );
-}
-return ($attachments);
+return $Ticket->TextAttachments;
 </%INIT>
 <%ARGS>
 $Ticket => undef
 </%ARGS>
-

commit 42d043c4d3727c7793b60b93d75271d8f1247990
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 03:59:30 2010 +0400

    use new method, other code there we have is messy

diff --git a/share/html/Ticket/Elements/FindAttachments b/share/html/Ticket/Elements/FindAttachments
index 1ce75fd..344a6a1 100644
--- a/share/html/Ticket/Elements/FindAttachments
+++ b/share/html/Ticket/Elements/FindAttachments
@@ -46,50 +46,47 @@
 %# 
 %# END BPS TAGGED BLOCK }}}
 <%INIT>
-my %documents;
-
-#A default implementation here loops through all transactions and pulls out all their attachments.
+# A default implementation here loops through all transactions and pulls out all their attachments.
 # We end up doing an end-run around that to get a bit more performance
 
-# We force the cache of ticket transactions to get populated up front. otherwise, the 
+# We force the cache of ticket transactions to get populated up front. otherwise, the
 # code that looks at attachments will look at each one in turn.
+
+return $Ticket->Attachments unless $Tickets;
+
 my $attachments = RT::Attachments->new( $session{'CurrentUser'} );
+$attachments->Columns( qw(
+    id TransactionId Parent MessageId
+    Subject Filename
+    ContentType ContentEncoding
+    Creator Created
+) );
 
-$attachments->Columns( qw( Id Filename Headers Subject Parent ContentEncoding ContentType TransactionId Created));
+my $transactions = $attachments->TransactionsAlias;
+my $tickets = $attachments->Join(
+    ALIAS1 => $transactions,
+    FIELD1 => 'ObjectId',
+    TABLE2 => 'Tickets',
+    FIELD2 => 'id',
+);
 
-my $transactions = $attachments->NewAlias('Transactions');
-$attachments->Join( ALIAS1 => 'main',
-		    FIELD1 => 'TransactionId',
-		    ALIAS2 => $transactions,
-		    FIELD2 => 'id' );
-    
-my $tickets = $attachments->NewAlias('Tickets');
+$attachments->Limit(
+    ALIAS => $transactions,
+    FIELD => 'ObjectType',
+    VALUE => 'RT::Ticket',
+);
 
-  $attachments->Join( ALIAS1 => $transactions,                         
-                        FIELD1 => 'ObjectId',
-                        ALIAS2 => $tickets,
-                        FIELD2 => 'id' );
-    
-    $attachments->Limit( ALIAS => $transactions,
-                         FIELD => 'ObjectType',
-                        VALUE => 'RT::Ticket');
-if ($Tickets) {
-    while ($Ticket = $Tickets->Next) {
-	$attachments->Limit( ALIAS => $tickets,
-			     FIELD => 'EffectiveId',
-			     VALUE => $Ticket->id() );
-    }
-} else {
-    $attachments->Limit( ALIAS => $tickets,
-			 FIELD => 'EffectiveId',
-			 VALUE => $Ticket->id() );
+while ( my $Ticket = $Tickets->Next) {
+    $attachments->Limit(
+        ALIAS => $tickets,
+        FIELD => 'EffectiveId',
+        VALUE => $Ticket->id,
+    );
 }
 
-
 return ($attachments);
 </%INIT>
 <%ARGS>
 $Ticket => undef
 $Tickets => undef
 </%ARGS>
-

commit d45e999606c7240ea7fbedf33706735b0f6b567b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Jun 30 07:23:21 2010 +0400

    first pass on generic ShowHistory, still on ticket's ShowTransaction

diff --git a/share/html/Elements/ShowHistory b/share/html/Elements/ShowHistory
new file mode 100644
index 0000000..73f7b16
--- /dev/null
+++ b/share/html/Elements/ShowHistory
@@ -0,0 +1,151 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%# 
+%# COPYRIGHT:
+%# 
+%# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
+%#                                          <jesse at 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 }}}
+<%perl>
+if ( $ShowDisplayModes or $ShowTitle ) {
+    my $titleright = '';
+    if ( $ShowDisplayModes ) {
+        $Page ||= $m->request_path;
+        if ( $ShowHeaders ) {
+            $titleright .=
+                '<a href="'. RT->Config->Get('WebPath') . $Page
+                . '?id='. $Object->id. '">'
+                . loc("Brief headers") .'</a>'
+                . ' &mdash; '
+                . '<span class="selected">'. loc("Full headers") .'</span>';
+        }
+        else {
+            $titleright .= '<span class="selected">'. loc("Brief headers") .'</span>'
+                .' &mdash; '
+                .'<a href="'. RT->Config->Get('WebPath') . $Page
+                . '?ShowHeaders=1&id='. $Object->id. '">'
+                . loc("Full headers") .'</a>';
+        }
+    }
+</%perl>
+<div class="history">
+<& /Widgets/TitleBoxStart,
+    title => $ShowTitle ? loc('History') : '&nbsp;',
+    titleright_raw => $titleright,
+&>
+% }
+
+<div id="ticket-history">
+<%perl>
+my $i = 1;
+while ( my $Transaction = $Transactions->Next ) {
+    my $skip = 0;
+    $m->callback(
+        %ARGS,
+        Transaction   => $Transaction,
+        skip          => \$skip,
+        CallbackName  => 'SkipTransaction',
+    );
+    next if $skip;
+
+    my $IsLastTransaction = 0;
+    if ( $OldestFirst ) {
+        $IsLastTransaction = $Transactions->IsLast;
+    } else {
+        $IsLastTransaction = 1 if $i == 1;
+    }
+
+    #Args is first because we're clobbering the "Attachments" parameter 
+    $m->comp( '/Ticket/Elements/ShowTransaction',
+        %ARGS,
+
+        Ticket            => $Object,
+        Transaction       => $Transaction,
+        ShowHeaders       => $ShowHeaders,
+        RowNum            => $i,
+        Attachments       => $attachments{ $Transaction->id } || [],
+        AttachmentContent => \%attachment_content,
+        LastTransaction   => $IsLastTransaction
+    );
+
+    # manually flush the content buffer after each txn,
+    # so the user sees some update
+    $m->flush_buffer;
+
+    $i++;
+}
+
+</%perl>
+</div>
+% if ($ShowDisplayModes or $ShowTitle) {
+<& /Widgets/TitleBoxEnd &>
+</div>
+% }
+<%INIT>
+my $Transactions = $Object->Transactions;
+
+my $OldestFirst = RT->Config->Get(
+    OldestTransactionsFirst => $session{'CurrentUser'}
+);
+my $SortOrder = $OldestFirst? 'ASC': 'DESC';
+$Transactions->OrderByCols(
+    { FIELD => 'Created', ORDER => $SortOrder },
+    { FIELD => 'id', ORDER => $SortOrder },
+);
+
+my %attachments;
+push @{ $attachments{ $_->TransactionId } ||= [] }, $_
+    foreach @{ $Attachments->ItemsArrayRef };
+my %attachment_content = map { $_->id => $_ }
+    @{ $AttachmentContent->ItemsArrayRef };
+
+</%INIT>
+<%ARGS>
+$Object
+$Attachments       => $Object->Attachments( WithHeaders => 1 )
+$AttachmentContent => $Object->TextAttachments
+
+$Page              => undef 
+$ShowHeaders       => 0
+$ShowTitle         => 1
+$ShowDisplayModes  => 1
+</%ARGS>

-----------------------------------------------------------------------


More information about the Rt-commit mailing list