Subversion Repositories VORC

Rev

Rev 196 | Rev 199 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
50 bgadell 1
#package tableViewer;
2
 
7 - 3
#######################################################################
4
# A set of functions to assist the scan data display tool.
196 - 5
# Kept here to unclutter the main script.
7 - 6
#######################################################################
7
#
8
#
9
# $Log: scanFunctions.pm,v $
10
#
11
 
50 bgadell 12
#use strict;
13
use Exporter 'import';
9 - 14
use cPanelUserConfig;
7 - 15
use DBI ();
16
use WebDB;
17
 
196 - 18
our @EXPORT = qw( byfield currentTime exportExcel fetchColEntries fetchDerbyNameWithRCid filter getData getDBConnection inArray notInArray uniq whereInArray printTablePage );
50 bgadell 19
 
153 - 20
my $internalDBH = WebDB::connect () || die "Unable to connect to Database\n\n";
7 - 21
 
22
sub currentTime {
25 - 23
  use DateTime;
24
  my $now = DateTime->now (time_zone => 'America/Los_Angeles');
25
  $now =~ s/T/ at /;
7 - 26
 
25 - 27
  return $now." US/Pacific";
7 - 28
}
29
 
196 - 30
sub byfield { $colOrderHash{$a} <=> $colOrderHash{$b}; }
7 - 31
 
32
sub exportExcel {
33
  my $listref = shift;
196 - 34
  my $FN_Prefix = shift // "VORC_Export";
7 - 35
 
36
  use Spreadsheet::WriteExcel;
196 - 37
 
38
  my $date = `date +"%m%d%y%H%M%S"`; chomp $date;
7 - 39
  my $filename = "${FN_Prefix}_${date}_$$.xls";
40
 
196 - 41
  print "Content-type: application/vnd.ms-excel\n";
7 - 42
  # The Content-Disposition will generate a prompt to save the file. If you want
43
  # to stream the file to the browser, comment out the following line.
44
  print "Content-Disposition: attachment; filename=$filename\n";
45
  print "\n";
196 - 46
 
7 - 47
  # Create a new workbook and add a worksheet. The special Perl filehandle - will
48
  # redirect the output to STDOUT
49
  #
50
  my $workbook  = Spreadsheet::WriteExcel->new(\*STDOUT);
51
  my $worksheet = $workbook->add_worksheet();
196 - 52
 
53
  my $format = $workbook->add_format();
54
  $format->set_bold();
55
 
56
  my $col = $row = 0;
57
 
58
  foreach $f (@displayFields)
59
    { $worksheet->write($row, $col++, "$NAME{$f}", $format); }
60
 
61
  foreach $t (sort @{ $listref })     # Unt now we print the tickets!
62
  {
63
    $col = 0;
64
    $row++;
65
    foreach $f (@displayFields) {
66
      if ($f eq "derby_name") {
67
        if ($user->{department}->{"OFF"} < 2 and $t->{derby_name} and $t->{RCid} != $RCid and $LVL < 5) {
68
          $t->{derby_name} = "FILLED";
69
        }
70
      }
71
      $t->{$f} =~ s/<br>/\n/ig; $worksheet->write($row, $col++, "$t->{$f}");
72
    }
73
  }
74
 
75
  $workbook->close();
7 - 76
  return;
77
}
78
 
79
 
196 - 80
sub fetchColEntries {
81
  my $colName = shift;
82
  my $selection = shift;
197 - 83
  my $year = shift // "year(now())";
196 - 84
  my $table = $DBTABLE;
85
  my $optionList = "";
7 - 86
 
87
  if ($colName eq "derby_name" and $LVL < 2) {
88
    # special case to anonymize assignees...
122 - 89
    my @opts = ("-blank-", $ORCUSER->{derby_name});
90
    push @opts, map { @{$_} } @{ $internalDBH->selectall_arrayref ("select derby_name from official where showme = 1 and derby_name <> ? order by derby_name", undef, $ORCUSER->{derby_name}) };
91
    $optionList = join "", map { $selection eq $_ ? "<OPTION selected>$_</OPTION>" : "<OPTION>$_</OPTION>" } @opts;
7 - 92
  } else {
197 - 93
    my $dept_where = $table eq "v_shift" ? "where dept != 'PER' and year(date) = $year" : "";
46 - 94
    my $orderby = $colName eq "dayofweek" ? "field(dayofweek, 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')" : $colName;
196 - 95
    my $cathan = $internalDBH->prepare("select distinct nullif($colName, '') from $table $dept_where order by $orderby");
96
 
97
    $cathan->execute();
98
    while (my ($cat) = $cathan->fetchrow) {
99
      if (!$cat) { $cat = "-blank-"; }
100
      if ($cat eq $selection) {
101
        $optionList .= "<OPTION selected>$cat</OPTION>";
102
      } else {
103
        $optionList .= "<OPTION>$cat</OPTION>";
104
      }
105
    }
7 - 106
  }
107
 
196 - 108
  return $optionList;
7 - 109
}
110
 
