[Rt-commit] rt branch, 4.6/priority-as-string, created. rt-4.4.2-96-gfeeff463a

Brian Duggan brian at bestpractical.com
Mon Jun 11 16:25:51 EDT 2018


The branch, 4.6/priority-as-string has been created
        at  feeff463a61d2b3507b5c97474d446294fc80697 (commit)

- Log -----------------------------------------------------------------
commit feeff463a61d2b3507b5c97474d446294fc80697
Author: Brian C. Duggan <brian at bestpractical.com>
Date:   Tue May 29 19:08:30 2018 -0400

    Core RT::Extension::PriorityAsString
    
    Port functionality of RT::Extension::PriorityAsString. Replicate
    existing behavior of extension.

diff --git a/etc/RT_Config.pm.in b/etc/RT_Config.pm.in
index fae0d46d4..c380808fa 100644
--- a/etc/RT_Config.pm.in
+++ b/etc/RT_Config.pm.in
@@ -3818,6 +3818,67 @@ Set( %ServiceBusinessHours, );
 
 =back
 
+
+
+
+=head1 Priority strings
+
+=over 4
+
+=item C<%PriorityAsString>
+
+RT can assign a priority value to tickets. Priority is stored as an
+integer in the database, but RT supports mapping strings to numerical
+values. For example, the default mapping is:
+
+    Set(%PriorityAsString, (Low => 0, Medium => 50, High => 100));
+
+Redefine C<%PriorityAsString> in C<RT_SiteConfig.pm> to set site
+priority strings.
+
+=cut
+
+Set(%PriorityAsString, (Low => 0, Medium => 50, High => 100));
+
+=item C<%PriorityAsStringOrder>
+
+Administrators can alter the order of priority strings as they appear
+in selection drop-downs with C<@PriorityStringOrder>. Administrators
+can also use this setting to limit the available priority strings on
+ticket update pages. When this options is defined, scrips and other RT
+code will still have access to all of the priority strings defined in
+C<%PriorityAsString>. To set a priority string order:
+
+    Set(@PriorityAsStringOrder, qw(Low Medium High));
+
+=cut
+
+=item C<%PriorityAsStringQueues>
+
+RT supports different priority string mappings for individual queues
+with C<%PriorityAsStringQueues>. Use queue names as keys in this
+hash. Then define priority string-number hash maps for each queue's
+value. Tickets in queues that aren't defined in this hash will fall
+back to RT's numerical priorities.
+
+When C<%PriorityAsStringQueues> is set, RT ignores both
+C<%PriorityAsString> and C<@PriorityAsStringOrder>. Administrators do
+not need to define C<%PriorityAsStringQueues> or C<%PriorityAsString>
+when they set C<%PriorityAsStringQueues>.
+
+To set per-queue priority strings:
+
+    Set(%PriorityAsStringQueues,
+      General => { Low => 0, Medium => 50, High => 100 },
+      Binary  => { Low => 0, High => 10 },
+    );
+
+=cut
+
+=back
+
+
+
 =head1 Administrative interface
 
 =over 4
diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index 08169fb9c..b304c0ba1 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -94,6 +94,10 @@ use RT::SLA;
 use MIME::Entity;
 use Devel::GlobalDestruction;
 
