<%ARGS> $TreeviewMagic => undef $id => undef $Query => undef $Format => undef $Rows => undef $OrderBy => undef $Order => undef $Page => undef $MaxDepth => 7 $ShowChildren => undef $ShowDependencies => undef <%init> unless ($TreeviewMagic) { unless (defined $ShowChildren) { $ShowChildren = 1; } unless (defined $ShowDependencies) { $ShowDependencies = 1; } } # {{{ 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 ); # }}} # {{{ 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.a $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__' ) { push @output, '___RT_TreeView_Indent__', $item; } else { push @output, $item; } } $entry->{'output'} = \@output; } # }}} my $tickets = RT::Tickets->new( $session{'CurrentUser'} ); $tickets->FromSQL($Query); $tickets->OrderBy( FIELD => $OrderBy, ORDER => $Order ); my $TopTickets = (); my @tickets = @{ $tickets->ItemsArrayRef || [] }; foreach my $ticket (@tickets) { $TopTickets->{ $ticket->id } = $ticket; } 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 ); 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, Depth => undef, MaxDepth => undef, @_ ); return if ( $args{'Depth'} > $args{'MaxDepth'} ); my $ticket = $args{'Ticket'}; my $TopTickets = $args{'TopTickets'}; my $deps = RT::Tickets->new( $session{'CurrentUser'} ); my @query; my @tickets; push @query, 'DependentOn = ' . $ticket->id if ( $args{'ShowDependencies'} ); push @query, 'MemberOf = ' . $ticket->id if ( $args{'ShowChildren'} ); $deps->FromSQL( join( ' OR ', @query ) ); $deps->OrderBy( FIELD => $args{'OrderBy'}, ORDER => $args{'Order'} ); while ( my $dep = $deps->Next ) { delete $TopTickets->{ $dep->id }; my $kids = undef; $kids = build_subtree( Ticket => $dep, TopTickets => $TopTickets, Depth => ( $args{'Depth'} + 1 ), MaxDepth => $args{'MaxDepth'}, ShowChildren => $args{'ShowChildren'}, ShowDependencies => $args{'ShowDependencies'} ); 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') &>

- <&|/l&>Sublevel display depth: >
%# Checkboxes have binary logic. "Off" looks like "never existed %# TreeviewMagic emulates trinary logic for them
- ><&|/l&>Show children in sublevels
- ><&|/l&>Show dependencies in sublevels

<& /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 ); } }