111
sub fetchDerbyNameWithRCid {
97 bgadell 112
  my $ATTRIBUTES;
113
  if (ref $_[0] eq "HASH") {
114
    $ATTRIBUTES = shift;
115
  }
7 - 116
  my $DEPT = shift // "";
57 bgadell 117
  my $selected = shift // "";
196 - 118
  my $optionList = "";
119
 
120
  my $cathan;
121
  if (!$DEPT or $DEPT eq "CMP") {
122
    $cathan = $internalDBH->prepare("select RCid, derby_name from official where access > 0 order by derby_name");
123
    $cathan->execute();
57 bgadell 124
  } elsif ($DEPT eq "CLA") {
97 bgadell 125
    $cathan = $internalDBH->prepare("select RCid, derby_name from v_official where access > 0 and isnull(MVPid) = false and last_login > CURRENT_DATE - INTERVAL 365 DAY order by derby_name");
57 bgadell 126
    $cathan->execute;
196 - 127
  } else {
97 bgadell 128
    $cathan = $internalDBH->prepare("select RCid, derby_name from official where access > 0 and (department like ? and department not like ?) and last_login > CURRENT_DATE - INTERVAL 365 DAY order by derby_name");
16 - 129
    $cathan->execute("%".$DEPT."%", "%".$DEPT."-0%");
196 - 130
  }
97 bgadell 131
 
132
  my $valuelabel = $ATTRIBUTES->{DATALIST} ? "data-value" : "value";
196 - 133
  while (my ($id, $cat) = $cathan->fetchrow) {
134
    if ($id == $selected) {
135
      $optionList .= "<OPTION $valuelabel=$id selected>$cat</OPTION>";
136
    } else {
137
      $optionList .= "<OPTION $valuelabel=$id>$cat</OPTION>";
138
    }
139
  }
7 - 140
 
196 - 141
  return $optionList;
7 - 142
}
143
 
144
 
