[Bps-public-commit] rt-extension-jsgantt branch, master, updated. 557409f8c348ff842f9e4c33c1b39e3395a95ccc

? sunnavy sunnavy at bestpractical.com
Thu Jul 1 15:14:56 EDT 2010


The branch, master has been updated
       via  557409f8c348ff842f9e4c33c1b39e3395a95ccc (commit)
      from  e860637c4dc90e599695688e27f94cd4b1cdd9c6 (commit)

Summary of changes:
 html/Search/JSGantt.html    |  251 +++---------------------------------------
 lib/RT/Extension/JSGantt.pm |  252 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 269 insertions(+), 234 deletions(-)

- Log -----------------------------------------------------------------
commit 557409f8c348ff842f9e4c33c1b39e3395a95ccc
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Fri Jul 2 03:16:13 2010 +0800

    move major logic to .pm

diff --git a/html/Search/JSGantt.html b/html/Search/JSGantt.html
index d38d724..480d158 100644
--- a/html/Search/JSGantt.html
+++ b/html/Search/JSGantt.html
@@ -15,6 +15,7 @@
     g.setShowRes(<% RT->Config->Get('JSGanttShowOwner')? 1 : 0 %>);
     g.setShowDur(<% RT->Config->Get('JSGanttShowDuration')? 1 : 0 %> );
 
