[Rt-commit] rt branch, 4.4/preview-scrip-recipients-checkbox, created. rt-4.4.1-311-g0a238ce

Dave Goehrig dave at bestpractical.com
Mon Feb 27 09:59:27 EST 2017


The branch, 4.4/preview-scrip-recipients-checkbox has been created
        at  0a238cea9eb98b4bf88bac4a19e4b55adb144760 (commit)

- Log -----------------------------------------------------------------
commit 26906c21fa62735cc7581b7c21e98cfabd9f4b06
Author: Dave Goehrig <dave at bestpractical.com>
Date:   Thu Feb 23 11:51:47 2017 -0500

    adding project time worked
    
    This adds a new recursive project time worked function to Ticket.pm
    and adds a COLUMN_MAP entry so that it can be displayed in reports.
    
    The code is optional and requires setting a $DisplayProjectTimeWorked
    in RT_SiteConfig.pm.  Also before creating tickets using this one needs
    to disable the  'On TimeWorked Change Update Parent TimeWorked' scrip
    which mutates the value of time worked on the parent tickets.
    
    It should be noted running this on an existing database will report
    invalid results for all tickets where that scrip was active as it will
    double count all of the child time worked in the parent tickets.
    
    Fixes: I#181638

diff --git a/lib/RT/Ticket.pm b/lib/RT/Ticket.pm
index f2581de..ca68ee2 100644
--- a/lib/RT/Ticket.pm
+++ b/lib/RT/Ticket.pm
@@ -1411,8 +1411,34 @@ sub TimeEstimatedAsString {
     return $self->_DurationAsString( $self->TimeEstimated );
 }
 
+=head2 ProjectTimeWorked
 
+Returns the amount of time worked on this ticket and all child tickets
 
+=cut
+
+sub ProjectTimeWorked {
+    my $self = shift;
+    my $time = $self->TimeWorked;
+    my $links = $self->Members;
+    LINK: while (my $link = $links->Next) {
+        my $obj = $link->BaseObj;
+        next LINK unless $obj->isa('RT::Ticket') || $link->Type ne 'MemberOf' || $obj->id == $self->id;
+        $time += $obj->ProjectTimeWorked;
+    }
+    return $time;
+}
+
+=head2 ProjectTimeWorkedAsString 
+
+Returns the amount of time worked on this ticket and all it's children as a formatted duration string
+
+=cut
+
+sub ProjectTimeWorkedAsString {
+    my $self = shift;
+    return $self->_DurationAsString( $self->ProjectTimeWorked );
+}
 
 =head2 Comment
 
diff --git a/share/html/Elements/RT__Ticket/ColumnMap b/share/html/Elements/RT__Ticket/ColumnMap
index 2db1149..8001d5f 100644
--- a/share/html/Elements/RT__Ticket/ColumnMap
+++ b/share/html/Elements/RT__Ticket/ColumnMap
@@ -332,7 +332,9 @@ $COLUMN_MAP = {
             return \($m->scomp("/Ticket/Elements/PopupTimerLink", id => $_[0]->id ) );
         },
     },
+
 };
+
 </%ONCE>
 <%init>
 # if no encryption support, then KeyOwnerName and KeyRequestors fall back to the regular
@@ -342,6 +344,16 @@ unless (RT->Config->Get('Crypt')->{'Enable'}) {
     $COLUMN_MAP->{KeyRequestors} = $GenericMap->{Requestors};
 }
 
+if(RT->Config->Get('DisplayProjectTimeWorked')) {
+  $COLUMN_MAP->{ProjectTimeWorked} = {
+        attribute => 'ProjectTimeWorked',
+        title => 'Project Time Worked',
+        value => sub {
+            return $_[0]->ProjectTimeWorkedAsString;
+        },
+    }
+}
+
 $m->callback( GenericMap => $GenericMap, COLUMN_MAP => $COLUMN_MAP, CallbackName => 'Once', CallbackOnce => 1 );
 return GetColumnMapEntry( Map => $COLUMN_MAP, Name => $Name, Attribute => $Attr );
 </%init>