145
sub filter {
196 - 146
  my $colName = shift;
147
  my $filter = shift;
197 - 148
  my $year = shift;
196 - 149
 
150
  if (exists &{"filter_".$colName}) { return &{"filter_".$colName} ($colName, $filter); }
151
 
152
  if ($colFilterTypeHash{$colName} eq 'select')
153
  {
154
    if (defined $filter)  {
155
      if ($filter eq "-blank-") {
156
        return "($colName = '' or isNull($colName) = 1)";
157
      }
158
#     $filter = s/'/\'/g;
159
      return "$colName = \"$filter\"";
160
    }
161
    else
162
    {
163
      my $thing = "filter-${colName}";
197 - 164
      my $categories = $year ? fetchColEntries ($colName, $FORM{$thing}, $year) : fetchColEntries ($colName, $FORM{$thing});
196 - 165
      my $Options = "<OPTION></OPTION>".$categories;
7 - 166
 
196 - 167
      $Options =~ s/>($FORM{$thing})/ selected>$1/;
168
      return "<SELECT name=filter-${colName} $onChange>$Options</SELECT>";
169
    }
170
  } elsif ($colFilterTypeHash{$colName} eq 'text') {
171
    if (defined $filter)
172
    {
173
      if ($filter =~ /\d{1,2}:\d{2}/ and $ORCUSER->{timeformat} eq "ampm") {
174
        my ($h, $m) = split /:/, $filter;
175
        my $caret;
176
        if ($h =~ s/^\^\s*//) { $caret = "^"; }
177
        if ($h < 8) { $h += 12; }
178
        $filter = $caret.join ":", $h, $m;
179
      }
180
 
181
      if ($filter =~ s/^=\s*//) { return "$colName = \"$filter\""; }
182
 
183
      if ($filter !~ s/^\^\s*//) { $filter = "\%$filter"; }
184
      if ($filter !~ s/\s*\$$//) { $filter = "$filter\%"; }
185
      $filter =~ s/\*/%/g;
186
 
187
      return "$colName like \"$filter\"";
188
    }
189
    else
190
    {
191
      my $thing = "filter-${colName}";
192
      return "<INPUT type=text name=$thing value=\"$FORM{$thing}\" size=15 $onChange>";
193
    }
194
  } elsif ($colFilterTypeHash{$colName} eq 'number') {
195
    if (defined $filter)
196
    {
197
      if ($filter =~ /^[>=<]\s*/) { return "$colName $filter"; }
198
      else { return "$colName = $filter"; }
199
    }
200
    else
201
    {
202
      my $thing = "filter-${colName}";
203
      return "<INPUT type=text name=$thing value=\"$FORM{$thing}\" size=2 $onChange>";
204
    }
205
  } elsif ($colFilterTypeHash{$colName} eq 'date') {
206
    if (defined $filter)
207
    {
208
      if ($filter =~ s/^<\s*//) { return "$colName < '$filter'"; }
209
      if ($filter =~ s/^>\s*//) { return "$colName > '$filter'"; }
210
 
211
      return "$colName = '$filter'";
212
    }
213
    else
214
    {
215
      my $thing = "filter-${colName}";
216
      return "<INPUT type=text name=$thing value=\"$FORM{$thing}\" size=15 $onChange>";
217
    }
218
  } elsif ($colFilterTypeHash{$colName} eq 'boolean') {
219
    if (defined $filter)
220
    {
221
      return "$colName = $filter";
222
    }
223
    else
224
    {
225
      my $thing = "filter-${colName}";
226
      my $Options = "<OPTION></OPTION><OPTION>True</OPTION><OPTION>False</OPTION>";
227
 
228
      $Options =~ s/>($FORM{$thing})/ selected>$1/;
229
      return "<SELECT name=filter-${colName} $onChange>$Options</SELECT>";
230
    }
231
  } elsif ($colFilterTypeHash{$colName} eq 'ERROR') {
232
    return "<center><strong><font color=red>ERROR!</font>";
233
  } elsif ($colFilterTypeHash{$colName} eq 'none') {
234
    return;
235
  }
7 - 236
}
237
 
238
 
239
sub getData {
196 - 240
  my $fields = shift;
241
  my $whereClause = shift;
242
  my $table = shift;
243
  my $orderby = shift;
244
  my $curpage = shift; $curpage = 1 unless $curpage;
245
  my $pagelimit = shift // "All";
7 - 246
 
196 - 247
  my $selected = '*';
248
  $whereClause = scalar @{$whereClause} > 0 ? "where ".join (" and ", @{$whereClause}) : '';
249
 
7 - 250
  if ($orderby eq "dayofweek") {
196 - 251
    $orderby = "order by date, time";
7 - 252
  } elsif ($orderby eq "eventid") { # only applicable to the log viewer...
196 - 253
    $orderby = "order by eventid desc";
254
  } elsif ($orderby eq "key") { # for the settings page, the column name 'key' is a reserved word in mysql
255
    $orderby = "order by ${table}.key";
7 - 256
  } else {
196 - 257
    $orderby = $orderby eq "" ? "" : "order by $orderby";
7 - 258
  }
259
 
260
  my $getMe;
261
  if ($pagelimit eq "All") {
196 - 262
    $getMe = "select distinct * from $table $whereClause $orderby";
7 - 263
  } else {
264
    $curpage = ($curpage - 1) * $pagelimit;
196 - 265
    $getMe = "select distinct * from $table $whereClause $orderby limit $curpage, $pagelimit";
7 - 266
  }
196 - 267
  my ($totalcount) = @{$internalDBH->selectrow_arrayref ("select distinct count(*) from $table $whereClause")};
197 - 268
  # warn $getMe;
196 - 269
  my $limhan = $internalDBH->prepare($getMe);     # Get the tickets from the DB
270
  $limhan->execute();
271
 
272
  my @results = ();
273
  while (my $P = $limhan->fetchrow_hashref)
274
  {
275
    push @results, $P;
276
  }
277
 
278
  return (\@results, $totalcount);
7 - 279
}
280
 
281
 
282
sub getDBConnection {
283
  use WebDB;
284
  $dbh = WebDB::connect ();
285
  return $dbh;
286
}
287
 
288
 
289
sub inArray {
196 - 290
  my $item = shift;
291
  my $array = shift;
292
  foreach (@{$array})
293
  {
294
    return 1 if $item eq $_;
295
  }
296
  return 0;
7 - 297
}
298
 
299
sub notInArray {
196 - 300
  return ! inArray (@_);
7 - 301
}
302
 
303
 
304
sub uniq (@) {
305
    # From CPAN List::MoreUtils, version 0.22
306
    my %h;
307
    map { $h{$_}++ == 0 ? $_ : () } @_;
308
}
309
 
310
 
311
sub whereInArray {
196 - 312
  my $item = shift;
313
  my $array = shift;
314
  my $i = 0;
315
  foreach (@{$array})
316
  {
317
    return $i if $item eq $_;
318
    $i++;
319
  }
320
  return -1;
7 - 321
}
322
 
196 - 323
sub printTablePage {
324
  my $paramhash = shift;
325
  my $RCAUTH_cookie = $paramhash->{RCAuth} // "";
326
  my $pageTitle = $paramhash->{Title};
327
  my $prefscookie = $paramhash->{Prefs} // "";
328
    ($prefscookie = lc $pageTitle) =~ s/\s+//g unless $prefscookie;
329
  my $DBTABLE = $paramhash->{Table};
330
  my $COLUMNS = $paramhash->{Columns};
331
  my $defaultWhereClause = $paramhash->{Where} // "";
332
  my $displayYearSelect = $paramhash->{DisplayYearSelect} // 1;
333
  my $showMyShiftsOption = $paramhash->{ShowMyShifts} // 0;
334
  my $highlightShifts = $paramhash->{HighlightShifts} // 0;
335
  my $headerButton = $paramhash->{HeaderButton} // "";
336
  my $blockPersonalTime = $paramhash->{PersonalTimeButton} // "";
337
 
338
  use CGI qw/param cookie header start_html url/;
339
  use HTML::Tiny;
340
  my $h = HTML::Tiny->new( mode => 'html' );
341
 
342
  my $stylesheet = "/style.css";
343
  my $homeURL = '/schedule/';
344
  my @pagelimitoptions = ("All", 5, 10, 25);
345
  my $YEAR;
346
 
347
  # Extract the column names and build utility variables
348
  my %NAME              = map  { $_ => $COLUMNS->{$_}->[0] } keys %{$COLUMNS};
349
  my %colOrderHash      = map  { $_ => $COLUMNS->{$_}->[1] } keys %{$COLUMNS};
350
  sub byfield { $colOrderHash{$a} <=> $colOrderHash{$b}; }
351
  our %colFilterTypeHash = map  { $_ => $COLUMNS->{$_}->[2] } keys %{$COLUMNS};
352
  my @staticFields      = sort byfield grep { $COLUMNS->{$_}->[3] and $COLUMNS->{$_}->[3] eq 'static' } keys %{$COLUMNS};
353
  my @defaultFields     = sort byfield grep { defined $COLUMNS->{$_}->[3] } keys %{$COLUMNS};
354
 
355
  my @allFields = sort byfield keys %NAME;
356
  my @displayFields = ();
357
  my @hideFields = ();
358
  my $QUERY_STRING;
359
 
360
  my $pagelimit = param ("limit") // $pagelimitoptions[$#pagelimitoptions];
361
  my $curpage = param ("page") // 1;
362
 
363
  our %FORM;
364
  my $FILTER;
365
  foreach (param()) {
366
    if (/^year$/) {
367
      $YEAR = param($_);
368
      next;
369
    }
370
 
371
    $FORM{$_} = param($_);        # Retrieve all of the FORM data submitted
372
    #warn "$_: $FORM{$_}";
373
 
374
    if ((/^filter/) and ($FORM{$_} ne '')) {  # Build a set of filters to apply
375
      my ($filter,$field) = split /-/, $_;
376
      $FILTER->{$field} = $FORM{$_} unless notInArray ($field, \@allFields);
377
    } elsif ($FORM{$_} eq "true")     # Compile list of fields to display
378
      { push @displayFields, $_ unless /shiftinclude/; }
379
  }
380
 
381
  if (exists $FORM{autoload}) {     # If the FORM was submitted (i.e. the page is being redisplayed),
382
                                    #   build the data for the cookie that remembers the page setup
383
    my $disFields = join ":", @displayFields;
384
    my $fils = join ":", map { "$_=$FILTER->{$_}" } keys %{$FILTER};
385
 
386
    $QUERY_STRING = $disFields.'&'.$fils.'&'.$FORM{sortby}.'&'.$FORM{autoload};
387
    $QUERY_STRING .= '&'.$FORM{shiftinclude} unless !$FORM{shiftinclude};
388
  }
389
 
390
  if (!(exists $FORM{autoload}))  {     # No FORM was submitted...
391
    if (my $prefs = cookie ($prefscookie) and !defined param ("ignoreCookie"))  { # Check for cookies from previous visits.
392
      my ($disF, $filts, $sb, $al, $si) = split /&/,$prefs;
393
      @displayFields = split /:/,$disF;
394
 
395
      foreach my $pair (split /:/, $filts)  {
396
        my ($key, $value) = split /=/, $pair;
397
        $FORM{"filter-$key"} = $value;
398
        $FILTER->{$key} = $value;
399
      }
400
 
401
      $FORM{sortby} = $sb;
402
      $FORM{autoload} = $al;
403
      $FORM{shiftinclude} = $si;
404
      $QUERY_STRING = $prefs;
405
    } else {
406
      @displayFields = @defaultFields; # Otherwise suppply a default list of columns.
407
      $FORM{autoload} = 1;             # And turn autoload on by default.
408
    }
409
  }
410
 
411
  # let's just make sure the columns are in the right order (and there aren't any missing)
412
  @displayFields = grep { inArray($_, \@allFields) } sort byfield uniq @displayFields, @staticFields;
413
 
414
  # If the field isn't in the displayFields list, then add it to the hideFields list
415
  @hideFields = grep { notInArray ($_, \@displayFields) } @allFields;
416
 
417
  # Process any filters provided in the form to pass to the database
418
  my @whereClause; # = $defaultWhereClause;
419
  push @whereClause, $defaultWhereClause unless !$defaultWhereClause;
420
  if ($displayYearSelect) {
421
    my $yearfield = inArray("date", \@allFields) ? 'year(date)' : "year";  # some pages only use the year, and not a date
422
 
423
    if ($YEAR) {
424
      push @whereClause, "$yearfield = '$YEAR'";
425
    } else {
426
      push @whereClause, "$yearfield = year(now())";
427
    }
428
  }
429
  push @whereClause, map { filter ($_, $FILTER->{$_}) } grep { defined $FILTER->{$_} } @displayFields;
430
 
431
                #  Given the fields to display and the where conditions,
432
                #   "getData" will return a reference to an array of
433
                #   hash references of the results.
434
  my ($data, $datacount) = getData (\@displayFields, \@whereClause, $DBTABLE, $FORM{sortby}, $curpage, $pagelimit);
435
  my @ProductList = @{ $data };
436
 
437
  my $x = scalar @ProductList; # How many results were returned?
438
 
439
  # If the user is trying to download the Excel file, send it to them and then exit out.
440
  if ($FORM{excel}) {
441
    (my $filename = $pageTitle) =~ s/\s+/_/g;
442
    exportExcel (\@ProductList, $filename);
443
    exit;
444
  }
445
 
446
  my @shifts;
447
  if ($FORM{shiftinclude} eq "true") {
448
    my @SIWhere = ("year(date) = '$YEAR'");
449
    push @SIWhere, "RCid = $ORCUSER->{RCid}";
450
    my ($d, $c) = getData (\@displayFields, \@SIWhere, $DBTABLE, $FORM{sortby});
451
    @shifts = @{ $d };
452
  }
453
 
454
  my $username = $h->a ({ href=>"/schedule/view_user.pl?submit=View&RCid=$ORCUSER->{RCid}" }, $ORCUSER->{derby_name});
455
  my $signedOnAs = $username ? "Welcome, $username. ".$h->input ({ type=>"button", value=>"Log Out", onClick=>"window.location.href='index.pl?LOGOUT';" }) : "You are not signed in.";
456
 
457
  # Set some cookie stuff...
458
  my $path = `dirname $ENV{SCRIPT_NAME}`; chomp $path; $path .= '/' unless $path eq "/";
459
  my $queryCookie = cookie(-NAME=>$prefscookie,
460
        -VALUE=>"$QUERY_STRING",
461
        -PATH=>"$path",
462
        -EXPIRES=>'+365d');
463
 
464
  # Print the header
465
  print header (-cookie=> [ $queryCookie, $RCAUTH_cookie ] );
466
 
467
  #------------------
468
 
469
  # Toggle the autoload fields within the table elements
470
  our ($onClick, $onChange);   # (also used in scanFunctions)
471
  my ($radiobutton, $refreshbutton, $sortby);
472
  if ($FORM{autoload}) {
473
    $onClick = "onClick='submit();'";
474
    $onChange = "onChange='page.value = 1; submit();'";
475
    $radiobutton = $h->div ({ class=>'autoload' },
476
      ["Autoload Changes: ",
477
      $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>1, onClick=>'submit();', checked=>[] }), "On ",
478
      $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>0, onClick=>'submit();' }), "Off ",
479
      ]);
480
    $refreshbutton = "";
481
    $sortby = $h->select ({name=>"sortby", onChange=>'submit();' }, [ map { $FORM{sortby} eq $_ ? $h->option ({ value=>$_, selected=>[] }, $NAME{$_}) : $h->option ({ value=>$_ }, $NAME{$_}) } @displayFields ]);
482
  } else {
483
    $onClick = "";
484
    $onChange = "onChange='page.value = 1;'";
485
    $radiobutton = $h->div ({ class=>'autoload' },
486
      ["Autoload Changes: ",
487
      $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>1, onClick=>'submit();' }), "On ",
488
      $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>0, onClick=>'submit();', checked=>[] }), "Off ",
489
      ]);
