[Rt-commit] rt branch, 3.9-trunk, updated. rt-3.9.4-431-gd99c16e

Jesse Vincent jesse at bestpractical.com
Tue Nov 9 10:50:26 EST 2010


The branch, 3.9-trunk has been updated
       via  d99c16e1f0837aca581ac7c5b55346e00ff5dbc6 (commit)
       via  d1e89fa3fed7141d28b969742d377a1490c75c18 (commit)
       via  9009ac0508e236d500497be037990fbea0899381 (commit)
       via  56a03c2bd89dc336381058b8fa0628255c767d94 (commit)
       via  1ddfe480ae2d3ff7f08cd6eabd8d36ce1c8456c4 (commit)
       via  6f1ee4083789859e5bc30d767ba7e18f27ad78b2 (commit)
       via  01882e342a23f7084774010b6685e3d09c2003fe (commit)
      from  061f9424ab60ce9244d7f4f84a4796f02dff514d (commit)

Summary of changes:
 etc/RT_Config.pm.in             |   96 +++++++++++++++++++++-----------------
 lib/RT/Config.pm                |    8 +++-
 lib/RT/Interface/Web/Handler.pm |    2 +-
 lib/RT/Lifecycle.pm             |   75 ++++++++++++++++++------------
 share/html/Elements/Tabs        |   17 +++++--
 t/lifecycles/utils.pl           |   31 ++++++-------
 6 files changed, 133 insertions(+), 96 deletions(-)

- Log -----------------------------------------------------------------
commit 01882e342a23f7084774010b6685e3d09c2003fe
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Nov 1 04:42:21 2010 +0300

    implement Lifecycle->actions
    
    * make it possible to order actions independently
    * make it possible to define more then one action for the same
      transition
    * delete transition_lable and transition_action methods

diff --git a/lib/RT/Lifecycle.pm b/lib/RT/Lifecycle.pm
index b2620e4..ca026e3 100644
--- a/lib/RT/Lifecycle.pm
+++ b/lib/RT/Lifecycle.pm
@@ -77,10 +77,10 @@ __PACKAGE__->register_rights;
 #               'status_y -> status_y' => 'right',
 #               ....
 #            }
-#            actions => {
-#               'status_y -> status_y' => [ transition_label, transition_action ],
+#            actions => [
+#               { from => 'a', to => 'b', label => '...', update => '...' },
 #               ....
-#            }
+#            ]
 #        }
 #    }
 
@@ -167,7 +167,7 @@ Returns name of the laoded lifecycle.
 
 sub name { return $_[0]->{'name'} }
 
-=head2 Getting statuses and validatiing.
+=head2 Getting statuses and validating.
 
 Methods to get statuses in different sets or validating them.
 
@@ -411,45 +411,40 @@ sub register_rights {
     }
 }
 
-=head3 transition_label
-
-Takes two statuses (from -> to) and returns label for the transition,
-if custom label is not defined then default equal to the second status.
+=head3 actions
 
-=cut
-
-sub transition_label {
-    my $self = shift;
-    my $from = shift;
-    my $to = shift;
-    return $self->{'data'}{'actions'}{ $from .' -> '. $to }[0] || $to;
-}
-
-=head3 transition_action
-
-Takes two statuses (from -> to) and returns action for the transition.
-
-At this moment it can be:
+Takes a status and returns list of defined actions for the status. Each
+element in the list is a hash reference with the following key/value
+pairs:
 
 =over 4
 
-=item '' (empty string) - no action (default)
+=item from - either the status or *
 
-=item hide - hide this button from the Web UI
+=item to - next status
 
-=item comment - comment page is shown
+=item label - label of the action
 
-=item respond - reply page is shown
+=item update - 'Respond', 'Comment' or '' (empty string)
 
 =back
 
 =cut
 
