<%ARGS> $TreeviewMagic => undef $id => undef $Query => undef $Format => undef $Rows => undef $OrderBy => undef $Order => undef $Page => undef $MaxDepth => 7 $ShowChildren => undef $ShowDependencies => undef @ShowStatus => (); <%init> my @statuses = RT::Queue->new($session{'CurrentUser'})->StatusArray; unless ($TreeviewMagic) { unless (defined $ShowChildren) { $ShowChildren = 1; } unless (defined $ShowDependencies) { $ShowDependencies = 1; } unless( @ShowStatus ) { @ShowStatus = qw(new open stalled); } } # {{{ Generic setup my $title = loc('Tree view'); my $QueryString = "?". $m->comp( '/Elements/QueryString', Query => $Query, Format => $Format, Rows => $Rows, OrderBy => $OrderBy, Order => $Order, Page => $Page, MaxDepth => $MaxDepth, ShowChildren => $ShowChildren, ShowDependencies => $ShowDependencies, ); # QueryString couldn't handle array refs $QueryString = join( '&', $QueryString, map { 'ShowStatus='. $m->interp->apply_escapes($_,'u') } @ShowStatus); # }}} # {{{ If we load a ticket, this search is on a given ticket and we'll get the # ticket menus instead of the tree ones my $Ticket; if ($id) { $Ticket = RT::Ticket->new( $session{'CurrentUser'} ); $Ticket->Load($id); $Query = "id = $id"; } # }}} # {{{ Scrub the html of the format string to remove any potential nasties. $Format = $m->comp( '/Elements/ScrubHTML', Content => ($Format|| $RT::DefaultSearchResultFormat)); my (@Format) = $m->comp( '/Elements/CollectionAsTable/ParseFormat', Format => $Format ); # Alter the format to do treeview indents. foreach my $entry (@Format) { my @output; foreach my $item ( @{ $entry->{'output'} } ) { if ( $item eq '__Subject__' ) { # add indent whitespaces before link unshift @output, '___RT_TreeView_Indent__'; push @output, $item; } else { push @output, $item; } } if( lc $entry->{'attribute'} eq 'id' ) { for my $item ( @output ) { $item =~ s/{'output'} = \@output; } # }}} my $tickets = RT::Tickets->new( $session{'CurrentUser'} ); $tickets->FromSQL($Query); $tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); my @tickets = @{ $tickets->ItemsArrayRef || [] }; my $TopTickets = {}; $TopTickets->{ $_->id } = $_ foreach( @tickets ); my @tree; foreach my $ticket (@tickets) { # If the parent ticket hasn't been invalidated by being displayed deeper... # recurse now and add it in next unless exists $TopTickets->{ $ticket->id }; my $kids = build_subtree( Ticket => $ticket, TopTickets => $TopTickets, Depth => 1, MaxDepth => $MaxDepth, ShowChildren => $ShowChildren, ShowDependencies => $ShowDependencies, ShowStatus => \@ShowStatus, ); unless( $kids && @$kids ) { next unless grep $_ eq $ticket->Status, @ShowStatus; } push @tree, [ $ticket, $kids ]; } # Ok. Let's build up our tree of tickets, recursing down. sub build_subtree { my %args = ( Ticket => undef, TopTickets => undef, ShowChildren => undef, ShowDependencies => undef, ShowStatus => undef, Depth => undef, MaxDepth => undef, @_ ); return if ( $args{'Depth'} > $args{'MaxDepth'} ); my @query; push @query, 'DependsOn = ' . $args{'Ticket'}->id if ( $args{'ShowDependencies'} ); push @query, 'MemberOf = ' . $args{'Ticket'}->id if ( $args{'ShowChildren'} ); my $deps = RT::Tickets->new( $session{'CurrentUser'} ); $deps->FromSQL( join( ' OR ', @query ) ); $deps->OrderBy( FIELD => $args{'OrderBy'}, ORDER => $args{'Order'} ); my @tickets; while ( my $dep = $deps->Next ) { delete $args{'TopTickets'}->{ $dep->id }; my $kids = undef; $kids = build_subtree( %args, Ticket => $dep, Depth => $args{'Depth'} + 1, ); unless( $kids && @$kids ) { next unless grep $_ eq $dep->Status, @{ $args{'ShowStatus'} }; } push @tickets, [ $dep, $kids ]; } return ( \@tickets ); } <& /Elements/Header, Title => $title, Refresh => $session{'tickets_refresh_interval'} &> <& /Ticket/Elements/Tabs, current_tab => "Search/Tree.html".$QueryString, Ticket => $Ticket, Title => $title, Format => $Format, Query => $Query, Rows => $Rows, OrderBy => $OrderBy, Order => $Order &>
<& /Elements/CollectionAsTable/Header, Format => \@Format, AllowSorting => 0, Query => $Query, &> <%perl> unshift @{$Format[0]->{'output'}}, "[+]'; foreach my $row (@tree) { $m->comp( '.entry', Ticket => $row->[0], Depth => 0, Format => \@Format, Children => $row->[1], Parents => { $row->[0]->id => 1 } ); }

<& /Elements/TitleBoxStart, title => loc('Display options') &> <& /Elements/Submit &> <& /Elements/TitleBoxEnd &>
<%DEF .entry> <%args> $Ticket $Depth => 0 $Children => undef @Format => undef $MaxDepth => undef $Parents => undef <%init> $m->comp('/Elements/CollectionAsTable/Row', Format => \@Format, i => $Depth, record => $Ticket); foreach my $row (@$Children) { if (!exists $Parents->{$row->[0]->id}) { $Parents->{$row->[0]->id} = 1; # look to see if the child is a parent up the tree $m->comp( '.entry', Ticket => $row->[0], Children => $row->[1], Depth => ( $Depth + 1 ), MaxDepth => $MaxDepth, Format => \@Format, Parents => $Parents ); } else { # found a loop my @Blank; foreach my $entry (@Format) { my @output = [' ']; my $title = ''; foreach my $item ( @{ $entry->{'output'} } ) { if ( $item =~ /Subject/i ) { @output = [ '___RT_TreeView_Indent__', '...' ]; } elsif ($item =~ /__NEWLINE__/i ) { $title = 'NEWLINE'; } } push @Blank, { output => @output, title => $title }; } $m->comp( '/Elements/CollectionAsTable/Row', Format => \@Blank, i => $Depth + 1, record => $Ticket ); } }