490
    $refreshbutton = $h->input ({ type=>"button", value=>"Refresh", onClick=>"submit(); return false;" });
491
    $sortby = $h->select ({name=>"sortby" }, [ map { $FORM{sortby} eq $_ ? $h->option ({ value=>$_, selected=>[] }, $NAME{$_}) : $h->option ({ value=>$_ }, $NAME{$_}) } @displayFields ]);
492
  }
493
 
494
  # "Shift Include" shows a checkbox to include a users shifts at the top of the page
495
  my $SIChecked;
496
  if ($showMyShiftsOption) {
497
    if ($FORM{shiftinclude}) {
498
      $SIChecked = "Show my shifts: ".$h->input ({ type=>"checkbox", name=>"shiftinclude", value=>"true", checked=>[], onClick=>'submit();' });
499
    } else {
500
      $SIChecked = "Show my shifts: ".$h->input ({ type=>"checkbox", name=>"shiftinclude", value=>"true", onClick=>'submit();' });
501
    }
502
  }
503
 
504
  # If the block personal time flag is set, include a button to go to that form.
505
  $SIChecked .= '&nbsp;'.$h->input ({ type=>"button", value=>"Block Personal Time", onClick=>"window.location.href='personal_time.pl'" }) unless !$blockPersonalTime;