-sub transition_action {
+sub actions {
     my $self = shift;
-    my $from = shift;
-    my $to = shift;
-    return $self->{'data'}{'actions'}{ $from .' -> '. $to }[1] || '';
+    my $from = shift || return ();
+
+    $self->fill_cache unless keys %LIFECYCLES_CACHE;
+
+    my @res = grep $_->{'from'} eq $from || ( $_->{'from'} eq '*' && $_->{'to'} ne $from ),
+        @{ $self->{'data'}{'actions'} };
+
+    # skip '* -> x' if there is '$from -> x'
+    foreach my $e ( grep $_->{'from'} eq '*', @res ) {
+        $e = undef if grep $_->{'from'} ne '*' && $_->{'to'} eq $e->{'to'}, @res;
+    }
+    return grep defined, @res;
 }
 
 =head2 Creation and manipulation
@@ -562,6 +557,8 @@ sub fill_cache {
 #    $map = $map->content or return;
 
     %LIFECYCLES_CACHE = %LIFECYCLES = %$map;
+    $_ = { %$_ } foreach values %LIFECYCLES_CACHE;
+
     my %all = (
         '' => [],
         initial => [],
@@ -585,6 +582,24 @@ sub fill_cache {
         push @{ $all{''} }, @{ $all{ $type } } if $type;
     }
     $LIFECYCLES_CACHE{''} = \%all;
+
+    foreach my $lifecycle ( values %LIFECYCLES_CACHE ) {
+        my @res;
+        if ( ref $lifecycle->{'actions'} eq 'HASH' ) {
+            foreach my $k ( sort keys %{ $lifecycle->{'actions'} } ) {
+                push @res, $k, $lifecycle->{'actions'}{ $k };
+            }
+        } elsif ( ref $lifecycle->{'actions'} eq 'ARRAY' ) {
+            @res = @{ $lifecycle->{'actions'} };
+        }
+
+        my @tmp = splice @res;
+        while ( my ($transition, $info) = splice @tmp, 0, 2 ) {
+            my ($from, $to) = split /\s*->\s*/, $transition, 2;
+            push @res, { from => $from, to => $to, label => $info->[0], update => $info->[1] };
+        }
+        $lifecycle->{'actions'} = \@res;
+    }
     return;
 }
 

commit 6f1ee4083789859e5bc30d767ba7e18f27ad78b2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Nov 1 04:45:22 2010 +0300

    describe new format

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 7a14276..8898163 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1914,23 +1914,21 @@ apropriate.
 
 =head3 Labeling and defining actions
 
-Each transition can be named, by default it's named as the end state.
+For each transition you can define an action that will be shown in the UI.
 
-Each action may be annotated with B<Comment>, B<Respond> or B<Hidden>.
+Each action annotated with label and update type.
 
-For example, you may want your staff to write a reply to the end user
-when they change status from B<new> to B<open>.
-
-Using B<Hide>, it's possible to hide the B<open> -> B<delete> from the ticket's
-main view, while still allowing it from the basics page and API.
-
-Neither B<Comment> nor B<Respond> are mandatory.
+Update type can be B<Comment>, B<Respond> or absent. For example, you may
+want your staff to write a reply to the end user when they change status
+from B<new> to B<open>. Neither B<Comment> nor B<Respond> are mandatory
+and user may leave message empty.
 
 Use the following format to define labels and actions of transitions:
 
     default => {
         ...
         actions => {
+        actions => [
             'new -> open'     => ['Open it', 'Respond'],
             'new -> resolved' => ['Resolve', 'Comment'],
             'new -> rejected' => ['Reject',  'Respond'],
@@ -1939,13 +1937,29 @@ Use the following format to define labels and actions of transitions:
             'open -> stalled'  => ['Stall',   'Comment'],
             'open -> resolved' => ['Resolve', 'Comment'],
             'open -> rejected' => ['Reject',  'Respond'],
-            'open -> deleted'  => ['Delete',  'hide'],
 
             'stalled -> open'  => ['Open it',  ''],
             'resolved -> open' => ['Re-open',  'Comment'],
             'rejected -> open' => ['Re-open',  'Comment'],
             'deleted -> open'  => ['Undelete', ''],
-        },
+        ],
+        ...
+    },
+
+In addition you can define multiple actions for the same transition.
+Also, it's possible to use '* -> x' to match more than one transition.
+For example:
+
+    default => {
+        ...
+        actions => [
+            ...
+            'new -> rejected' => ['Reject', 'Respond'],
+            'new -> rejected' => ['Quick Reject'],
+            ...
+            '*   -> deleted'  => ['Delete'],
+            ...
+        ],
         ...
     },
 
@@ -1989,7 +2003,7 @@ Set(%Lifecycles,
             '* -> rejected' => 'ModifyTicket',
             '* -> *'        => 'ModifyTicket',
         },
-        actions => {
+        actions => [
 
             # 'from -> to'    => [action text, Respond/Comment/hide/''],
             'new -> open'     => [ 'Open it', 'Respond' ],
@@ -2007,7 +2021,7 @@ Set(%Lifecycles,
             'rejected -> open' => [ 'Re-open',  'Comment' ],
             'deleted -> open'  => [ 'Undelete', '' ],
             'open -> new'      => [ 'New',      'hide' ],
-        },
+        ],
     },
 );
 

commit 1ddfe480ae2d3ff7f08cd6eabd8d36ce1c8456c4
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Mon Nov 1 04:45:37 2010 +0300

    no need to hide actions

diff --git a/t/lifecycles/utils.pl b/t/lifecycles/utils.pl
index 21abeb2..0ea6f77 100644
--- a/t/lifecycles/utils.pl
+++ b/t/lifecycles/utils.pl
@@ -30,7 +30,6 @@ Set(\%Lifecycles,
             'open -> stalled'  => ['Stall',   'Comment'],
             'open -> resolved' => ['Resolve', 'Comment'],
             'open -> rejected' => ['Reject',  'Respond'],
-            'open -> deleted'  => ['Delete',  'hide'],
 
             'stalled -> open'  => ['Open It',  ''],
             'resolved -> open' => ['Re-open',  'Comment'],

commit 56a03c2bd89dc336381058b8fa0628255c767d94
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Tue Nov 2 07:23:04 2010 +0300

    Name action properties, positionals are extensible

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index 8898163..002f523 100755
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -1929,19 +1929,19 @@ Use the following format to define labels and actions of transitions:
         ...
         actions => {
         actions => [
-            'new -> open'     => ['Open it', 'Respond'],
-            'new -> resolved' => ['Resolve', 'Comment'],
-            'new -> rejected' => ['Reject',  'Respond'],
-            'new -> deleted'  => ['Delete',  ''],
-
-            'open -> stalled'  => ['Stall',   'Comment'],
-            'open -> resolved' => ['Resolve', 'Comment'],
-            'open -> rejected' => ['Reject',  'Respond'],
-
-            'stalled -> open'  => ['Open it',  ''],
-            'resolved -> open' => ['Re-open',  'Comment'],
-            'rejected -> open' => ['Re-open',  'Comment'],
-            'deleted -> open'  => ['Undelete', ''],
+            'new -> open'     => { label => 'Open it', update => 'Respond' },
+            'new -> resolved' => { label => 'Resolve', update => 'Comment' },
+            'new -> rejected' => { label => 'Reject',  update => 'Respond' },
+            'new -> deleted'  => { label => 'Delete' },
+
+            'open -> stalled'  => { label => 'Stall',   update => 'Comment' },
+            'open -> resolved' => { label => 'Resolve', update => 'Comment' },
+            'open -> rejected' => { label => 'Reject',  update => 'Respond' },
+
+            'stalled -> open'  => { label => 'Open it' },
+            'resolved -> open' => { label => 'Re-open', update => 'Comment' },
+            'rejected -> open' => { label => 'Re-open', update => 'Comment' },
+            'deleted -> open'  => { label => 'Undelete' },
         ],
         ...
     },
@@ -1954,10 +1954,10 @@ For example:
         ...
         actions => [
             ...
-            'new -> rejected' => ['Reject', 'Respond'],
-            'new -> rejected' => ['Quick Reject'],
+            'new -> rejected' => { label => 'Reject', update => 'Respond' },
+            'new -> rejected' => { label => 'Quick Reject' },
             ...
-            '*   -> deleted'  => ['Delete'],
+            '* -> deleted' => { label => 'Delete' },
             ...
         ],
         ...
@@ -2004,23 +2004,19 @@ Set(%Lifecycles,
             '* -> *'        => 'ModifyTicket',
         },
         actions => [
-
-            # 'from -> to'    => [action text, Respond/Comment/hide/''],
-            'new -> open'     => [ 'Open it', 'Respond' ],
-            'new -> resolved' => [ 'Resolve', 'Comment' ],
-            'new -> rejected' => [ 'Reject',  'Respond' ],
-            'new -> deleted'  => [ 'Delete',  '' ],
-
-            'open -> stalled'  => [ 'Stall',   'Comment' ],
-            'open -> resolved' => [ 'Resolve', 'Comment' ],
-            'open -> rejected' => [ 'Reject',  'Respond' ],
-            'open -> deleted'  => [ 'Delete',  'hide' ],
-
-            'stalled -> open'  => [ 'Open it',  '' ],
-            'resolved -> open' => [ 'Re-open',  'Comment' ],
-            'rejected -> open' => [ 'Re-open',  'Comment' ],
-            'deleted -> open'  => [ 'Undelete', '' ],
-            'open -> new'      => [ 'New',      'hide' ],
+            'new -> open'      => { label => 'Open It',  update => 'Respond' },
+            'new -> resolved'  => { label => 'Resolve',  update => 'Comment' },
+            'new -> rejected'  => { label => 'Reject',   update => 'Respond' },
+            'new -> deleted'   => { label => 'Delete'                        },
+
+            'open -> stalled'  => { label => 'Stall',    update => 'Comment' },
+            'open -> resolved' => { label => 'Resolve',  update => 'Comment' },
+            'open -> rejected' => { label => 'Reject',   update => 'Respond' },
+
+            'stalled -> open'  => { label => 'Open It'                       },
+            'resolved -> open' => { label => 'Re-open',  update => 'Comment' },
+            'rejected -> open' => { label => 'Re-open',  update => 'Comment' },
+            'deleted -> open'  => { label => 'Undelete'                      },
         ],
     },
 );
