<%doc>

Given a list of objects, sorts by given criteria and prints a page with the essential columns.
Performs paging by passing the sorted/indexed list to itself, together with the current offset

Supported arguments:

  table:      name of a table in the database
  object:     referece to a list of objects in that table for displaying in html
  sort:       column to sort by
  page:       page to link to with results (default is view.html)
  withedit:   add checkboxes to allow user to edit or delete selected objects
  return_args: Caller arguments to pass to delete.html so user can return after deleting objects

  # The following are passed to itself in subsequent calls
  per_page:   Maximum entries displayed per page
  offset:     Current position
  total:      Total number of items in list
  sid:        Session id
</%doc>

<%args>

$table       => undef
$object      => undef
$sort        => undef
$page        => undef
$withedit    => 0
$per_page    => undef
$offset      => 0
$total       => undef
$sid         => undef
$osid        => undef
$return_args => undef
$dowindow    => undef
</%args>

<%init>
my $DEBUG = 0;
my %orderbrief;
my @orderbrief;
my $lblf;
my %cssitem    = ( 0 => "formtablec1", 1 => "formtablec2" );
my $ci         = 1;
my $last_item;
my $session;
my $osession;
my %objindex;
my $numcols;
my $IPV4 = Netdot->get_ipv4_regex();
my $caller_path;
my $user = $ui->get_current_user($r);

my $user_per_page = $user->getAttribute("USER_PERPAGE");
if ( !defined($per_page) ){
    $per_page = $ui->config->get('DEFAULT_PERPAGE');
    
    #per user per_page preference takes precedence over global pref
    if ( $user_per_page =~ /\d+/ && ($per_page != $user_per_page) ) {
	$per_page = $user_per_page;
    }
} else {
    #set the new one
    $user->setAttribute($r, "USER_PERPAGE", $per_page);
}

print "<pre>", Dumper(%ARGS), "</pre>" if $DEBUG;

if ( $return_args ){
    $caller_path = $m->caller->path;
    $caller_path .= $return_args;
}

if ( $osid ){
    $osession = $ui->get_session($osid);
    print "<pre> Session $osid contains:", Dumper($osession), "</pre>" if $DEBUG;
    $object = $osession->{object};
}
#########################################################
#
# This happens on first call
#
#########################################################

if ( defined($object) && scalar @$object ){
    if ( ! $osid ){
	$osession = $ui->mk_session();
	$osession->{object} = $object;
    }
    
    ##############################################
    # Determine table name if not passed to us
    $table = $object->[0]->short_class 
	unless $table;

    %orderbrief  = $table->meta_data->get_column_order_brief();
    @orderbrief  = sort { $orderbrief{$a} <=> $orderbrief{$b} } keys %orderbrief;

    ##############################################
    # get the first label field for this table (as defined in metadata)
    $lblf = ($table->meta_data->get_labels)[0];
    
    my $i = 0;
    ##############################################
    # Deal with sorting
    if ( !defined($sort) && defined($table) ) {
	# check for previously-stored sorting preference,
	# if none exists then $sort remains undefined.
	$sort = $user->getAttribute("USER_SORT_BY_COL_".$table);
    }
    if ( defined $sort && ($sort eq '0' || $sort =~ /^no$/i ) ){
	# We're told not to sort
	map { $objindex{$i++} = $_ } @{ $object };
	print "sort == $sort" if $DEBUG;
    }else{
	# Default to label field
	my $sort_field = $lblf;

	# But maybe the sort field was specified
	if ( defined($sort) && $sort ne '' ){
	    # Make sure it's a valid column
	    my %col;
	    map { $col{$_}++ } $table->columns;
	    if( exists( $col{$sort} ) ) {
		$sort_field = $sort;
		# remember it in user variable
		$user->setAttribute($r, "USER_SORT_BY_COL_".$table, $sort);
	    }
	}
	print "Sorting by $sort_field<br/>" if $DEBUG;
	# Be smart about sorting numerically, alphabetically or by IP
	my $alpha = 0;
	my $ipv4  = 0;
	my ($lbl, @lbls);
	foreach my $obj ( @{ $object } ){
	    if ( ref($obj->$sort_field) ){
		# Value of sort field is a foreign object
		# Get that object's display value
		$lbl = $obj->$sort_field->get_label;
	    }else{
		$lbl = $obj->$sort_field;
	    }
	    if ( $lbl =~ /$IPV4/ ){
		$ipv4 = 1;
	    }elsif  ( $lbl =~ /\D+/ ){
		$alpha = 1;
	    }
	    push @lbls, [$obj , $lbl];
	}
	if ( $ipv4 ){
	    @lbls = sort { compare_ip() } @lbls; 
	}elsif ( $alpha ){ 
	    @lbls = sort { $a->[1] cmp $b->[1] } @lbls; 
	}else{
	    @lbls = sort { $a->[1] <=> $b->[1] } @lbls; 
	}
	map { $objindex{$i++} = $_ } map  { $_->[0] } @lbls;
    }
    # Total number of items
    $total = $i;
    
    ##############################################
    # remove id and aliases (if present)
    if( exists( $orderbrief{id} ) ) {
	delete( $orderbrief{id} );
    }
    if( exists( $orderbrief{aliases} ) ) {
	delete( $orderbrief{aliases} );
    }
    ##############################################
    # munge so that label is first 
    if( defined( $lblf ) && length( $lblf ) > 0 ) {
	unless( $orderbrief{$lblf} == 1 ) {
	    my $j              = $orderbrief{$lblf};
	    my %rev            = reverse %orderbrief;
	    my $k              = $rev{1} ;
	    $orderbrief{$k}    = $j;
	    $orderbrief{$lblf} = 1;
	}
    }

    $session = $ui->mk_session();
    $session->{objindex}    = \%objindex;
    $session->{table}       = $table;
    $session->{orderbrief}  = \@orderbrief;
    $session->{page}        = $page;
    $session->{withedit}    = $withedit;
    $session->{caller_path} = $caller_path;
    $session->{total}       = $total;

    
#########################################################
#
# This happens on subsequent calls (paging)
#
#########################################################
}elsif( $sid ) {
    $session = $ui->get_session($sid);
    print "<pre> Session $sid contains:", Dumper($session), "</pre>" if $DEBUG;
    
    %objindex   = %{ $session->{objindex} };
    $table      = $session->{table};
    @orderbrief = @{ $session->{orderbrief} };
    $page       = $session->{page};
    print "<br>Page is now $page<br/>" if $DEBUG;
    $withedit   = $session->{withedit};
    $total      = $session->{total};   
    $caller_path = $session->{caller_path};
 
}