diff --git a/share/html/Search/Elements/BuildFormatString b/share/html/Search/Elements/BuildFormatString
index 1bf71b1..bc86080 100644
--- a/share/html/Search/Elements/BuildFormatString
+++ b/share/html/Search/Elements/BuildFormatString
@@ -101,6 +101,9 @@ my @fields = qw(
     NBSP
 ); # loc_qw
 
+# Project time worked is an optional ColumnMap enabled for rolling up child timeworked
+push @fields, 'ProjectTimeWorked' if (RT->Config->Get('DisplayProjectTimeWorked'));
+
 my $CustomFields = RT::CustomFields->new( $session{'CurrentUser'});
 foreach my $id (keys %queues) {
     # Gotta load up the $queue object, since queues get stored by name now.
diff --git a/share/html/Ticket/Elements/ShowBasics b/share/html/Ticket/Elements/ShowBasics
index 0a06f02..71db661 100644
--- a/share/html/Ticket/Elements/ShowBasics
+++ b/share/html/Ticket/Elements/ShowBasics
@@ -74,6 +74,12 @@
     <td class="value"><& ShowTime, minutes => $Ticket->TimeWorked &></td>
   </tr>
 % }
+% if (RT->Config->Get('DisplayProjectTimeWorked') && $Ticket->ProjectTimeWorked) {
+  <tr class="project time worked sum">
+    <td class="label"><&|/l&>Project Time Worked</&>:</td>
+    <td class="value"><& ShowTime, minutes => $Ticket->ProjectTimeWorked &></td>
+  </tr>
+% }
 % if ( keys %$time_worked ) {
 <tr class="time worked by-user">
   <td class="label"><&|/l&>Users</&>:</td>
diff --git a/t/api/ticket.t b/t/api/ticket.t
index c5f1e24..b7aebd0 100644
--- a/t/api/ticket.t
+++ b/t/api/ticket.t
@@ -330,4 +330,70 @@ diag("Test ticket types with different cases");
     is($t->Type, "approval", "Approvals, the third and final internal type, are also lc'd during Create");
 }
 
+diag("Test tickets project time worked");
+{
+    my $scrip = RT::Scrip->new(RT->SystemUser);
+    $scrip->LoadByCols(Description => 'On TimeWorked Change Update Parent TimeWorked');
+    $scrip->SetDisabled(1);
+
+    my $t1 = RT::Ticket->new(RT->SystemUser);
+    my ($ok1) = $t1->Create(
+        Queue => 'general',
+        Subject => 'project time worked test parent',
+    );
+
+    my $t2 = RT::Ticket->new(RT->SystemUser);
+    my ($ok2) = $t2->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child',
+    );
+
+    my $t3 = RT::Ticket->new(RT->SystemUser);
+    my ($ok3) = $t3->Create(
+        Queue => 'general',
+        Subject => 'project time worked test child child',
+    );
+
+    my ($status1,$msg1) = $t1->AddLink(
+        Type => 'MemberOf',
+        Base => $t2->id,
+    );
+
+    my ($status2,$msg2) = $t2->AddLink(
+        Type => 'MemberOf',
+        Base => $t3->id,
+    );
+
+    my $t4 = RT::Ticket->new(RT->SystemUser);
+    my ($ok4) = $t4->Create(
+        Queue => 'general',
+        Subject => 'project time worked test other child child',
+    );
+
+    my ($status4,$msg4) = $t2->AddLink(
+        Type => 'MemberOf',
+        Base => $t4->id,
+    );
+
+    $t1->SetTimeWorked(10);
+    $t2->SetTimeWorked(20);
+    $t3->SetTimeWorked(40);
+    $t4->SetTimeWorked(50);
+
+    is $t4->TimeWorked, 50, 'set other child child time worked';
+    is $t4->TimeWorked, 50, 'check other child child time worked';
+    is $t3->TimeWorked, 40, 'check child child time worked';
+    is $t2->TimeWorked, 20, 'check child time worked';
+    is $t1->TimeWorked, 10, 'check parent time worked';
+
+    is $t1->ProjectTimeWorked, 120, 'check parent project time worked';
+    is $t2->ProjectTimeWorked, 110, 'check child project time worked';
+    is $t3->ProjectTimeWorked, 40, 'check child child project time worked';
+    is $t4->ProjectTimeWorked, 50, 'check other child child project time worked';
+
+    is $t1->ProjectTimeWorkedAsString, '2 hours (120 minutes)', 'check parent project time worked as string';
+    is $t3->ProjectTimeWorkedAsString, '40 minutes', 'check child child project time workd as string';
+}
+
+
 done_testing;