diff --git a/lib/RT/Lifecycle.pm b/lib/RT/Lifecycle.pm
index ca026e3..d611ba9 100644
--- a/lib/RT/Lifecycle.pm
+++ b/lib/RT/Lifecycle.pm
@@ -596,7 +596,7 @@ sub fill_cache {
         my @tmp = splice @res;
         while ( my ($transition, $info) = splice @tmp, 0, 2 ) {
             my ($from, $to) = split /\s*->\s*/, $transition, 2;
-            push @res, { from => $from, to => $to, label => $info->[0], update => $info->[1] };
+            push @res, { %$info, from => $from, to => $to };
         }
         $lifecycle->{'actions'} = \@res;
     }
diff --git a/t/lifecycles/utils.pl b/t/lifecycles/utils.pl
index 0ea6f77..33813e9 100644
--- a/t/lifecycles/utils.pl
+++ b/t/lifecycles/utils.pl
@@ -22,19 +22,19 @@ Set(\%Lifecycles,
             deleted  => [qw(open)],
         },
         actions => {
-            'new -> open'     => ['Open It', 'Respond'],
-            'new -> resolved' => ['Resolve', 'Comment'],
-            'new -> rejected' => ['Reject',  'Respond'],
-            'new -> deleted'  => ['Delete',  ''],
+            'new -> open'     => {label => 'Open It', update => 'Respond'},
+            'new -> resolved' => {label => 'Resolve', update => 'Comment'},
+            'new -> rejected' => {label => 'Reject',  update => 'Respond'},
+            'new -> deleted'  => {label => 'Delete',  update => ''},
 
-            'open -> stalled'  => ['Stall',   'Comment'],
-            'open -> resolved' => ['Resolve', 'Comment'],
-            'open -> rejected' => ['Reject',  'Respond'],
+            'open -> stalled'  => {label => 'Stall',   update => 'Comment'},
+            'open -> resolved' => {label => 'Resolve', update => 'Comment'},
+            'open -> rejected' => {label => 'Reject',  update => 'Respond'},
 
-            'stalled -> open'  => ['Open It',  ''],
-            'resolved -> open' => ['Re-open',  'Comment'],
-            'rejected -> open' => ['Re-open',  'Comment'],
-            'deleted -> open'  => ['Undelete', ''],
+            'stalled -> open'  => {label => 'Open It',  update => ''},
+            'resolved -> open' => {label => 'Re-open',  update => 'Comment'},
+            'rejected -> open' => {label => 'Re-open',  update => 'Comment'},
+            'deleted -> open'  => {label => 'Undelete', update => ''},
         },
     },
     delivery => {
@@ -49,11 +49,11 @@ Set(\%Lifecycles,
             delivered => [],
         },
         actions => {
-            'ordered -> on way'   => ['Put On Way', 'Respond'],
-            'ordered -> delayed'  => ['Delay',      'Respond'],
+            'ordered -> on way'   => {label => 'Put On Way', update => 'Respond'},
+            'ordered -> delayed'  => {label => 'Delay',      update => 'Respond'},
 
-            'on way -> delivered' => ['Done',       'Respond'],
-            'delayed -> on way'   => ['Put On Way', 'Respond'],
+            'on way -> delivered' => {label => 'Done',       update => 'Respond'},
+            'delayed -> on way'   => {label => 'Put On Way', update => 'Respond'},
         },
     },
 );