506
  $SIChecked .= $h->br unless !$SIChecked;
507
 
508
  print start_html (-title => $pageTitle, -style => {'src' => $stylesheet} );
509
 
510
  print $h->open ('form', { action=>url, method=>'POST', name=>'Req' });
511
  print $h->input ({ type=>"hidden", name=>"excel", value=>0 });
512
  print $h->div ({ class => "accent pageheader" }, [
513
    $h->h1 ($pageTitle),
514
    $h->div ({ class=>"sp0" }, [
515
      $h->div ({ class=>"spLeft" }, [
516
        $radiobutton
517
      ]),
518
      $h->div ({ class=>"spRight" }, [
519
        $h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href=".$homeURL }),
520
        $refreshbutton
521
      ]),
522
    ]),
523
  ]);
524
 
525
  # Print the Hidden fields' check boxes (if there are any)
526
  my $c = 1;
527
  my @hiddencheckboxes;
528
  my @hiddenrows;
529
  foreach my $field (sort { $NAME{$a} cmp $NAME{$b}; } @hideFields) {
530
    if ($FORM{autoload}) {
531
      push @hiddencheckboxes, $h->div ({ class=>'rTableCell quarters nowrap', onClick=>"Req.$field.click();" }, [ $h->input ({ type=>'checkbox', class=>'accent', name=>$field, value=>'true', onClick=>"event.stopPropagation(); submit();" }), $NAME{$field} ]);
532
    } else {
533
      push @hiddencheckboxes, $h->div ({ class=>'rTableCell quarters nowrap', onClick=>"Req.$field.checked=!Req.$field.checked;" }, [ $h->input ({ type=>'checkbox', class=>'accent', name=>$field, value=>'true', onClick=>"event.stopPropagation();" }), $NAME{$field} ]);
534
    }
535
    if ($c++ % 4 == 0) {
536
      push @hiddenrows, $h->div ({ class=>'rTableRow' }, [ @hiddencheckboxes ]);
537
      @hiddencheckboxes = [];
538
    }
539
  }