commit 0a238cea9eb98b4bf88bac4a19e4b55adb144760
Author: Dave Goehrig <dave at bestpractical.com>
Date:   Mon Feb 27 09:48:26 2017 -0500

    Fix PreviewScrip checkbox toggling
    
    When the PreviewScrip box is reloaded for any reason,
    the POST request was passing the state of the checkbox
    but the PreviewScrips Helper wasn't respecting the state.
    
    This change sets the checked status based on the input value
    from the AJAX load POST.  This will fix the seeming race
    condition which resets the all recipients button.
    
    In the future it would be worth rewriting this code to not
    do the DOM rendering on the server side, and move towards
    a client side rendering with a proper data model.  DOM
    replacements like this code does every time any element in
    the top level form change make it difficult to maintain a
    consistent view on the client side.
    
    A better implementation would be to have the client side
    view render via DOM manipulation (for those elements which
    need to be dynamically added), and the AJAX post simply
    negotiate a data transfer (say in JSON) of the data elements
    needed to populate the form values.  This would make it work
    similarly to the autocomplete helpers which uses JSON from
    a Helper to add autocomplete fields to the dropdown.
    
    Fixes: I#180703

diff --git a/share/html/Helpers/PreviewScrips b/share/html/Helpers/PreviewScrips
index ecc2a3e..770993f 100644
--- a/share/html/Helpers/PreviewScrips
+++ b/share/html/Helpers/PreviewScrips
@@ -93,7 +93,7 @@ $submitted{$_} = 1 for split /,/, $ARGS{TxnRecipients};
 %          my $action = $s->ActionObj->Action;
 %          scalar(map { $action->$_ } qw(To Cc Bcc))
 %        } @scrips ) {
-<input type="checkbox" class="checkbox" id="TxnSendMailToAll" name="TxnSendMailToAll" value="1">
+<input type="checkbox" class="checkbox" id="TxnSendMailToAll" name="TxnSendMailToAll" <% $ARGS{TxnSendMailToAll} ? 'checked="checked"' : ''  %>" value="1">
 <label for="TxnSendMailToAll"><b><% loc('All recipients') %></b></label><br />
 %   }
 %     for my $scrip (@scrips) {
diff --git a/share/html/Ticket/Update.html b/share/html/Ticket/Update.html
index 8540600..27b3685 100644
--- a/share/html/Ticket/Update.html
+++ b/share/html/Ticket/Update.html
@@ -231,7 +231,9 @@ jQuery( function() {
                var txn_send_field = jQuery("#previewscrips input[name=TxnSendMailTo]");
                txn_send_field.change( syncCheckboxes );
                txn_send_field.click( function () { setCheckbox(this) } );
-               jQuery("#previewscrips input[name=TxnSendMailToAll]").click( function() { setCheckbox(this, 'TxnSendMailTo'); } );
+               jQuery("#previewscrips input[name=TxnSendMailToAll]").click( function() { 
+                    setCheckbox(this, 'TxnSendMailTo');
+                } );
                if (txn_send_field.length > 0) {
                    setCheckbox(txn_send_field[0]);
                }

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


More information about the rt-commit mailing list