+$RT::Config::META{PriorityAsString}{Type} = 'HASH';
+$RT::Config::META{PriorityAsStringOrder}{Type} = 'ARRAY';
+$RT::Config::META{PriorityAsStringQueues}{Type} = 'HASH';
+
 sub LifecycleColumn { "Queue" }
 
 my %ROLES = (
@@ -3316,7 +3320,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of InitialPriority.
 (In the database, InitialPriority is stored as int(11).)
 
+=head2 InitialPriorityAsString
 
+Returns the current mapped string value of InitialPriority.
 
 =head2 SetInitialPriority VALUE
 
@@ -3334,7 +3340,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of FinalPriority.
 (In the database, FinalPriority is stored as int(11).)
 
+=head2 FinalPriorityAsString
 
+Returns the current mapped string value of FinalPriority.
 
 =head2 SetFinalPriority VALUE
 
@@ -3352,7 +3360,9 @@ Returns (1, 'Status message') on success and (0, 'Error Message') on failure.
 Returns the current value of Priority.
 (In the database, Priority is stored as int(11).)
 
+=head2 PriorityAsString
 
+Returns the current mapped string value of Priority.
 
 =head2 SetPriority VALUE
 
@@ -3697,6 +3707,52 @@ sub Serialize {
     return %store;
 }
 
+sub PriorityIsString {
+    my $self = shift;
+    my %queues = RT->Config->Get('PriorityAsStringQueues');
+    return 0 if (keys %queues and not $queues{$self->QueueObj->Name});
+    return 1;
+}
+
+# Returns String: Various Ticket Priorities as either a string or integer
+sub PriorityAsString {
+    my $self = shift;
+    return $self->_PriorityAsString($self->Priority);
+}
+
+sub InitialPriorityAsString {
+    my $self = shift;
+    return $self->_PriorityAsString( $self->InitialPriority );
+}
+
+sub FinalPriorityAsString {
+    my $self=shift;
+    return $self->_PriorityAsString( $self->FinalPriority );
+}
+
+sub _PriorityAsString {
+    my $self = shift;
+    my $priority = shift;
+    return undef unless defined $priority && length $priority;
+
+    my %map;
+    my $queues = RT->Config->Get('PriorityAsStringQueues');
+    if (@_) {
+        %map = %{ shift(@_) };
+    } elsif ($queues and $queues->{$self->QueueObj->Name}) {
+        %map = %{ $queues->{$self->QueueObj->Name} };
+    } else {
+        %map = RT->Config->Get('PriorityAsString');
+    }
+
+    # Count from high down to low until we find one that our number is
+    # greater than or equal to.
+    foreach my $label ( sort { $map{$b} <=> $map{$a} } keys %map ) {
+        return $label if $priority >= $map{ $label };
+    }
+    return "unknown";
+}
+
 RT::Base->_ImportOverlays();
 
 1;
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 089ccea11..d5663f428 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -153,19 +153,19 @@ $COLUMN_MAP = {
     Priority => {
         title     => 'Priority', # loc
         attribute => 'Priority',
-        value     => sub { return $_[0]->Priority }
+        value     => sub { return $_[0]->PriorityAsString }
     },
     InitialPriority => {
         title     => 'InitialPriority', # loc
         attribute => 'InitialPriority',
         name      => 'Initial Priority',
-        value     => sub { return $_[0]->InitialPriority }
+        value     => sub { return $_[0]->InitialPriorityAsString }
     },
     FinalPriority => {
         title     => 'FinalPriority', # loc
         attribute => 'FinalPriority',
         name      => 'Final Priority',
-        value     => sub { return $_[0]->FinalPriority }
+        value     => sub { return $_[0]->FinalPriorityAsString }
     },
     EffectiveId => {
         title     => 'EffectiveId', # loc
diff --git a/share/html/Elements/SelectPriority b/share/html/Elements/SelectPriority
index 078d85df7..40a26a9a6 100644
--- a/share/html/Elements/SelectPriority
+++ b/share/html/Elements/SelectPriority
@@ -48,8 +48,32 @@
 <input name="<% $Name %>" value="<% $Default %>" size="5" />
 <%ARGS>
 $Name => 'Priority'
-$Default => ''
+$Default => undef
 </%ARGS>
 <%INIT>
+
+my %queues = RT->Config->Get('PriorityAsStringQueues');
+
+# If enabled for all queues, always show the drop-down
+return $m->comp("/Elements/SelectPriorityAsString",%ARGS)
+    unless keys %queues;
+
+# Some callsites we can easily override with callbacks with logic to
+# know when to call SelectPriorityAsString; for ticket create and queue
+# modify, we need to inspect the callstack.
+my $caller      = $m->callers(1)->path;
+my $caller_args = $m->caller_args(1);
+my $QueueObj = RT::Queue->new( $session{'CurrentUser'} );
+if ( $caller eq "/Admin/Queues/Modify.html") {
+    $QueueObj->Load( $caller_args->{id} ) || $QueueObj->Load( $caller_args->{Name} );
+} elsif ( $caller eq "/Ticket/Create.html" or $caller eq "/m/ticket/create" ) {
+    RT::Logger->debug("Pri3");
+    $QueueObj->Load( $caller_args->{Queue} );
+}
+RT::Logger->debug("Queue ID: ".$QueueObj->Id);
+RT::Logger->debug("Queue Name: ".$QueueObj->Name);
+return $m->comp("/Elements/SelectPriorityAsString",%ARGS, Mapping => $queues{$QueueObj->Name})
+    if $QueueObj->Id and $queues{$QueueObj->Name};
+
 $Default = '' unless defined $Default;
 </%INIT>
diff --git a/share/html/Elements/SelectPriority b/share/html/Elements/SelectPriorityAsString
similarity index 68%
copy from share/html/Elements/SelectPriority
copy to share/html/Elements/SelectPriorityAsString
index 078d85df7..e56e40fb3 100644
--- a/share/html/Elements/SelectPriority
+++ b/share/html/Elements/SelectPriorityAsString
@@ -45,11 +45,39 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
-<input name="<% $Name %>" value="<% $Default %>" size="5" />
+<select class="select-priority" name="<% $Name %>">
+% unless ( defined $Default ) {
+<option value="">-</option>
+% }
+<%PERL>
+foreach my $label ( @order ) {
+    my ($value, $selected);
+    if ( $label eq $default_label ) {
+        ($value, $selected) = ($Default, 'selected="selected"');
+    } else {
+        ($value, $selected) = ($map{ $label }, '');
+    }
+</%PERL>
+<option class="<% lc $label %>" value="<% $value %>" <% $selected |n %>><% loc($label) %></option>
+% }
+</select>
 <%ARGS>
 $Name => 'Priority'
-$Default => ''
+$Default => undef
+$Mapping => undef
 </%ARGS>
 <%INIT>
-$Default = '' unless defined $Default;
+
+my %map   = $Mapping ? %{ $Mapping } : RT->Config->Get('PriorityAsString');
+my @order;
+if (not $Mapping and RT->Config->Get('PriorityAsStringOrder')) {
+    @order = grep {exists $map{$_}} RT->Config->Get('PriorityAsStringOrder');
+} else {
+    @order = sort { $map{$a} <=> $map{$b} } keys %map;
+}
+
+my $default_label = '';
+if ( defined $Default && length $Default ) {
+    $default_label = RT::Ticket->_PriorityAsString( $Default, \%map ) || '';
+}
 </%INIT>
diff --git a/share/html/Search/Elements/PickBasics b/share/html/Search/Elements/PickBasics
index 3f2ed237a..fb36de06e 100644
--- a/share/html/Search/Elements/PickBasics
+++ b/share/html/Search/Elements/PickBasics
@@ -223,6 +223,34 @@ my @lines = (
     },
 );
 
+# Updating 'Path' for *Priority:
+#
+# Don't update 'Path' when %PriorityAsStringQueues is not
+# configured. SelectPriority hands off to SelectPriorityAsString when
+# %PriorityAsString is configured.
+#
+# Display the number input unless all queues specified use
+# %PriorityAsStringQueues.
+my %as_string = RT->Config->Get('PriorityAsStringQueues');
+
+if ( %queues and %as_string and scalar(keys %queues) == grep {$as_string{$_}} keys %queues ) {
+    # Additionally, all queues in PriorityAsStringQueues must use the _same_
+    # values for each name; if "High" is mapped to 10 in one queue and 100
+    # in another, we can't use names
+    my %values;
+    for my $q (keys %queues) {
+        for my $priority (keys %{$as_string{$q}}) {
+            return if exists $values{$priority} and $as_string{$q}{$priority} != $values{$priority};
+            $values{$priority} = $as_string{$q}{$priority};
+        }
+    }
+
+    # Swap out the /Elements/SelectPriority for /Elements/SelectPriorityAsString
+    my ($priority) = grep {$_->{Name} eq "Priority"} @lines;
+    $priority->{Value}{Path} = "/Elements/SelectPriorityAsString";
+    $priority->{Value}{Arguments}{Mapping} = \%values;
+}
+
 $m->callback( Conditions => \@lines );
 
 </%INIT>
diff --git a/share/html/Ticket/Elements/EditBasics b/share/html/Ticket/Elements/EditBasics
index c4505e770..8b393753a 100644
--- a/share/html/Ticket/Elements/EditBasics
+++ b/share/html/Ticket/Elements/EditBasics
@@ -58,6 +58,16 @@ if ($TicketObj) {
     $QueueObj ||= $TicketObj->QueueObj;
 }
 
+my %queue_priority_strings = RT->Config->Get('PriorityAsStringQueues');
+
+# Leave it as-is if all queues use PriorityAsString; the overridden
+# /Elements/SelectPriority catches this case and always shows the
+# drop-down
+#return unless keys %as_string;
+
+# Only applies if the ticket is in a PriorityAsString queue
+#return unless $TicketObj and $as_string{$TicketObj->QueueObj->Name};
+
 unless ( @fields ) {
     my $subject = $defaults{'Subject'} || $TicketObj->Subject;
     @fields = (
@@ -124,10 +134,15 @@ unless ( @fields ) {
                 (my $field = $_) =~ s/ //g;
                 {
                     name => $_,
-                    comp => '/Elements/SelectPriority',
+                    comp => $TicketObj->PriorityIsString
+                        ? '/Elements/SelectPriorityAsString'
+                        : '/Elements/SelectPriority',
                     args => {
                         Name => $field,
                         Default => $defaults{$field} || $TicketObj->$field,
+                        Mapping => $TicketObj->PriorityIsString
+                            ? $queue_priority_strings{$TicketObj->QueueObj->Name}
+                            : undef,
                     }
                 }
             } ('Priority', 'Final Priority')
diff --git a/share/html/Ticket/Elements/ShowPriority b/share/html/Ticket/Elements/ShowPriority
index c465d4875..122382037 100644
--- a/share/html/Ticket/Elements/ShowPriority
+++ b/share/html/Ticket/Elements/ShowPriority
@@ -45,7 +45,23 @@
 %# those contributions and any derivatives thereof.
 %#
 %# END BPS TAGGED BLOCK }}}
+%# if (keys %queues and not $queues{$Ticket->QueueObj->Name}) {
+% if ( $Ticket->PriorityIsString ) {
+% my $current = $Ticket->PriorityAsString || '';
+% my $final = $Ticket->FinalPriorityAsString || '';
+<span class="ticket-info-priority-<% $CSSClass->(lc($current)) %>"><% loc($current) %></span>/\
+<span class="ticket-info-final-priority-<% $CSSClass->(lc($final)) %>"><% loc($final) %></span>
+% } else {
 <% $Ticket->Priority %>/<% $Ticket->FinalPriority || ''%>
+% }
 <%ARGS>
 $Ticket => undef
 </%ARGS>
+<%INIT>
+my $CSSClass = sub {
+    my $value = shift;
+    return '' unless defined $value;
+    $value =~ s/[^A-Za-z0-9_-]/_/g;
+    return $value;
+};
+</%INIT>
diff --git a/t/web/mobile.t b/t/web/mobile.t
index 3f32e49e6..831bf6652 100644
--- a/t/web/mobile.t
+++ b/t/web/mobile.t
@@ -82,7 +82,7 @@ $m->content_contains( 'ticket1', 'subject' );
 $m->content_contains( 'open', 'status' );
 $m->content_contains( 'cc at example.com', 'cc' );
 $m->content_contains( 'admincc at example.com', 'admincc' );
-$m->content_contains( '13/93', 'priority' );
+$m->text_contains( 'Low/Medium', 'priority' );
 $m->content_contains( '2 hour', 'time estimates' );
 $m->content_contains( '30 min', 'time worked' );
 $m->content_contains( '60 min', 'time left' );

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


More information about the rt-commit mailing list