540
  push @hiddenrows, $h->div ({ class=>'rTableRow' }, [ @hiddencheckboxes ]) unless --$c % 4 == 0;
541
 
542
  if (scalar @hideFields) {
543
    my @topleft;
544
    push @topleft, $h->div ({ class=>"nowrap" }, "Hidden Columns:");
545
    push @topleft, $h->div ({ class=>'rTable' }, [ @hiddenrows ]);
546
 
547
    print $h->div ({ class=>"sp0" }, [
548
      $h->div ({ class=>"spLeft"  }, [ @topleft ]),
549
      $h->div ({ class=>"spRight" }, [
550
        $signedOnAs, $h->br,
551
        $SIChecked,
552
      ])
553
    ]);
554
  }
555
 
556
  # Print the main table...............................................
557
 
558
  print $h->open ('div', { class=>'rTable' });
559
 
560
  my @tmptitlerow;
561
  foreach my $f (@displayFields)  {  # Print the Column headings
562
    my $special_button;
563
    if ($headerButton) {
564
      if ($f eq $headerButton->{field}) {
565
        $special_button = '&nbsp;'.$headerButton->{button};
566
      }
567
    }
568
    if (inArray ($f, \@staticFields)) {
569
      push @tmptitlerow, $h->div ({ class=>'rTableHead' }, [ $h->input ({ type=>"hidden", name=>$f, value=>"true" }), $NAME{$f}, $special_button ]);
570
    } else {
571
      if ($FORM{autoload}) {
572
        push @tmptitlerow, $h->div ({ class=>'rTableHead', onClick=>"Req.$f.click();" }, [ $h->input ({ type=>"checkbox", class=>"accent", name=>$f, value=>"true", checked=>[], onClick=>'event.stopPropagation(); submit();' }), $NAME{$f}, $special_button ]);
573
      } else {
574
        push @tmptitlerow, $h->div ({ class=>'rTableHead', onClick=>"Req.$f.checked=!Req.$f.checked;" }, [ $h->input ({ type=>"checkbox", class=>"accent", name=>$f, value=>"true", checked=>[], onClick=>"event.stopPropagation();" }), $NAME{$f}, $special_button ]);
575
      }
576
    }
577
  }