+% my $show_progress = RT->Config->Get('JSGanttShowProgress' );
 % if ( $show_progress ) {
         g.setShowComp(1);
 % } else {
@@ -32,8 +33,8 @@
     
     // You can also use the XML file parser JSGantt.parseXML('project.xml',g)
 %   use JSON;
-%   for my $id ( @ids ) {
-%       my $json = to_json( [ $id, map { $info{$id}{$_} } qw/name start end
+%   for my $id ( @$ids ) {
+%       my $json = to_json( [ $id, map { $info->{$id}{$_} } qw/name start end
 %           color link milestone owner progress has_members parent open
 %           depends/ ] );
 %       $json =~ s/^\[//; $json =~ s/\]$//;
@@ -55,254 +56,36 @@
 
 <%init>
 my $title = loc('JSGantt Results');
-
-my ( $Tickets, @Tickets );
-
-sub related_tickets {
-    my $ticket = shift;
-    my @types = @_;
-    return unless $ticket;
-    my @tickets;
-    for my $type ( @types ) {
-        my $links = $ticket->$type->ItemsArrayRef;
-        my $target_or_base =
-          $type =~ /DependsOn|MemberOf|RefersTo/ ? 'TargetObj' : 'BaseObj';
-        for my $link (@$links) {
-            my $obj = $link->$target_or_base;
-            if ( $obj && $obj->isa('RT::Ticket') ) {
-                push @tickets, $obj;
-            }
-        }
-    }
-    return @tickets;
-}
+my @Tickets;
 
 if ( $Ticket ) {
-    my %checked;
-    my @to_be_checked;
-
-    my $ticket = RT::Ticket->new( $session{CurrentUser} );
-    $ticket->Load( $Ticket );
-    if ( $ticket->id ) {
-        # find the highest ancestors to make chart pretty
-        my @parents = related_tickets( $ticket, 'MemberOf' );
-        @parents = $ticket unless @parents;
-        while ( @parents ) {
-            my @ancestors;
-            for my $parent ( @parents ) {
-                unshift @ancestors, related_tickets( $parent, 'MemberOf' );
-            }
-            
-            if ( @ancestors ) {
-                @parents = @ancestors;
-            }
-            else {
-                @to_be_checked = @parents;
-                undef @parents;
-            }
-        }
-
-        while ( my $ticket = shift @to_be_checked ) {
-            push @Tickets, $ticket unless grep { $ticket->id eq $_->id } @Tickets;
-            push @to_be_checked, grep { ! $checked{$_->id}++ } related_tickets( $ticket, 'Members' );
-        }
-
-        @to_be_checked = @Tickets;
-        while ( my $ticket = shift @to_be_checked ) {
-            push @Tickets, $ticket unless grep { $ticket->id eq $_->id } @Tickets;
-            unshift @to_be_checked, grep { ! $checked{$_->id}++ } related_tickets( $ticket, 'Members' );
-            unshift @to_be_checked, grep { ! $checked{$_->id}++ } related_tickets( $ticket, 'MemberOf' );
-            push @to_be_checked, grep { ! $checked{$_->id}++ } related_tickets(
-                $ticket, 'DependsOn', 'DependedOnBy', 'RefersTo', 'ReferredToBy' );
-        }
-    }
+    @Tickets = RT::Extension::JSGantt->AllRelatedTickets(
+        Ticket     => $Ticket,
+        CurrentUser => $session{CurrentUser},
+    );
 }
-elsif ( $Query ) {
-    $Tickets = RT::Tickets->new( $session{'CurrentUser'} );
-    $Tickets->FromSQL( $Query );
+elsif ($Query) {
+    my $Tickets = RT::Tickets->new( $session{'CurrentUser'} );
+    $Tickets->FromSQL($Query);
     if ( $OrderBy =~ /\|/ ) {
+
         # Multiple Sorts
         my @OrderBy = split /\|/, $OrderBy;
         my @Order   = split /\|/, $Order;
         $Tickets->OrderByCols(
             map { { FIELD => $OrderBy[$_], ORDER => $Order[$_] } }
-            ( 0 .. $#OrderBy )
-        );
+              ( 0 .. $#OrderBy ) );
     }
     else {
         $Tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order );
     }
     @Tickets = @{ $Tickets->ItemsArrayRef };
 }
-else {
-    $m->abort;
-}
-
-my $progress = 0;
-my $show_progress = RT->Config->Get('JSGanttShowProgress' );
-
-my @colors = grep { defined } RT->Config->Get('JSGanttColorScheme');
- at colors = ( 'ff0000', 'ffff00', 'ff00ff', '00ff00', '00ffff', '0000ff' )  unless @colors;
-my $i;
-my ( @ids, %info );
-my ( $min_start, $min_start_obj );
-
-for my $Ticket (@Tickets) {
-    my $subject = $Ticket->Subject;
-
-    my $parent = 0;
-    if ( $Ticket->MemberOf->Count ) {
-        $parent = $Ticket->MemberOf->First->TargetObj->id;
-    }
-
-    # find start/end, this is, uhh, long long way to go
-    my ( $start, $end ) = ( '', '' );
-    my ( $start_obj, $end_obj );
-    if ( $Ticket->StartsObj->Unix ) {
-        my ( $day, $month, $year ) =
-          ( $Ticket->StartsObj->Localtime('user') )[ 3, 4, 5 ];
-        $start = join '/', $month + 1, $day, $year;
-        $start_obj = $Ticket->StartsObj;
-    }
-    elsif ( $Ticket->StartedObj->Unix ) {
-        my ( $day, $month, $year ) =
-          ( $Ticket->StartedObj->Localtime('user') )[ 3, 4, 5 ];
-        $start = join '/', $month + 1, $day, $year;
-        $start_obj = $Ticket->StartedObj;
-    }
-
-    if ( $Ticket->DueObj->Unix ) {
-        my ( $day, $month, $year ) =
-          ( $Ticket->DueObj->Localtime('user') )[ 3, 4, 5 ];
-        $end = join '/', $month + 1, $day, $year;
-        $end_obj = $Ticket->DueObj;
-    }
-
-    # if $start or $end is empty still
-    unless ( $start && $end ) {
-        if ( $parent ) {
-            # yep, it's sure that $parent lives in %info already
-            $start ||= $info{$parent}{start};
-            $end ||= $info{$parent}{end};
-        }
-        else {
-            my $hours_per_day = RT->Config->Get('JSGanttWorkingHoursPerDay')
-              || 8;
-            my $total_time =
-              defined $Ticket->TimeLeft
-              ? ( $Ticket->TimeWorked + $Ticket->TimeLeft )
-              : $Ticket->TimeEstimated;
-            $total_time ||= 0;
-            my $days = int( $total_time / ( 60 * $hours_per_day ) );
-            $days ||= RT->Config->Get('JSGanttDefaultDays') || 7;
 
-            # since we only use date without time, let's make days inclusive
-            # ( i.e. 5/12/2010 minus 3 days is 5/10/2010. 10,11,12, 3 days! )
-            $days = $days =~ /\./ ? int $days : $days - 1;
-            $days = 0 if $days < 0;
-
-            if ( $start && !$end ) {
-                $end_obj = RT::Date->new( $session{CurrentUser} );
-                $end_obj->Set( Value => $start_obj->Unix );
-                $end_obj->AddDays($days);
-                my ( $day, $month, $year ) =
-                  ( $end_obj->Localtime('user') )[ 3, 4, 5 ];
-                $end = join '/', $month + 1, $day, $year;
-            }
-
-            if ( $end && !$start ) {
-                $start_obj = RT::Date->new( $session{CurrentUser} );
-                $start_obj->Set( Value => $end_obj->Unix );
-                $start_obj->AddDays( -1 * $days );
-                my ( $day, $month, $year ) =
-                  ( $start_obj->Localtime('user') )[ 3, 4, 5 ];
-                $start = join '/', $month + 1, $day, $year;
-            }
-        }
-    }
-
-    if ( !$start ) {
-        $RT::Logger->warning( "Ticket "
-              . $Ticket->id
-              . " doesn't have Starts/Started defined, and we can't figure it out either"
-        );
-        $start = $end;
-    }
-    if ( !$end ) {
-        $RT::Logger->warning( "Ticket "
-              . $Ticket->id
-              . " doesn't have Due defined, and we can't figure it out either"
-        );
-        $end = $start;
-    }
-
-    my $has_members = $Ticket->Members->Count ? 1 : 0;
-
-    # parent ticket's start date is not used when drawing
-    if (  !$has_members
-        && $start_obj
-        && ( !$min_start_obj || $min_start_obj->Unix > $start_obj->Unix ) )
-    {
-        $min_start_obj = $start_obj;
-        $min_start     = $start;
-    }
-
-    my $depends = $Ticket->DependsOn;
-    my @depends;
-    if ( $depends->Count ) {
-        while ( my $d = $depends->Next ) {
-            push @depends, $d->TargetObj->id;
-        }
-    }
-
-    if ($show_progress) {
-        my $total_time =
-          defined $Ticket->TimeLeft
-          ? ( $Ticket->TimeWorked + $Ticket->TimeLeft )
-          : $Ticket->TimeEstimated;
-        if ( $Ticket->TimeWorked ) {
-            $progress = int( 100 * $Ticket->TimeWorked / $total_time );
-        }
-    }
-
-    push @ids, $Ticket->id;
-    $info{$Ticket->id} = 
-      {
-        name => ( $Ticket->id . ': ' . substr $subject, 0, 30 ),
-        start => $start,
-        end => $end,
-        color => $colors[ $i++ % @colors ],
-        link => (
-                RT->Config->Get('WebPath')
-              . '/Ticket/Display.html?id='
-              . $Ticket->id
-        ),
-        milestone => 0,
-        owner => ( $Ticket->OwnerObj->Name || $Ticket->OwnerObj->EmailAddress ),
-        progress => $progress,
-        has_members => $has_members,
-        parent => $parent,
-        open => 1,
-        depends => ( @depends ? join ',', @depends : 0 )
-      };
-}
-
-
-#let's tweak our results
-#set to now if all tickets don't have start/end dates
-if ( ! $min_start ) {
-    $min_start_obj = RT::Date->new($session{CurrentUser});
-    $min_start_obj->SetToNow;
-    my ($day,$month,$year) = ($min_start_obj->Localtime('user'))[3,4,5];
-    $min_start = join '/', $month+1, $day, $year;
-}
-
-my $no_dates_color = RT->Config->Get('JSGanttNullDatesColor') || '333';
-for my $id ( @ids ) {
-    $info{$id}{color} = $no_dates_color unless $info{$id}{start};
-    $info{$id}{start} ||= $min_start;
-    $info{$id}{end} ||= $min_start;
-}
+my ( $ids, $info ) = RT::Extension::JSGantt->TicketsInfo(
+    Tickets     => \@Tickets,
+    CurrentUser => $session{CurrentUser},
+);
 
 </%init>
 
diff --git a/lib/RT/Extension/JSGantt.pm b/lib/RT/Extension/JSGantt.pm
index e77db1a..2bc567a 100644
--- a/lib/RT/Extension/JSGantt.pm
+++ b/lib/RT/Extension/JSGantt.pm
@@ -5,6 +5,258 @@ our $VERSION = '0.03';
 use warnings;
 use strict;
 
+sub AllRelatedTickets {
+    my $class = shift;
+    my %args = ( Ticket => undef, CurrentUser => undef, @_ );
+
+    my @tickets;
+    my %checked;
+    my @to_be_checked;
+    my $ticket = RT::Ticket->new( $args{CurrentUser} );
+    $ticket->Load( $args{Ticket} );
+    if ( $ticket->id ) {
+
+        # find the highest ancestors to make chart pretty
+        my @parents = _RelatedTickets( $ticket, 'MemberOf' );
+        @parents = $ticket unless @parents;
+        while (@parents) {
+            my @ancestors;
+            for my $parent (@parents) {
+                unshift @ancestors, _RelatedTickets( $parent, 'MemberOf' );
+            }
+
+            if (@ancestors) {
+                @parents = @ancestors;
+            }
+            else {
+                @to_be_checked = @parents;
+                undef @parents;
+            }
+        }
+
+        while ( my $ticket = shift @to_be_checked ) {
+            push @tickets, $ticket
+              unless grep { $ticket->id eq $_->id } @tickets;
+            push @to_be_checked,
+              grep { !$checked{ $_->id }++ }
+              _RelatedTickets( $ticket, 'Members' );
+        }
+
+        @to_be_checked = @tickets;
+        while ( my $ticket = shift @to_be_checked ) {
+            push @tickets, $ticket
+              unless grep { $ticket->id eq $_->id } @tickets;
+            unshift @to_be_checked,
+              grep { !$checked{ $_->id }++ }
+              _RelatedTickets( $ticket, 'Members' );
+            unshift @to_be_checked,
+              grep { !$checked{ $_->id }++ }
+              _RelatedTickets( $ticket, 'MemberOf' );
+            push @to_be_checked, grep { !$checked{ $_->id }++ } _RelatedTickets(
+                $ticket, 'DependsOn', 'DependedOnBy', 'RefersTo',
+                'ReferredToBy'
+            );
+        }
+    }
+    return @tickets;
+}
+
+
+sub TicketsInfo {
+    my $class = shift;
+    my %args = ( Tickets => [], CurrentUser => undef, @_ );
+
+
+    my ( @ids, %info );
+    my $progress = 0;
+    my @colors = grep { defined } RT->Config->Get('JSGanttColorScheme');
+    @colors = ( 'ff0000', 'ffff00', 'ff00ff', '00ff00', '00ffff', '0000ff' )
+      unless @colors;
+    my $i;
+    my $show_progress = RT->Config->Get('JSGanttShowProgress' );
+
+    my ( $min_start, $min_start_obj );
+
+    for my $Ticket (@{$args{Tickets}}) {
+        my $subject = $Ticket->Subject;
+
+        my $parent = 0;
+        if ( $Ticket->MemberOf->Count ) {
+            $parent = $Ticket->MemberOf->First->TargetObj->id;
+        }
+
+        # find start/end, this is, uhh, long long way to go
+        my ( $start, $end ) = ( '', '' );
+        my ( $start_obj, $end_obj );
+        if ( $Ticket->StartsObj->Unix ) {
+            my ( $day, $month, $year ) =
+              ( $Ticket->StartsObj->Localtime('user') )[ 3, 4, 5 ];
+            $start = join '/', $month + 1, $day, $year;
+            $start_obj = $Ticket->StartsObj;
+        }
+        elsif ( $Ticket->StartedObj->Unix ) {
+            my ( $day, $month, $year ) =
+              ( $Ticket->StartedObj->Localtime('user') )[ 3, 4, 5 ];
+            $start = join '/', $month + 1, $day, $year;
+            $start_obj = $Ticket->StartedObj;
+        }
+
+        if ( $Ticket->DueObj->Unix ) {
+            my ( $day, $month, $year ) =
+              ( $Ticket->DueObj->Localtime('user') )[ 3, 4, 5 ];
+            $end = join '/', $month + 1, $day, $year;
+            $end_obj = $Ticket->DueObj;
+        }
+
+        # if $start or $end is empty still
+        unless ( $start && $end ) {
+            if ($parent) {
+
+                # yep, it's sure that $parent lives in %info already
+                $start ||= $info{$parent}{start};
+                $end   ||= $info{$parent}{end};
+            }
+            else {
+                my $hours_per_day = RT->Config->Get('JSGanttWorkingHoursPerDay')
+                  || 8;
+                my $total_time =
+                  defined $Ticket->TimeLeft
+                  ? ( $Ticket->TimeWorked + $Ticket->TimeLeft )
+                  : $Ticket->TimeEstimated;
+                $total_time ||= 0;
+                my $days = int( $total_time / ( 60 * $hours_per_day ) );
+                $days ||= RT->Config->Get('JSGanttDefaultDays') || 7;
+
+               # since we only use date without time, let's make days inclusive
+               # ( i.e. 5/12/2010 minus 3 days is 5/10/2010. 10,11,12, 3 days! )
+                $days = $days =~ /\./ ? int $days : $days - 1;
+                $days = 0 if $days < 0;
+
+                if ( $start && !$end ) {
+                    $end_obj = RT::Date->new( $args{CurrentUser} );
+                    $end_obj->Set( Value => $start_obj->Unix );
+                    $end_obj->AddDays($days);
+                    my ( $day, $month, $year ) =
+                      ( $end_obj->Localtime('user') )[ 3, 4, 5 ];
+                    $end = join '/', $month + 1, $day, $year;
+                }
+
+                if ( $end && !$start ) {
+                    $start_obj = RT::Date->new( $args{CurrentUser} );
+                    $start_obj->Set( Value => $end_obj->Unix );
+                    $start_obj->AddDays( -1 * $days );
+                    my ( $day, $month, $year ) =
+                      ( $start_obj->Localtime('user') )[ 3, 4, 5 ];
+                    $start = join '/', $month + 1, $day, $year;
+                }
+            }
+        }
+
+        if ( !$start ) {
+            $RT::Logger->warning( "Ticket "
+                  . $Ticket->id
+                  . " doesn't have Starts/Started defined, and we can't figure it out either"
+            );
+            $start = $end;
+        }
+        if ( !$end ) {
+            $RT::Logger->warning( "Ticket "
+                  . $Ticket->id
+                  . " doesn't have Due defined, and we can't figure it out either"
+            );
+            $end = $start;
+        }
+
+        my $has_members = $Ticket->Members->Count ? 1 : 0;
+
+        # parent ticket's start date is not used when drawing
+        if (  !$has_members
+            && $start_obj
+            && ( !$min_start_obj || $min_start_obj->Unix > $start_obj->Unix ) )
+        {
+            $min_start_obj = $start_obj;
+            $min_start     = $start;
+        }
+
+        my $depends = $Ticket->DependsOn;
+        my @depends;
+        if ( $depends->Count ) {
+            while ( my $d = $depends->Next ) {
+                push @depends, $d->TargetObj->id;
+            }
+        }
+
+        if ($show_progress) {
+            my $total_time =
+              defined $Ticket->TimeLeft
+              ? ( $Ticket->TimeWorked + $Ticket->TimeLeft )
+              : $Ticket->TimeEstimated;
+            if ( $Ticket->TimeWorked ) {
+                $progress = int( 100 * $Ticket->TimeWorked / $total_time );
+            }
+        }
+
+        push @ids, $Ticket->id;
+        $info{ $Ticket->id } = {
+            name  => ( $Ticket->id . ': ' . substr $subject, 0, 30 ),
+            start => $start,
+            end   => $end,
+            color => $colors[ $i++ % @colors ],
+            link  => (
+                    RT->Config->Get('WebPath')
+                  . '/Ticket/Display.html?id='
+                  . $Ticket->id
+            ),
+            milestone => 0,
+            owner =>
+              ( $Ticket->OwnerObj->Name || $Ticket->OwnerObj->EmailAddress ),
+            progress    => $progress,
+            has_members => $has_members,
+            parent      => $parent,
+            open        => 1,
+            depends     => ( @depends ? join ',', @depends : 0 )
+        };
+    }
+
+    #let's tweak our results
+    #set to now if all tickets don't have start/end dates
+    if ( !$min_start ) {
+        $min_start_obj = RT::Date->new( $args{CurrentUser} );
+        $min_start_obj->SetToNow;
+        my ( $day, $month, $year ) =
+          ( $min_start_obj->Localtime('user') )[ 3, 4, 5 ];
+        $min_start = join '/', $month + 1, $day, $year;
+    }
+
+    my $no_dates_color = RT->Config->Get('JSGanttNullDatesColor') || '333';
+    for my $id (@ids) {
+        $info{$id}{color} = $no_dates_color unless $info{$id}{start};
+        $info{$id}{start} ||= $min_start;
+        $info{$id}{end}   ||= $min_start;
+    }
+    return \@ids, \%info;
+}
+
+sub _RelatedTickets {
+    my $ticket = shift;
+    my @types = @_;
+    return unless $ticket;
+    my @tickets;
+    for my $type ( @types ) {
+        my $links = $ticket->$type->ItemsArrayRef;
+        my $target_or_base =
+          $type =~ /DependsOn|MemberOf|RefersTo/ ? 'TargetObj' : 'BaseObj';
+        for my $link (@$links) {
+            my $obj = $link->$target_or_base;
+            if ( $obj && $obj->isa('RT::Ticket') ) {
+                push @tickets, $obj;
+            }
+        }
+    }
+    return @tickets;
+}
+
+
 =head1 NAME
 
 RT::Extension::JSGantt - 

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



More information about the Bps-public-commit mailing list