#########################################################
#
# This happens always
#
#########################################################

# Some tables have a specific view page. 
# Point to those when appropriate
#
#I'm not sure why the first column of a sorted table of lists needs special treatment on how to get back, vs using meta data to get the table
#it should link to like the other columns, if this page were only used for devices I would remove this check all together.  But its possible
#this is being used somewhere else in the program.  I tried removing this check and clicked around, and everything seemed fine, but just in case,
#we'll ignore it if DEVICE is set, since thats whats causing the bugs on the device page (with links not resolving correctly after a list has been
#resorted.
unless($page && $page ne "DEVICE"){
    $page = $ui->table_view_page($table);
}
$page ||= 'view.html';

# Calculate last item to show
$last_item = ( ($offset + $per_page) < $total )? $offset + $per_page : $total;

</%init>

%
% if( %objindex ) {

<!-- begin sortresults -->


% #####################################################################
% # Begin the table for this instance of sortresults
% #####################################################################

% $numcols = scalar @orderbrief;
% $numcols++ if $withedit;
% $numcols++ if $withedit;  #again to accomodate [edit] buttons

%     if ( $withedit ) {
         <form name="form_<% $table %>" method="POST" >
         <input type="hidden" name="table" value="<% $table %>">
%	 if ( $caller_path ){
	     <input type="hidden" name="return_url" value="<% $caller_path %>">
%        }
%     }

      <table border="0" cellspacing="0" cellpadding="0" class="tablebackground">

%     #####################################################################
%     # Header row
      <tr class="rowtitle2">
%
%     foreach my $c ( @orderbrief ) {
%          my $tag = $table->meta_data->get_column($c)->tag;
%          if( defined($tag) ) {
               <th><a href="list.html?osid=<% $osession->{_session_id} %>&sort=<% $c %>&offset=<% $offset %>&withedit=<% $withedit %>"><% $tag %></a></th>
%          } else {
               <th><% $c %></th>
%	   }
%     }
%     if ( $withedit ){
          <th></th>
          <th align="center">Select</th>
%     }
      </tr>
%     ####################################################################
%     # Loop around the window of items that we are showing in this page
%     ####################################################################

%     my $pos = $offset;
%     while ( $pos < $last_item ) {
%         my $o;
%         unless ( $o = $objindex{$pos} ){
%             $m->comp("error.mhtml", error=>"Object not valid at index $pos");
%         }
%         $pos++;
%         my $first_column = 1;
%         $ci = ($ci + 1) % 2;

          <tr class="<% $cssitem{$ci} %>">
%
%         ####################################################################
%         # Get the column order and process each item.
%         ####################################################################
%         
%
%         foreach my $c ( @orderbrief ) {
              <td align="left" valign="middle">
%             my $ftable = $table->meta_data->get_column($c)->links_to;
%             #####################################################################
%             # If it is a link to another column....
%             #####################################################################
%             if ( defined $ftable ) {
%                 my $fo; # foreign object
%                 if ( int($fo = $o->$c) != 0 && ref($fo) ) {
%                     my $lbl = $fo->get_label;
%                     if( $first_column ) {
                          &nbsp;
                          <a href="<% $page %>?table=<% $table %>&id=<% $o->id %>"><% $lbl %></a>
%                     }else{
%                         my $fviewpage = $ui->table_view_page($ftable) || 'view.html';
                          &nbsp;
                          <a href="<% $fviewpage %>?table=<% $ftable %>&id=<% $fo->id %>"><% $lbl %></a>
%   		      }
%                 }else{
                         &nbsp -
%                 }
%            }else{
%            #####################################################################
%            # It s not a link to another column
%            #####################################################################
%                if( $first_column ) {
                     &nbsp;
                     <a href="<% $page %>?table=<% $table %>&id=<% $o->id %>"><% $o->$c %></a>
%		 }else{
                     <% $o->$c %>
%		 }
%            } # else fi
            </td>
% #####################################################################
% # Wrap this row up.
% #####################################################################
%           $first_column = 0 if( $first_column );          
%     } # for c
%
%     if ( $withedit ){
          <td style="text-align:right" valign="middle">
              <a href="#" onClick="openinsertwindow('table=<% $table %>&id=<% $o->id %>&dowindow=<% $dowindow %>')">[edit]</a>
          </td>
          <td style="text-align:center" valign="middle" width="40">
              <input type="checkbox" name="<% $table %>__<% $o->id %>">
          </td>
%     }
      </tr>
% } # end while
% ####################################################################

% ## Last row
% if( $withedit ) {
%     my $selectall_ids = join ',', map { $objindex{$_}{id} } keys %objindex;
      <tr class="rowtitle">
%         for( my $i=0; $i<($numcols-2); $i++ ) {
              <td>&nbsp;</td>
%         }
          <td>
            <div align="right" valign="middle">Select All <% $total %> results:</div>
            <input type="hidden" name="selectall_ids" value="<% $selectall_ids %>">
          </td>
          <td style="text-align:center" valign="middle" width="40">
	      <input type="checkbox" name="selectall" id="selectall">
          </td>
      </tr>
% }
% ## Empty row
      <tr class="rowtitle">
%      for( my $i=0; $i<$numcols; $i++ ) {
           <td>&nbsp;</td>
%      }
      </tr>
  </table>

  <div class="containerheadright">
% if ( $total > $per_page ){
      Results: [<% $offset+1 %>-<% $last_item %>] of <% $total %> 
%     my $prev_offset = $offset - $per_page;
%     if ( $session->{_session_id} && $prev_offset >= 0 ){
          <a href="list.html?sid=<% $sid %>&osid=<% $osid %>&offset=<% $prev_offset %>&per_page=<% $per_page %>&sort=<% $sort %>&page=<% $page %>">[<<] </a>
%     }
%     unless ( $last_item == $total ){
          <a href="list.html?sid=<% $session->{_session_id} %>&osid=<% $osession->{_session_id} %>&offset=<% $last_item %>&per_page=<% $per_page %>&sort=<% $sort %>&page=<% $page %>">[>>] </a>
%     }
% }

    <a href="#" onClick="opentextwindow('','csv','sid=<% $session->{_session_id} %>')">[csv]</a>

% if ( $withedit ){
      <p>
      <input type="button" name="Edit" value="Edit" onClick="document.form_<% $table %>.action='edit-multiple.html';document.form_<% $table %>.submit();">
      <input type="button" name="Delete" value="Delete" onClick="document.form_<% $table %>.action='delete.html';document.form_<% $table %>.submit();">
      <input type="button" name="Cancel" value="Cancel" onClick="history.go(-1)">
      </form>
      </p>
% }

% if ( $session ){
    <form name="form_sortresults" method="POST" action="list.html">
      <input type="hidden" name="sid" value="<% $session->{_session_id} %>">
      <input type="hidden" name="offset" value="<% $offset %>">
      <input type="submit" name="Show" value="Show"> <input type="text" size="3" name="per_page" value="<% $per_page %>"> items per page
    </form>
% }

  </div>


<!-- end sortresults -->
% } # endif %objindex

<%once>
sub compare_ip{
    pack("C4"=>$a->[1] =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/) cmp pack("C4"=>$b->[1] =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/);
}
</%once>
