summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authorivan <ivan>2007-11-26 02:19:49 +0000
committerivan <ivan>2007-11-26 02:19:49 +0000
commit9f8e50c683598d9797e8babf4a21db4f6a65a1d8 (patch)
tree3cc0db9e4b2fcbfa9cf359238cfd86186b9c3552 /httemplate
parente256d78e23dafd768b6c01608d4b741070215129 (diff)
add a "printable copy" link to searches to get full results as printable HTML without other cruft, closes: #1885
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/search/elements/search.html1353
1 files changed, 699 insertions, 654 deletions
diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html
index d72bcfdb1..7b1a515df 100644
--- a/httemplate/search/elements/search.html
+++ b/httemplate/search/elements/search.html
@@ -1,704 +1,749 @@
-% # options example...
-% # (everything not commented required is optional)
-% #
-% # # basic options, required
-% # 'title' => 'Page title',
-% #
-% # 'name_singular' => 'item', #singular name for the records returned
-% # #OR# # (preferred, will be pluralized automatically)
-% # 'name' => 'items', #plural name for the records returned
-% # # (deprecated, will be singularlized
-% # # simplisticly)
-% #
-% # # some HTML callbacks...
-% # 'menubar' => '', #menubar arrayref
-% # 'html_init' => '', #after the header/menubar and before the pager
-% # 'html_form' => '', #after the pager, right before the results
-% # # (only shown if there are results)
-% # # (use this for any form-opening tag rather than
-% # # html_init, to avoid a nested form)
-% # 'html_foot' => '', #at the bottom
-% # 'html_posttotal' => '', #at the bottom
-% # # (these three can be strings or coderefs)
-% #
-% #
-% # #literal SQL query string or qsearch hashref, required
-% # 'query' => {
-% # 'table' => 'tablename',
-% # #everything else is optional...
-% # 'hashref' => { 'field' => 'value',
-% # 'field' => { 'op' => '<',
-% # 'value' => '54',
-% # },
-% # },
-% # 'select' => '*',
-% # 'addl_from' => '', #'LEFT JOIN othertable USING ( key )',
-% # 'extra_sql' => '', #'AND otherstuff', #'WHERE onlystuff',
-% # 'order_by' => 'ORDER BY something',
-% #
-% # },
-% # # "select * from tablename";
-% #
-% # #required unless 'query' is an SQL query string (shouldn't be...)
-% # 'count_query' => 'SELECT COUNT(*) FROM tablename',
-% #
-% # 'count_addl' => [], #additional count fields listref of sprintf strings
-% # # [ $money_char.'%.2f total paid', ],
-% #
-% # #listref of column labels, <TH>
-% # #required unless 'query' is an SQL query string
-% # # (if not specified the database column names will be used)
-% # 'header' => [ '#', 'Item' ],
-% #
-% # 'disable_download' => '', # set true to hide the CSV/Excel download links
-% # 'disable_nonefound' => '', # set true to disable the "No matching Xs found"
-% # # message
-% #
-% # 'disableable' => 1, # set true if this table has a "disabled" field, to
-% # # hide disabled records & have "show disabled" links
-% # 'disabled_statuspos' => 3, #optional position (starting from 0) to insert
-% # #a Status column when showing disabled records
-% # #(query needs to be a qsearch hashref and
-% # # header & fields need to be defined)
-% # 'agent_virt' => 1, # set true if this search should be agent-virtualized
-% # 'agent_null_right' => 'Access Right', #opt. right to view global records
-% # 'agent_pos' => 3, #optional position (starting from 0) to insert
-% # #an Agent column
-% # #(query needs to be a qsearch hashref and
-% # # header & fields need to be defined)
-% #
-% # #listref - each item is a literal column name (or method) or coderef
-% # #if not specified all columns will be shown
-% # 'fields' => [
-% # 'column',
-% # sub { my $row = shift; $row->column; },
-% # ],
-% #
-% # #listref of column footers
-% # 'footer' => [],
-% #
-% # #listref - each item is the empty string, or a listref of ...
-% # 'links' =>
-% #
-% #
-% # 'align' => 'lrc.', #one letter for each column, left/right/center/none
-% # # can also pass a listref with full values:
-% # # [ 'left', 'right', 'center', '' ]
-% #
-% # #listrefs...
-% # #currently only HTML, maybe eventually Excel too
-% # 'color' => [],
-% # 'size' => [],
-% # 'style' => [],
-% #
-% # #redirect if there's only one item...
-% # # listref of URL base and column name (or method)
-% # # or a coderef that returns the same
-% # 'redirect' =>
-% #
-% # #set to 1 (or column position for "disabled" status col) to enable
-% # #"show disabled/hide disabled" links
-% # #(can't be used with a literal query)
-% # 'disableable' => 1,
-%
-% my(%opt) = @_;
-% #warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
-%
-% my $curuser = $FS::CurrentUser::CurrentUser;
-%
-% my %align = (
-% 'l' => 'left',
-% 'r' => 'right',
-% 'c' => 'center',
-% ' ' => '',
-% '.' => '',
-% );
-% $opt{align} = [ map $align{$_}, split(//, $opt{align}) ],
-% unless !$opt{align} || ref($opt{align});
-%
-% if ( $opt{'agent_virt'} ) {
-%
-% my $agentnums_sql = $curuser->agentnums_sql(
-% 'null_right' => $opt{'agent_null_right'}
-% );
-%
-% $opt{'query'}{'extra_sql'} .=
-% ( $opt{'query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
-% $agentnums_sql;
-% $opt{'count_query'} .=
-% ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
-% $agentnums_sql;
-%
-% if ( $opt{'agent_pos'} || $opt{'agent_pos'} eq '0'
-% and scalar($curuser->agentnums) > 1 ) {
-% #false laziness w/statuspos above
-% my $pos = $opt{'agent_pos'};
-%
-% foreach my $att (qw( align style color size )) {
-% $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
-% }
-%
-% splice @{ $opt{'header'} }, $pos, 0, 'Agent';
-% splice @{ $opt{'align'} }, $pos, 0, 'c';
-% splice @{ $opt{'style'} }, $pos, 0, '';
-% splice @{ $opt{'size'} }, $pos, 0, '';
-% splice @{ $opt{'fields'} }, $pos, 0,
-% sub { $_[0]->agentnum ? $_[0]->agent->agent : '(global)'; };
-% splice @{ $opt{'color'} }, $pos, 0, '';
-% splice @{ $opt{'links'} }, $pos, 0, '' #[ 'agent link?', 'agentnum' ]
-% if $opt{'links'};
-%
-% }
-%
-% }
-%
-% if ( $opt{'disableable'} ) {
-%
-% unless ( $cgi->param('showdisabled') ) { #modify searches
-%
-% $opt{'query'}{'hashref'}{'disabled'} = '';
-% $opt{'query'}{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
-%
-% $opt{'count_query'} .=
-% ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
-% "( disabled = '' OR disabled IS NULL )";
-%
-% } elsif ( $opt{'disabled_statuspos'}
-% || $opt{'disabled_statuspos'} eq '0' ) { #add status column
-%
-% my $pos = $opt{'disabled_statuspos'};
-%
-% foreach my $att (qw( align style color size )) {
-% $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
-% }
-%
-% splice @{ $opt{'header'} }, $pos, 0, 'Status';
-% splice @{ $opt{'align'} }, $pos, 0, 'c';
-% splice @{ $opt{'style'} }, $pos, 0, 'b';
-% splice @{ $opt{'size'} }, $pos, 0, '';
-% splice @{ $opt{'fields'} }, $pos, 0,
-% sub { shift->disabled ? 'DISABLED' : 'Active'; };
-% splice @{ $opt{'color'} }, $pos, 0,
-% sub { shift->disabled ? 'FF0000' : '00CC00'; };
-% splice @{ $opt{'links'} }, $pos, 0, ''
-% if $opt{'links'};
-% }
-%
-% #add show/hide disabled links
-% my $items = $opt{'name'} || PL($opt{'name_singular'});
-% if ( $cgi->param('showdisabled') ) {
-% $cgi->param('showdisabled', 0);
-% $opt{'html_posttotal'} .=
-% '( <a href="'. $cgi->self_url. qq!">hide disabled $items</a> )!;
-% $cgi->param('showdisabled', 1);
-% } else {
-% $cgi->param('showdisabled', 1);
-% $opt{'html_posttotal'} .=
-% '( <a href="'. $cgi->self_url. qq!">show disabled $items</a> )!;
-% $cgi->param('showdisabled', 0);
-% }
-%
-% }
-%
-% my $type = '';
-% my $limit = '';
-% my($confmax, $maxrecords, $total, $offset, $count_arrayref);
-%
-% if ( $cgi->param('_type') =~ /^(csv|\w*\.xls)$/ ) {
-%
-% $type = $1;
-%
-% } else { #setup some pagination things if we're in html mode
-%
-% unless (exists($opt{count_query}) && length($opt{count_query})) {
-% ( $opt{count_query} = $opt{query} ) =~
-% s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i; #silly vim:/
-% }
-%
-% if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
-% $opt{count_query} .=
-% ( ( $opt{count_query} =~ /WHERE/i ) ? ' AND ' : ' WHERE ' ).
-% "( disabled = '' OR disabled IS NULL )";
-% }
-%
-% my $conf = new FS::Conf;
-% $confmax = $conf->config('maxsearchrecordsperpage');
-% if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
-% $maxrecords = $1;
-% } else {
-% $maxrecords ||= $confmax;
-% }
-%
-% $limit = $maxrecords ? "LIMIT $maxrecords" : '';
-%
-% $offset = $cgi->param('offset') || 0;
-% $limit .= " OFFSET $offset" if $offset;
-%
-% my $count_sth = dbh->prepare($opt{'count_query'})
-% or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
-% $count_sth->execute
-% or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
-% $count_arrayref = $count_sth->fetchrow_arrayref;
-% $total = $count_arrayref->[0];
-%
-% }
-%
-% # run the query
-%
-% my $header = $opt{header};
-% my $rows;
-% if ( ref($opt{query}) ) {
-%
-% if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
-% #%search = ( 'disabled' => '' );
-% $opt{'query'}->{'hashref'}->{'disabled'} = '';
-% $opt{'query'}->{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
-% }
-%
-% #eval "use FS::$opt{'query'};";
-% $rows = [ qsearch({
-% 'select' => $opt{'query'}->{'select'},
-% 'table' => $opt{'query'}->{'table'},
-% 'addl_from' => (exists($opt{'query'}->{'addl_from'}) ? $opt{'query'}->{'addl_from'} : ''),
-% 'hashref' => $opt{'query'}->{'hashref'} || {},
-% 'extra_sql' => $opt{'query'}->{'extra_sql'},
-% 'order_by' => $opt{'query'}->{'order_by'}. " $limit",
-% }) ];
-% } else {
-% my $sth = dbh->prepare("$opt{'query'} $limit")
-% or die "Error preparing $opt{'query'}: ". dbh->errstr;
-% $sth->execute
-% or die "Error executing $opt{'query'}: ". $sth->errstr;
-%
-% #can get # of rows without fetching them all?
-% $rows = $sth->fetchall_arrayref;
-%
-% $header ||= $sth->{NAME};
-% }
-%
-% if ( $type eq 'csv' ) {
-%
-% #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
-% http_header('Content-Type' => 'text/plain' );
-%
-% my $csv = new Text::CSV_XS { 'always_quote' => 1,
-% 'eol' => "\n", #"\015\012", #"\012"
-% };
-%
-% $csv->combine(@$header); #or die $csv->status;
+<%doc>
+
+Example:
+
+ include( 'elements/search.html',
+
+ # basic options, required
+ 'title' => 'Page title',
+
+ 'name_singular' => 'item', #singular name for the records returned
+ #OR# # (preferred, will be pluralized automatically)
+ 'name' => 'items', #plural name for the records returned
+ # (deprecated, will be singularlized
+ # simplisticly)
+
+ # some HTML callbacks...
+ 'menubar' => '', #menubar arrayref
+ 'html_init' => '', #after the header/menubar and before the pager
+ 'html_form' => '', #after the pager, right before the results
+ # (only shown if there are results)
+ # (use this for any form-opening tag rather than
+ # html_init, to avoid a nested form)
+ 'html_foot' => '', #at the bottom
+ 'html_posttotal' => '', #at the bottom
+ # (these three can be strings or coderefs)
+
+
+ #literal SQL query string (deprecated?) or qsearch hashref, required
+ 'query' => {
+ 'table' => 'tablename',
+ #everything else is optional...
+ 'hashref' => { 'field' => 'value',
+ 'field' => { 'op' => '<',
+ 'value' => '54',
+ },
+ },
+ 'select' => '*',
+ 'addl_from' => '', #'LEFT JOIN othertable USING ( key )',
+ 'extra_sql' => '', #'AND otherstuff', #'WHERE onlystuff',
+ 'order_by' => 'ORDER BY something',
+
+ },
+ # "select * from tablename";
+
+ #required unless 'query' is an SQL query string (shouldn't be...)
+ 'count_query' => 'SELECT COUNT(*) FROM tablename',
+
+ 'count_addl' => [], #additional count fields listref of sprintf strings
+ # [ $money_char.'%.2f total paid', ],
+
+ #listref of column labels, <TH>
+ #required unless 'query' is an SQL query string
+ # (if not specified the database column names will be used)
+ 'header' => [ '#', 'Item' ],
+
+ 'disable_download' => '', # set true to hide the CSV/Excel download links
+ 'disable_nonefound' => '', # set true to disable the "No matching Xs found"
+ # message
+
+ 'disableable' => 1, # set true if this table has a "disabled" field, to
+ # hide disabled records & have "show disabled" links
+ 'disabled_statuspos' => 3, #optional position (starting from 0) to insert
+ #a Status column when showing disabled records
+ #(query needs to be a qsearch hashref and
+ # header & fields need to be defined)
+ 'agent_virt' => 1, # set true if this search should be agent-virtualized
+ 'agent_null_right' => 'Access Right', #opt. right to view global records
+ 'agent_pos' => 3, #optional position (starting from 0) to insert
+ #an Agent column
+ #(query needs to be a qsearch hashref and
+ # header & fields need to be defined)
+
+ #listref - each item is a literal column name (or method) or coderef
+ #if not specified all columns will be shown
+ 'fields' => [
+ 'column',
+ sub { my $row = shift; $row->column; },
+ ],
+
+ #listref of column footers
+ 'footer' => [],
+
+ #listref - each item is the empty string, or a listref of ...
+ 'links' =>
+
+
+ 'align' => 'lrc.', #one letter for each column, left/right/center/none
+ # can also pass a listref with full values:
+ # [ 'left', 'right', 'center', '' ]
+
+ #listrefs...
+ #currently only HTML, maybe eventually Excel too
+ 'color' => [],
+ 'size' => [],
+ 'style' => [],
+
+ #redirect if there's only one item...
+ # listref of URL base and column name (or method)
+ # or a coderef that returns the same
+ 'redirect' =>
+
+ #set to 1 (or column position for "disabled" status col) to enable
+ #"show disabled/hide disabled" links
+ #(can't be used with a literal query)
+ 'disableable' => 1,
+
+ );
+
+</%doc>
+% if ( $type eq 'csv' ) {
+%
+% #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes
+% http_header('Content-Type' => 'text/plain' );
+%
+% my $csv = new Text::CSV_XS { 'always_quote' => 1,
+% 'eol' => "\n", #"\015\012", #"\012"
+% };
+%
+% $csv->combine(@$header); #or die $csv->status;
%
<% $csv->string %>
%
%
-% foreach my $row ( @$rows ) {
+% foreach my $row ( @$rows ) {
%
-% if ( $opt{'fields'} ) {
+% if ( $opt{'fields'} ) {
%
-% my @line = ();
+% my @line = ();
%
-% foreach my $field ( @{$opt{'fields'}} ) {
-% if ( ref($field) eq 'CODE' ) {
-% push @line, map {
-% ref($_) eq 'ARRAY'
-% ? '(N/A)' #unimplemented
-% : $_;
-% }
-% &{$field}($row);
-% } else {
-% push @line, $row->$field();
-% }
-% }
+% foreach my $field ( @{$opt{'fields'}} ) {
+% if ( ref($field) eq 'CODE' ) {
+% push @line, map {
+% ref($_) eq 'ARRAY'
+% ? '(N/A)' #unimplemented
+% : $_;
+% }
+% &{$field}($row);
+% } else {
+% push @line, $row->$field();
+% }
+% }
%
-% $csv->combine(@line); #or die $csv->status;
+% $csv->combine(@line); #or die $csv->status;
%
-% } else {
-% $csv->combine(@$row); #or die $csv->status;
-% }
+% } else {
+% $csv->combine(@$row); #or die $csv->status;
+% }
%
%
<% $csv->string %>
%
%
-% }
-%
-% #} elsif ( $type eq 'excel' ) {
-% } elsif ( $type =~ /\.xls$/ ) {
-%
-% #http_header('Content-Type' => 'application/excel' ); #eww
-% http_header('Content-Type' => 'application/vnd.ms-excel' );
-% #http_header('Content-Type' => 'application/msexcel' ); #alas
-%
-% my $data = '';
-% my $XLS = new IO::Scalar \$data;
-% my $workbook = Spreadsheet::WriteExcel->new($XLS)
-% or die "Error opening .xls file: $!";
-%
-% my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
-%
-% my($r,$c) = (0,0);
-%
-% $worksheet->write($r, $c++, $_) foreach @$header;
-%
-% foreach my $row ( @$rows ) {
-% $r++;
-% $c = 0;
-%
-% if ( $opt{'fields'} ) {
-%
-% #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
-% #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
-%
-% foreach my $field ( @{$opt{'fields'}} ) {
-% #my $align = $aligns ? shift @$aligns : '';
-% #$align = " ALIGN=$align" if $align;
-% #my $a = '';
-% #if ( $links ) {
-% # my $link = shift @$links;
-% # $link = &{$link}($row) if ref($link) eq 'CODE';
-% # if ( $link ) {
-% # my( $url, $method ) = @{$link};
-% # if ( ref($method) eq 'CODE' ) {
-% # $a = $url. &{$method}($row);
-% # } else {
-% # $a = $url. $row->$method();
-% # }
-% # $a = qq(<A HREF="$a">);
-% # }
-% #}
-% if ( ref($field) eq 'CODE' ) {
-% foreach my $value ( &{$field}($row) ) {
-% if ( ref($value) eq 'ARRAY' ) {
-% $worksheet->write($r, $c++, '(N/A)' ); #unimplemented
-% } else {
-% $worksheet->write($r, $c++, $value );
-% }
-% }
-% } else {
-% $worksheet->write($r, $c++, $row->$field() );
-% }
-% }
-%
-% } else {
-% $worksheet->write($r, $c++, $_) foreach @$row;
-% }
-%
-% }
-%
-% $workbook->close();# or die "Error creating .xls file: $!";
-%
-% http_header('Content-Length' => length($data) );
+% }
+%
+% #} elsif ( $type eq 'excel' ) {
+% } elsif ( $type =~ /\.xls$/ ) {
+%
+% #http_header('Content-Type' => 'application/excel' ); #eww
+% http_header('Content-Type' => 'application/vnd.ms-excel' );
+% #http_header('Content-Type' => 'application/msexcel' ); #alas
+%
+% my $data = '';
+% my $XLS = new IO::Scalar \$data;
+% my $workbook = Spreadsheet::WriteExcel->new($XLS)
+% or die "Error opening .xls file: $!";
+%
+% my $worksheet = $workbook->add_worksheet(substr($opt{'title'},0,31));
+%
+% my($r,$c) = (0,0);
+%
+% $worksheet->write($r, $c++, $_) foreach @$header;
+%
+% foreach my $row ( @$rows ) {
+% $r++;
+% $c = 0;
+%
+% if ( $opt{'fields'} ) {
+%
+% #my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+% #my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+%
+% foreach my $field ( @{$opt{'fields'}} ) {
+% #my $align = $aligns ? shift @$aligns : '';
+% #$align = " ALIGN=$align" if $align;
+% #my $a = '';
+% #if ( $links ) {
+% # my $link = shift @$links;
+% # $link = &{$link}($row) if ref($link) eq 'CODE';
+% # if ( $link ) {
+% # my( $url, $method ) = @{$link};
+% # if ( ref($method) eq 'CODE' ) {
+% # $a = $url. &{$method}($row);
+% # } else {
+% # $a = $url. $row->$method();
+% # }
+% # $a = qq(<A HREF="$a">);
+% # }
+% #}
+% if ( ref($field) eq 'CODE' ) {
+% foreach my $value ( &{$field}($row) ) {
+% if ( ref($value) eq 'ARRAY' ) {
+% $worksheet->write($r, $c++, '(N/A)' ); #unimplemented
+% } else {
+% $worksheet->write($r, $c++, $value );
+% }
+% }
+% } else {
+% $worksheet->write($r, $c++, $row->$field() );
+% }
+% }
+%
+% } else {
+% $worksheet->write($r, $c++, $_) foreach @$row;
+% }
+%
+% }
+%
+% $workbook->close();# or die "Error creating .xls file: $!";
+%
+% http_header('Content-Length' => length($data) );
%
<% $data %>
%
%
-% } else { # regular HTML
-%
-% if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1 ) {
-% my $redirect = $opt{'redirect'};
-% $redirect = &{$redirect}($rows->[0]) if ref($redirect) eq 'CODE';
-% my( $url, $method ) = @$redirect;
-% redirect( $url. $rows->[0]->$method() );
-% } else {
-% if ( $opt{'name_singular'} ) {
-% $opt{'name'} = PL($opt{'name_singular'});
-% }
-% ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
-% if ( $total == 1 ) {
-% if ( $opt{'name_singular'} ) {
-% $opt{'name'} = $opt{'name_singular'}
-% } else {
-% #$opt{'name'} =~ s/s$// if $total == 1;
-% $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1;
-% }
-% }
-%
-% my @menubar = ();
-% if ( $opt{'menubar'} ) {
-% @menubar = @{ $opt{'menubar'} };
-% #} else {
-% # @menubar = ( 'Main menu' => $p );
-% }
-
- <% include( '/elements/header.html', $opt{'title'},
- include( '/elements/menubar.html', @menubar )
- )
- %>
- <% defined($opt{'html_init'})
- ? ( ref($opt{'html_init'})
- ? &{$opt{'html_init'}}()
- : $opt{'html_init'}
- )
- : ''
- %>
-%
-% unless ( $total ) {
-% unless ( $opt{'disable_nonefound'} ) {
-
- No matching <% $opt{'name'} %> found.<BR>
-% }
-% } else {
+% } else { # regular HTML
+%
+% if ( exists($opt{'redirect'}) && scalar(@$rows) == 1 && $total == 1
+% && $type ne 'html-print'
+% ) {
+% my $redirect = $opt{'redirect'};
+% $redirect = &{$redirect}($rows->[0]) if ref($redirect) eq 'CODE';
+% my( $url, $method ) = @$redirect;
+% redirect( $url. $rows->[0]->$method() );
+% } else {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = PL($opt{'name_singular'});
+% }
+% ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
+% if ( $total == 1 ) {
+% if ( $opt{'name_singular'} ) {
+% $opt{'name'} = $opt{'name_singular'}
+% } else {
+% #$opt{'name'} =~ s/s$// if $total == 1;
+% $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1;
+% }
+% }
+%
+% if ( $type eq 'html-print' ) {
+
+ <% include( '/elements/header-popup.html', $opt{'title'} ) %>
+
+% } else {
+%
+% my @menubar = ();
+% if ( $opt{'menubar'} ) {
+% @menubar = @{ $opt{'menubar'} };
+% #} else {
+% # @menubar = ( 'Main menu' => $p );
+% }
+
+ <% include( '/elements/header.html', $opt{'title'},
+ include( '/elements/menubar.html', @menubar )
+ )
+ %>
- <TABLE>
- <TR>
+ <% defined($opt{'html_init'})
+ ? ( ref($opt{'html_init'})
+ ? &{$opt{'html_init'}}()
+ : $opt{'html_init'}
+ )
+ : ''
+ %>
- <TD VALIGN="bottom">
+% }
- <FORM>
+% unless ( $total ) {
+% unless ( $opt{'disable_nonefound'} ) {
+ No matching <% $opt{'name'} %> found.<BR>
+% }
+% } else {
- <% $total %> total <% $opt{'name'} %>
+ <TABLE>
+ <TR>
-% if ( $confmax && $total > $confmax ) {
-% $cgi->delete('maxrecords');
-% $cgi->param('_dummy', 1);
+ <TD VALIGN="bottom">
-%# ( show <SELECT NAME="maxrecords" onChange="this.form.submit();">
- ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $cgi->self_url %>;maxrecords=' + this.options[this.selectedIndex].value;">
+ <FORM>
-% foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
- <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
-% }
+ <% $total %> total <% $opt{'name'} %>
- </SELECT> per page )
+% if ( $confmax && $total > $confmax && $type ne 'html-print' ) {
+% $cgi->delete('maxrecords');
+% $cgi->param('_dummy', 1);
-% $cgi->param('maxrecords', $maxrecords);
-% }
+%# ( show <SELECT NAME="maxrecords" onChange="this.form.submit();">
+ ( show <SELECT NAME="maxrecords" onChange="window.location = '<% $cgi->self_url %>;maxrecords=' + this.options[this.selectedIndex].value;">
- <% defined($opt{'html_posttotal'})
- ? ( ref($opt{'html_posttotal'})
- ? &{$opt{'html_posttotal'}}()
- : $opt{'html_posttotal'}
- )
- : ''
- %>
- <BR>
+% foreach my $max ( map { $_ * $confmax } qw( 1 5 10 25 ) ) {
+ <OPTION VALUE="<% $max %>" <% ( $maxrecords == $max ) ? 'SELECTED' : '' %>><% $max %></OPTION>
+% }
-% if ( $opt{'count_addl'} ) {
-% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) {
+ </SELECT> per page )
- <% sprintf( $count, $count_arrayref->[++$n] ) %><BR>
+% $cgi->param('maxrecords', $maxrecords);
+% }
-% }
-% }
- </FORM>
+% if ( defined($opt{'html_posttotal'}) && $type ne 'html-print' ) {
+ <% ref($opt{'html_posttotal'})
+ ? &{$opt{'html_posttotal'}}()
+ : $opt{'html_posttotal'}
+ %>
+% }
+ <BR>
- </TD>
+% if ( $opt{'count_addl'} ) {
+% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) {
+ <% sprintf( $count, $count_arrayref->[++$n] ) %><BR>
+% }
+% }
+ </FORM>
-% unless ( $opt{'disable_download'} ) {
+ </TD>
- <TD ALIGN="right">
-% $cgi->param('_type', "$xlsname.xls" );
+% unless ( $opt{'disable_download'} || $type eq 'html-print' ) {
- Download full results<BR>
- as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
-% $cgi->param('_type', 'csv');
+ <TD ALIGN="right">
- as <A HREF="<% $cgi->self_url %>">CSV file</A>
- </TD>
-% $cgi->param('_type', "html" );
-% }
+ Download full results<BR>
- </TR>
- <TR>
- <TD COLSPAN=2>
-
- <% my $pager = include ( '/elements/pager.html',
- 'offset' => $offset,
- 'num_rows' => scalar(@$rows),
- 'total' => $total,
- 'maxrecords' => $maxrecords,
- ) %>
-
- <% defined($opt{'html_form'})
- ? ( ref($opt{'html_form'})
- ? &{$opt{'html_form'}}()
- : $opt{'html_form'}
- )
- : ''
- %>
-
- <% include('/elements/table-grid.html') %>
-
- <TR>
-%
-% foreach my $header ( @$header ) {
+% $cgi->param('_type', "$xlsname.xls" );
+ as <A HREF="<% $cgi->self_url %>">Excel spreadsheet</A><BR>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% $header %></TH>
-% }
+% $cgi->param('_type', 'csv');
+ as <A HREF="<% $cgi->self_url %>">CSV file</A><BR>
- </TR>
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor;
-% foreach my $row ( @$rows ) {
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-%
-
- <TR>
-% if ( $opt{'fields'} ) {
-%
-% my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
-% my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
-% my $colors = $opt{'color'} ? [ @{$opt{'color'}} ] : [];
-% my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
-% my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : [];
-%
-% foreach my $field (
-%
-% map {
-% if ( ref($_) eq 'ARRAY' ) {
-%
-% my $tableref = $_;
-%
-% '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0 WIDTH="100%">'.
-%
-% join('', map {
-%
-% my $rowref = $_;
-%
-% '<tr>'.
-%
-% join('', map {
-%
-% my $e = $_;
-%
-% '<TD '.
-% join(' ', map {
-% uc($_).'="'. $e->{$_}. '"';
-% }
-% grep exists($e->{$_}),
-% qw( align bgcolor colspan rowspan
-% style valign width )
-% ).
-% '>'.
-%
-% ( $e->{'link'}
-% ? '<A HREF="'. $e->{'link'}. '">'
-% : ''
-% ).
-% ( $e->{'size'}
-% ? '<FONT SIZE="'.uc($e->{'size'}).'">'
-% : ''
-% ).
-% ( $e->{'data_style'}
-% ? '<'. uc($e->{'data_style'}). '>'
-% : ''
-% ).
-% $e->{'data'}.
-% ( $e->{'data_style'}
-% ? '</'. uc($e->{'data_style'}). '>'
-% : ''
-% ).
-% ( $e->{'size'} ? '</FONT>' : '' ).
-% ( $e->{'link'} ? '</A>' : '' ).
-% '</td>';
-%
-% } @$rowref ).
-%
-% '</tr>';
-% } @$tableref ).
-%
-% '</table>';
-%
-% } else {
-% $_;
-% }
-% }
-%
-% map {
-% if ( ref($_) eq 'CODE' ) {
-% &{$_}($row);
-% } else {
-% $row->$_();
-% }
-% }
-% @{$opt{'fields'}}
-%
-% ) {
-%
-% my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid';
-%
-% my $align = $aligns ? shift @$aligns : '';
-% $align = " ALIGN=$align" if $align;
-%
-% my $a = '';
-% if ( $links ) {
-% my $link = shift @$links;
-% $link = &{$link}($row) if ref($link) eq 'CODE';
-% if ( $link ) {
-% my( $url, $method ) = @{$link};
-% if ( ref($method) eq 'CODE' ) {
-% $a = $url. &{$method}($row);
-% } else {
-% $a = $url. $row->$method();
-% }
-% $a = qq(<A HREF="$a">);
-% }
-% }
-%
-% my $font = '';
-% my $color = shift @$colors;
-% $color = &{$color}($row) if ref($color) eq 'CODE';
-% my $size = shift @$sizes;
-% $size = &{$size}($row) if ref($size) eq 'CODE';
-% if ( $color || $size ) {
-% $font = '<FONT '.
-% ( $color ? "COLOR=#$color " : '' ).
-% ( $size ? qq(SIZE="$size" ) : '' ).
-% '>';
-% }
-%
-% my($s, $es) = ( '', '' );
-% my $style = shift @$styles;
-% $style = &{$style}($row) if ref($style) eq 'CODE';
-% if ( $style ) {
-% $s = join( '', map "<$_>", split('', $style) );
-% $es = join( '', map "</$_>", split('', $style) );
-% }
-%
-%
-
- <TD CLASS="<% $class %>" BGCOLOR="<% $bgcolor %>"<% $align %>><% $font %><% $a %><% $s %><% $field %><% $es %><% $a ? '</A>' : '' %><% $font ? '</FONT>' : '' %></TD>
-% }
-% } else {
-% foreach ( @$row ) {
+% $cgi->param('_type', 'html-print');
+ as <A HREF="<% $cgi->self_url %>">printable copy</A>
- <TD CLASS="grid" BGCOLOR="$bgcolor"><% $_ %></TD>
-% }
-% }
+ </TD>
+% $cgi->param('_type', "html" );
+% }
- </TR>
-% }
-% if ( $opt{'footer'} ) {
+ </TR>
+ <TR>
+ <TD COLSPAN=2>
- <TR>
-% foreach my $footer ( @{ $opt{'footer'} } ) {
+% my $pager = '';
+% unless ( $type eq 'html_print' ) {
- <TD CLASS="grid" BGCOLOR="#dddddd" STYLE="border-top: dashed 1px black;"><i><% $footer %></i></TH>
-% }
+ <% $pager = include( '/elements/pager.html',
+ 'offset' => $offset,
+ 'num_rows' => scalar(@$rows),
+ 'total' => $total,
+ 'maxrecords' => $maxrecords,
+ )
+ %>
+
+ <% defined($opt{'html_form'})
+ ? ( ref($opt{'html_form'})
+ ? &{$opt{'html_form'}}()
+ : $opt{'html_form'}
+ )
+ : ''
+ %>
+% }
+
+ <% include('/elements/table-grid.html') %>
+
+ <TR>
+% foreach my $header ( @$header ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% $header %></TH>
+% }
</TR>
-% }
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor;
+%
+% foreach my $row ( @$rows ) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+% if ( $opt{'fields'} ) {
+%
+% my $links = $opt{'links'} ? [ @{$opt{'links'}} ] : '';
+% my $aligns = $opt{'align'} ? [ @{$opt{'align'}} ] : '';
+% my $colors = $opt{'color'} ? [ @{$opt{'color'}} ] : [];
+% my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
+% my $styles = $opt{'style'} ? [ @{$opt{'style'}} ] : [];
+%
+% foreach my $field (
+%
+% map {
+% if ( ref($_) eq 'ARRAY' ) {
+%
+% my $tableref = $_;
+%
+% '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0 WIDTH="100%">'.
+%
+% join('', map {
+%
+% my $rowref = $_;
+%
+% '<tr>'.
+%
+% join('', map {
+%
+% my $e = $_;
+%
+% '<TD '.
+% join(' ', map {
+% uc($_).'="'. $e->{$_}. '"';
+% }
+% grep exists($e->{$_}),
+% qw( align bgcolor colspan rowspan
+% style valign width )
+% ).
+% '>'.
+%
+% ( $e->{'link'}
+% ? '<A HREF="'. $e->{'link'}. '">'
+% : ''
+% ).
+% ( $e->{'size'}
+% ? '<FONT SIZE="'.uc($e->{'size'}).'">'
+% : ''
+% ).
+% ( $e->{'data_style'}
+% ? '<'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% $e->{'data'}.
+% ( $e->{'data_style'}
+% ? '</'. uc($e->{'data_style'}). '>'
+% : ''
+% ).
+% ( $e->{'size'} ? '</FONT>' : '' ).
+% ( $e->{'link'} ? '</A>' : '' ).
+% '</td>';
+%
+% } @$rowref ).
+%
+% '</tr>';
+% } @$tableref ).
+%
+% '</table>';
+%
+% } else {
+% $_;
+% }
+% }
+%
+% map {
+% if ( ref($_) eq 'CODE' ) {
+% &{$_}($row);
+% } else {
+% $row->$_();
+% }
+% }
+% @{$opt{'fields'}}
+%
+% ) {
+%
+% my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid';
+%
+% my $align = $aligns ? shift @$aligns : '';
+% $align = " ALIGN=$align" if $align;
+%
+% my $a = '';
+% if ( $links ) {
+% my $link = shift @$links;
+% $link = &{$link}($row) if ref($link) eq 'CODE';
+% if ( $link ) {
+% my( $url, $method ) = @{$link};
+% if ( ref($method) eq 'CODE' ) {
+% $a = $url. &{$method}($row);
+% } else {
+% $a = $url. $row->$method();
+% }
+% $a = qq(<A HREF="$a">);
+% }
+% }
+%
+% my $font = '';
+% my $color = shift @$colors;
+% $color = &{$color}($row) if ref($color) eq 'CODE';
+% my $size = shift @$sizes;
+% $size = &{$size}($row) if ref($size) eq 'CODE';
+% if ( $color || $size ) {
+% $font = '<FONT '.
+% ( $color ? "COLOR=#$color " : '' ).
+% ( $size ? qq(SIZE="$size" ) : '' ).
+% '>';
+% }
+%
+% my($s, $es) = ( '', '' );
+% my $style = shift @$styles;
+% $style = &{$style}($row) if ref($style) eq 'CODE';
+% if ( $style ) {
+% $s = join( '', map "<$_>", split('', $style) );
+% $es = join( '', map "</$_>", split('', $style) );
+% }
+
+ <TD CLASS="<% $class %>" BGCOLOR="<% $bgcolor %>"<% $align %>><% $font %><% $a %><% $s %><% $field %><% $es %><% $a ? '</A>' : '' %><% $font ? '</FONT>' : '' %></TD>
+
+% }
+%
+% } else {
+%
+% foreach ( @$row ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $_ %></TD>
+% }
+%
+% }
+
+ </TR>
+
+% }
+
+% if ( $opt{'footer'} ) {
+
+ <TR>
+
+% foreach my $footer ( @{ $opt{'footer'} } ) {
+ <TD CLASS="grid" BGCOLOR="#dddddd" STYLE="border-top: dashed 1px black;"><i><% $footer %></i></TD>
+% }
+
+ </TR>
+% }
- </TABLE>
- <% $pager %>
+ </TABLE>
+
+ <% $pager %>
- </TD>
- </TR>
- </TABLE>
-% }
+ </TD>
+ </TR>
+ </TABLE>
+% }
- <% defined($opt{'html_foot'})
- ? ( ref($opt{'html_foot'})
- ? &{$opt{'html_foot'}}()
- : $opt{'html_foot'}
- )
- : ''
- %>
- <% include( '/elements/footer.html' ) %>
-% }
+% if ( $type eq 'html-print' ) {
+
+ </BODY></HTML>
+
+% } else {
+
+ <% defined($opt{'html_foot'})
+ ? ( ref($opt{'html_foot'})
+ ? &{$opt{'html_foot'}}()
+ : $opt{'html_foot'}
+ )
+ : ''
+ %>
+
+ <% include( '/elements/footer.html' ) %>
+
+% }
+
+% }
+%
% }
+<%init>
+
+my(%opt) = @_;
+#warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n";
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my %align = (
+ 'l' => 'left',
+ 'r' => 'right',
+ 'c' => 'center',
+ ' ' => '',
+ '.' => '',
+);
+$opt{align} = [ map $align{$_}, split(//, $opt{align}) ],
+ unless !$opt{align} || ref($opt{align});
+
+if ( $opt{'agent_virt'} ) {
+
+ my $agentnums_sql = $curuser->agentnums_sql(
+ 'null_right' => $opt{'agent_null_right'}
+ );
+
+ $opt{'query'}{'extra_sql'} .=
+ ( $opt{'query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ $agentnums_sql;
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ $agentnums_sql;
+
+ if ( $opt{'agent_pos'} || $opt{'agent_pos'} eq '0'
+ and scalar($curuser->agentnums) > 1 ) {
+ #false laziness w/statuspos above
+ my $pos = $opt{'agent_pos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Agent';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, '';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { $_[0]->agentnum ? $_[0]->agent->agent : '(global)'; };
+ splice @{ $opt{'color'} }, $pos, 0, '';
+ splice @{ $opt{'links'} }, $pos, 0, '' #[ 'agent link?', 'agentnum' ]
+ if $opt{'links'};
+
+ }
+
+}
+
+if ( $opt{'disableable'} ) {
+
+ unless ( $cgi->param('showdisabled') ) { #modify searches
+
+ $opt{'query'}{'hashref'}{'disabled'} = '';
+ $opt{'query'}{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+
+ $opt{'count_query'} .=
+ ( $opt{'count_query'} =~ /WHERE/i ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+
+ } elsif ( $opt{'disabled_statuspos'}
+ || $opt{'disabled_statuspos'} eq '0' ) { #add status column
+
+ my $pos = $opt{'disabled_statuspos'};
+
+ foreach my $att (qw( align style color size )) {
+ $opt{$att} ||= [ map '', @{ $opt{'fields'} } ];
+ }
+
+ splice @{ $opt{'header'} }, $pos, 0, 'Status';
+ splice @{ $opt{'align'} }, $pos, 0, 'c';
+ splice @{ $opt{'style'} }, $pos, 0, 'b';
+ splice @{ $opt{'size'} }, $pos, 0, '';
+ splice @{ $opt{'fields'} }, $pos, 0,
+ sub { shift->disabled ? 'DISABLED' : 'Active'; };
+ splice @{ $opt{'color'} }, $pos, 0,
+ sub { shift->disabled ? 'FF0000' : '00CC00'; };
+ splice @{ $opt{'links'} }, $pos, 0, ''
+ if $opt{'links'};
+ }
+
+ #add show/hide disabled links
+ my $items = $opt{'name'} || PL($opt{'name_singular'});
+ if ( $cgi->param('showdisabled') ) {
+ $cgi->param('showdisabled', 0);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">hide disabled $items</a> )!;
+ $cgi->param('showdisabled', 1);
+ } else {
+ $cgi->param('showdisabled', 1);
+ $opt{'html_posttotal'} .=
+ '( <a href="'. $cgi->self_url. qq!">show disabled $items</a> )!;
+ $cgi->param('showdisabled', 0);
+ }
+
+}
+
+my $type = $cgi->param('_type') =~ /^(csv|\w*\.xls|html(-print)?)$/
+ ? $1 : 'html';
+
+my $limit = '';
+my($confmax, $maxrecords, $total, $offset, $count_arrayref);
+
+unless ( $type =~ /^(csv|\w*\.xls)$/ ) {
+
+ unless (exists($opt{count_query}) && length($opt{count_query})) {
+ ( $opt{count_query} = $opt{query} ) =~
+ s/^\s*SELECT\s*(.*?)\s+FROM\s/SELECT COUNT(*) FROM /i; #silly vim:/
+ }
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ $opt{count_query} .=
+ ( ( $opt{count_query} =~ /WHERE/i ) ? ' AND ' : ' WHERE ' ).
+ "( disabled = '' OR disabled IS NULL )";
+ }
+
+ unless ( $type eq 'html-print' ) {
+
+ #setup some pagination things if we're in html mode
+
+ my $conf = new FS::Conf;
+ $confmax = $conf->config('maxsearchrecordsperpage');
+ if ( $cgi->param('maxrecords') =~ /^(\d+)$/ ) {
+ $maxrecords = $1;
+ } else {
+ $maxrecords ||= $confmax;
+ }
+
+ $limit = $maxrecords ? "LIMIT $maxrecords" : '';
+
+ $offset = $cgi->param('offset') =~ /^(\d+)$/ ? $1 : 0;
+ $limit .= " OFFSET $offset" if $offset;
+
+ }
+
+ my $count_sth = dbh->prepare($opt{'count_query'})
+ or die "Error preparing $opt{'count_query'}: ". dbh->errstr;
+ $count_sth->execute
+ or die "Error executing $opt{'count_query'}: ". $count_sth->errstr;
+ $count_arrayref = $count_sth->fetchrow_arrayref;
+ $total = $count_arrayref->[0];
+
+}
+
+# run the query
+
+my $header = $opt{header};
+my $rows;
+if ( ref($opt{query}) ) {
+
+ if ( $opt{disableable} && ! $cgi->param('showdisabled') ) {
+ #%search = ( 'disabled' => '' );
+ $opt{'query'}->{'hashref'}->{'disabled'} = '';
+ $opt{'query'}->{'extra_sql'} =~ s/^\s*WHERE/ AND/i;
+ }
+
+ #eval "use FS::$opt{'query'};";
+ $rows = [ qsearch({
+ 'select' => $opt{'query'}->{'select'},
+ 'table' => $opt{'query'}->{'table'},
+ 'addl_from' => (exists($opt{'query'}->{'addl_from'}) ? $opt{'query'}->{'addl_from'} : ''),
+ 'hashref' => $opt{'query'}->{'hashref'} || {},
+ 'extra_sql' => $opt{'query'}->{'extra_sql'},
+ 'order_by' => $opt{'query'}->{'order_by'}. " $limit",
+ }) ];
+} else {
+ my $sth = dbh->prepare("$opt{'query'} $limit")
+ or die "Error preparing $opt{'query'}: ". dbh->errstr;
+ $sth->execute
+ or die "Error executing $opt{'query'}: ". $sth->errstr;
+
+ #can get # of rows without fetching them all?
+ $rows = $sth->fetchall_arrayref;
+
+ $header ||= $sth->{NAME};
+}
+
+</%init>