commit 9009ac0508e236d500497be037990fbea0899381
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Wed Nov 3 07:58:02 2010 +0300

    use simple merge for HASH options
    
    RT site config wins, then core config, then extension site config,
    then extension core config

diff --git a/lib/RT/Config.pm b/lib/RT/Config.pm
index 0f08772..3188eb4 100644
--- a/lib/RT/Config.pm
+++ b/lib/RT/Config.pm
@@ -870,7 +870,13 @@ sub SetFromConfig {
     # if option is already set we have to check where
     # it comes from and may be ignore it
     if ( exists $OPTIONS{$name} ) {
-        if ( $args{'SiteConfig'} && $args{'Extension'} ) {
+        if ( $type eq 'HASH' ) {
+            $args{'Value'} = [
+                @{ $args{'Value'} },
+                @{ $args{'Value'} }%2? (undef) : (),
+                $self->Get( $name ),
+            ];
+        } elsif ( $args{'SiteConfig'} && $args{'Extension'} ) {
             # if it's site config of an extension then it can only
             # override options that came from its main config
             if ( $args{'Extension'} ne $META{$name}->{'Source'}{'Extension'} ) {

commit d1e89fa3fed7141d28b969742d377a1490c75c18
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Tue Nov 9 14:05:43 2010 +0000

    Update Elements/Tabs to use Ruslan's new Lifecycles API

diff --git a/share/html/Elements/Tabs b/share/html/Elements/Tabs
index fba3d2c..c235b66 100755
--- a/share/html/Elements/Tabs
+++ b/share/html/Elements/Tabs
@@ -374,23 +374,30 @@ if ( $request_path !~ qr{^/SelfService/} ) {
                 my $current   = $obj->Status;
                 my $lifecycle = $obj->QueueObj->lifecycle;
                 my $i         = 1;
-                foreach my $next ( $lifecycle->transitions($current) ) {
-                    my $action = $lifecycle->transition_action( $current => $next );
-                    next if $action eq 'hide';
+
+                foreach my $info ( $lifecycle->actions($current) ) {
+                    my $next = $info->{'to'};
+                    next unless $lifecycle->is_transition( $current => $next );
+
                     my $check = $lifecycle->check_right( $current => $next );
                     $can{$check} = $obj->CurrentUserHasRight($check) unless exists $can{$check};
                     next unless $can{$check};
 
+
+                   my $action = $info->{'update'} || '';
+
+
                     my $url = '/Ticket/';
                     if ($action) {
 
                         $url .= "Update.html?" . $query_string->(Action => $action,
                                                DefaultStatus => $next,
-                                               id            => $id);
+                                               id            => $id
+                                             );
                     } else {
                         $url .= "Display.html?" . $query_string->( Status => $next, id => $id );
                     }
-                    $actions->child( loc($lifecycle->transition_label( $current => $next )) => path => $url);
+                    $actions->child( loc( $info->{'label'} || ucfirst($next) ) => path => $url);
                 }
 
             }

commit d99c16e1f0837aca581ac7c5b55346e00ff5dbc6
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Tue Nov 9 14:08:09 2010 +0000

    RT::Interface::Web::Handler doesn't need to 'use' itself, but it _does_
    need to use RT::Interface::Web, since we call
    RT::Interface::Web->HandleRequest() from the autohandler

diff --git a/lib/RT/Interface/Web/Handler.pm b/lib/RT/Interface/Web/Handler.pm
index 431efa4..cff1a86 100644
--- a/lib/RT/Interface/Web/Handler.pm
+++ b/lib/RT/Interface/Web/Handler.pm
@@ -58,7 +58,7 @@ use Time::ParseDate;
 use Time::HiRes;
 use HTML::Entities;
 use HTML::Scrubber;
-use RT::Interface::Web::Handler;
+use RT::Interface::Web;
 use RT::Interface::Web::Request;
 use File::Path qw( rmtree );
 use File::Glob qw( bsd_glob );

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


More information about the Rt-commit mailing list