578
 
579
  # Print the filter boxes...
197 - 580
  print $h->div ({ class=>'rTableHeading' }, [ @tmptitlerow ], [ map { $h->div ({ class=>'rTableCell filters' }, filter ($_, undef, $YEAR)) } @displayFields ], $h->div ({ class=>"rTableCell" }));
196 - 581
 
582
  if ($FORM{shiftinclude}) {  # Include all of the user's shifts at the top
583
    foreach my $t (@shifts) {
584
      no strict;
585
      print $h->div ({ class=>'rTableRow highlighted' }, [ map { $h->div ({ class=>'rTableCell' }, exists &{"modify_".$_} ? &{"modify_".$_} ($t) : $t->{$_} ? $t->{$_} : "") } @displayFields ]);
586
    }
587
    print $h->hr ({ width=>"500%" });
588
  }
589
 
590
 
591
  # Print the things
592
  foreach my $t (@ProductList)  {
593
    my $shading = ($highlightShifts and $t->{RCid} eq $ORCUSER->{RCid}) ? "highlighted" : "shaded";
594
    no strict; # 'strict' doesn't like the exists functionality
595
    my $rowclick = (exists &addRowClick) ? addRowClick ($t) : "";
596
 
597
    print $h->div ({ class=>'rTableRow '.$shading, onClick=>$rowclick }, [ map { $h->div ({ class=>'rTableCell' }, exists &{"modify_".$_} ? &{"modify_".$_} ($t) : $t->{$_} ? $t->{$_} : "") } @displayFields ]);
598
  }
599
 
600
  print $h->close ('div');
601
 
602
  # close things out................................................
603
 
604
  my $pages = $pagelimit eq "All" ? 1 : int( $datacount / $pagelimit + 0.99 );
605
  if ($curpage > $pages) { $curpage = $pages; }
606
 
607
  my @pagerange;
608
  if ($pages <= 5 ) {
609
    @pagerange = 1 .. $pages;
610
  } else {
611
    if ($curpage <= 3) {
612
      @pagerange = (1, 2, 3, 4, ">>");
613
    } elsif ($curpage >= $pages - 2) {
614
      @pagerange = ("<<", $pages-3, $pages-2, $pages-1, $pages);
615
    } else {
616
      @pagerange = ("<<", $curpage-1, $curpage, $curpage+1, ">>");
617
    }
618
  }
619
 
620
  my @yearoptions;
621
  if ($displayYearSelect) {
622
    my $currentyear;
623
    foreach (@{&getYears()}) {
624
      push @yearoptions, $YEAR eq $_ ? $h->option ({ selected=>[] }, $_) : $h->option ($_);
625
      $currentyear = $_;
626
    }
627
    $yearoptions[$#yearoptions] = $h->option ({ selected=>[] }, $currentyear) unless $YEAR;
628
  }
629
 
630
  print $h->br; # print $h->br;
631
  print $h->div ({ class=>"sp0" }, [
632
      $h->div ({ class=>"spLeft" }, [
633
        $h->div ({ class=>"footer" }, [
634
          "To bookmark, save, or send this exact view, use the ",
635
          $h->a ({ href=>'', onClick=>"window.document.Req.method = 'GET'; Req.submit(); return false;" }, "[Full URL]"),
636
          $h->br,
637
          "If this page is displaying oddly, ", $h->a ({ href=>url ()."?ignoreCookie=1" }, "[Reset Your View]"),
638
          $h->br,
639
          $h->a ({ href=>"", target=>"_new", onClick=>"window.document.Req.excel.value=1; window.document.Req.submit(); window.document.Req.excel.value=0; return false;" }, "[Export Displayed Data as an Excel Document.]"),
640
          $h->br,
641
          "This page was displayed on ", currentTime (),
642
          $h->br,
643
          "Please direct questions, problems, and concerns to $SYSTEM_EMAIL",
644
          $displayYearSelect ? $h->br."Displaying: ".$h->select ({ name=>"year", onchange=>"Req.submit();" }, [ @yearoptions ]) : $h->br
645
        ])
646
      ]),
647
      $h->div ({ class=>"spRight" }, [
648
        $h->h5 ([
649
                 "$x of $datacount Record". ($x == 1 ? "" : "s") ." Displayed", $h->br,
650
                 "Sorted by ", $sortby, $h->br,
651
                 "Displaying ", $h->select ({ name=>"limit", onChange=>"page.value = 1; submit();" }, [ map { $pagelimit == $_ ? $h->option ({ selected=>[] }, $_) : $h->option ($_) } @pagelimitoptions ]), " Per Page", $h->br,
652
                 ( $pages > 1 ? ( join " ", map { $_ == $curpage ? "<B>$_</b>" :
653
                                                  $_ eq "<<"     ? $h->a ({ onClick=>qq{Req.page.value=1; Req.submit();} }, "$_") :
654
                                                  $_ eq ">>"     ? $h->a ({ onClick=>qq{Req.page.value=$pages; Req.submit();} }, "$_") :
655
                                                                   $h->a ({ onClick=>qq{Req.page.value=$_; Req.submit();} }, "[$_]") } @pagerange ) : "" ), $h->br,
656
                 $h->input ({ type=>"hidden", name=>"page", value=>$curpage })
657
        ])
658
      ]),
659
  ]);
660
 
661
  print $h->close('form');
662
  print $h->close('body');
663
  print $h->close('html');
664
}
7 - 665
 
666
# Leave this alone, it's needed to compile correctly
667
return 1;