Subversion Repositories VORC

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
35 - 1
#!/usr/bin/perl
2
 
3
#if ($ENV{SHELL}) { die "This script shouldn't be executed from the command line!\n"; }
4
 
5
#use strict;
6
use cPanelUserConfig;
7
use CGI qw/param cookie header start_html url/;
8
use HTML::Tiny;
9
use tableViewer;
10
use RollerCon;
43 - 11
use DateTime;
12
#use DateTime::Duration;
13
my $now = DateTime->now (time_zone => 'America/Los_Angeles');
35 - 14
our $h = HTML::Tiny->new( mode => 'html' );
15
 
16
my $cookie_string;
17
our ($EML, $PWD, $LVL);
18
my $user;
19
my $username;
20
my $RCid;
21
my $RCAUTH_cookie;
50 bgadell 22
#my $YEAR = "2023";
35 - 23
 
24
$cookie_string = authenticate(1) || die;
25
($EML, $PWD, $LVL) = split /&/, $cookie_string;
26
$user = getUser($EML);
27
$username = $h->a ({ href=>"/schedule/manage_user.pl?submit=View&RCid=$user->{RCid}" }, $user->{derby_name});
28
$RCid = $user->{RCid};
29
$RCAUTH_cookie = CGI::Cookie->new(-name=>'RCAUTH',-value=>"$cookie_string",-expires=>"+30m");
30
 
31
if (convertDepartments($user->{department})->{CLA} < 1 and $LVL < 4) {
32
	print header(-cookie=>$RCAUTH_cookie);
33
	printRCHeader("Unauthorized Page");
34
	print $h->div ({ class=>"error" }, "No Access");
35
	print $h->div ("Your user account is not registered to sign up for MVP Classes, so you can't see this page.  It's possible that your access is still being reviewed.  Please be patient.");
36
	print $h->a ({ href=>"/schedule/" }, "[Go Home]");
37
	print $h->close ("html");
38
	exit;
39
}
40
 
41
 
42
my $pageTitle = "MVP Classes";
43
my $prefscookie = "newmvpclasses";
44
our $DBTABLE = 'v_mvp_class';
45
my %COLUMNS = (
46
# colname   =>  [qw(DisplayName       N    type     status)],   status ->  static | default | <blank>
47
	note				=> [qw(Class         5    text     static )],
48
	date				=> [qw(Date         10    date              )],
49
	dayofweek		=> [qw(Day          15    select    default )],
50
	start_time	=> [qw(StartTime    20    text      )],
51
	end_time		=> [qw(EndTime      25    text       )],
52
	time				=> [qw(Time         30    text      default )],
53
	location		=> [qw(Track        35    select    default )],
54
	role				=> [qw(Coach        40    select    default )],
55
	available		=> [qw(SignUp       45    text      static )]
56
);
57
my $stylesheet = "/style.css";
58
my $homeURL = '/schedule/';
59
my @pagelimitoptions = ("All", 5, 10, 25);
60
 
61
# Set any custom "where" DB filters here...
62
my @whereClause;
63
 
64
# If we need to modify line item values, create a subroutine named "modify_$columnname"
65
#    It will receive a hashref to the object lineitem
66
 
67
#use WebDB;
68
#my $dbh = WebDB::connect;
69
my $dbh = getRCDBH;
70
 
71
sub modify_available {
72
	my $t = shift;
43 - 73
 
74
 	my ($yyyy, $mm, $dd) = split /\-/, $t->{date};
75
	my $cutoff = DateTime->new(
76
        year => $yyyy,
77
        month => $mm,
78
        day => $dd,
79
        hour => 5,
80
        minute => 0,
81
        second => 0,
82
        time_zone => 'America/Los_Angeles'
83
  );
84
 
85
  return "CLOSED" unless $now < $cutoff;
86
 
35 - 87
	($t->{signedup}) = $dbh->selectrow_array ("select id from v_shift where RCid = ? and date = ? and start_time = ? and location = ?", undef, $RCid, $t->{date}, $t->{start_time}, $t->{location} );
88
	my $droplink = $h->a ({ onClick=>"if (confirm('Really? You want to drop this shift?')==true) { window.open('make_shift_change.pl?change=del&RCid=$RCid&id=$t->{signedup}','Confirm Change','resizable,height=260,width=370'); return false; }" }, "[DROP]");
89
	if (!$t->{available}) {
90
	  my $full = "FULL";
91
	  $full .= " | ".$droplink unless !$t->{signedup};
92
	  return $full;
93
  }
94
 
95
	my $classkey = join '|', $t->{date}, $t->{start_time}, $t->{location};
96
	$t->{available} .= " Open";
97
  $t->{available} .= " | ".$droplink unless !$t->{signedup};
98
	if (signUpEligible ($ORCUSER, $t, "class")) {
99
		# SIGN UP
100
		$t->{available} .= " | ".$h->a ({ onClick=>"window.open('make_shift_change.pl?change=add&RCid=$RCid&id=$classkey','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "[SIGN UP]");
101
	}
102
	if ($user->{department}->{CLA} >= 2 or $LVL > 4 or $user->{department}->{VCI} >= 2) {
103
		# ADD USER
104
		$t->{available} ? $t->{available} .= " | " : {};
105
		$t->{available} .= $h->a ({ onClick=>"window.open('make_shift_change.pl?change=lookup&RCid=$RCid&id=$classkey','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "[ADD USER]");
106
	}
107
 
108
	return $t->{available};
109
}
110
 
111
sub filter_available {
112
  my $colName = shift;
113
	my $filter = shift;
114
 
115
	if (defined $filter)	{
116
		if ($filter eq "Full") {
117
			return "$colName = 0";
118
		}
119
		return "$colName > 0";
120
	}	else {
121
		my $thing = "filter-${colName}";
122
		my $Options = "<OPTION></OPTION>"."<OPTION>Available</OPTION>"."<OPTION>Full</OPTION>";
123
 
124
		$Options =~ s/>($FORM{$thing})/ selected>$1/;
125
		return "<SELECT name=filter-${colName} $onChange>$Options</SELECT>";
126
	}
127
}
128
 
50 bgadell 129
sub modify_time {
130
  my $t = shift;
131
  return convertTime $t->{time};
132
}
133
 
134
 
35 - 135
# Ideally, nothing below this comment needs to change
136
#-------------------------------------------------------------------------------
137
 
138
 
139
our %NAME              = map  { $_ => $COLUMNS{$_}->[0] } keys %COLUMNS;
140
our %colOrderHash      = map  { $_ => $COLUMNS{$_}->[1] } keys %COLUMNS;
141
our %colFilterTypeHash = map  { $_ => $COLUMNS{$_}->[2] } keys %COLUMNS;
142
our @staticFields      = sort byfield grep { $COLUMNS{$_}->[3] eq 'static' } keys %COLUMNS;
143
our @defaultFields     = sort byfield grep { defined $COLUMNS{$_}->[3] } keys %COLUMNS;
144
#our @defaultFields     = grep { $COLUMNS{$_}->[3] eq 'default' or inArray ($_, \@staticFields) } keys %COLUMNS;
145
 
146
our @allFields = sort byfield keys %NAME;
147
our @displayFields = ();
148
our @hideFields = ();
149
my $QUERY_STRING;
150
 
151
my $pagelimit = param ("limit") // "All"; #$pagelimitoptions[$#pagelimitoptions];
152
my $curpage = param ("page") // 1;
153
 
154
our %FORM;
155
my $FILTER;
156
foreach (param()) {
157
# 	if (/^year$/) { #
158
#		$YEAR = param($_);
159
#		next;
160
#	}
161
 
162
	$FORM{$_} = param($_);				# Retrieve all of the FORM data submitted
163
 
164
	if ((/^filter/) and ($FORM{$_} ne '')) {	# Build a set of filters to apply
165
		my ($filter,$field) = split /-/, $_;
166
		$FILTER->{$field} = $FORM{$_};
167
	}	elsif ($FORM{$_} eq "true")	{		# Compile list of fields to display
168
	  if ($_ ne "shiftinclude") {
169
		  push @displayFields, $_;
170
		}
171
	}
172
}
173
 
174
#my @yearoptions = ($YEAR);
175
#foreach (@{&getYears()}) {
176
#	push @yearoptions, $YEAR eq $_ ? $h->option ({ selected=>[] }, $_) : $h->option ($_);
177
#}
178
 
179
 
180
if (exists $FORM{autoload})	{			# If the FORM was submitted (i.e. the page is being redisplayed),
181
							                    #  	build the data for the cookie that remembers the page setup
182
	my $disFields = join ":", @displayFields;
183
	my $fils = join ":", map { "$_=$FILTER->{$_}" } keys %{$FILTER};
184
 
185
	$QUERY_STRING = $disFields.'&'.$fils.'&'.$FORM{sortby}.'&'.$FORM{autoload}.'&'.$FORM{shiftinclude};
186
}
187
 
188
 
189
if (!(exists $FORM{autoload}))	{			# No FORM was submitted...
190
	if (my $prefs = cookie ($prefscookie) and !defined param ("ignoreCookie"))	{ # Check for cookies from previous visits.
191
		my ($disF, $filts, $sb, $al, $si) = split /&/,$prefs;
192
		@displayFields = split /:/,$disF;
193
 
194
		foreach my $pair (split /:/, $filts)	{
195
			my ($key, $value) = split /=/, $pair;
196
			$FORM{"filter-$key"} = $value;
197
			$FILTER->{$key} = $value;
198
		}
199
 
200
		$FORM{sortby} = $sb;
201
		$FORM{autoload} = $al;
202
		$FORM{shiftinclude} = $si;
203
		$QUERY_STRING = $prefs;
204
	}	else {
205
	  @displayFields = @defaultFields; # Otherwise suppply a default list of columns.
206
	  $FORM{autoload} = 1;             # And turn aut0load on by default.
207
		$FORM{sortby} = "note";
208
	}
209
}
210
 
211
# let's just make sure the columns are in the right order (and there aren't any missing)
212
@displayFields = sort byfield uniq @displayFields, @staticFields;
213
 
214
# If the field isn't in the displayFields list,	then add it to the hideFields list
215
@hideFields = grep { notInArray ($_, \@displayFields) } @allFields;
216
 
217
# Process any filters provided in the form to pass to the database
218
push @whereClause, map { filter ($_, $FILTER->{$_}) } grep { defined $FILTER->{$_} } @displayFields;
219
#push @whereClause, "year(date) = '$YEAR'";
220
#warn join " and ", @whereClause;
221
 
222
							#  Given the fields to display and the where conditions,
223
							#	  "getData" will return a reference to an array of
224
							#	  hash references of the results.
225
my ($data, $datacount) = getData (\@displayFields, \@whereClause, $DBTABLE, $FORM{sortby}, $curpage, $pagelimit);
226
my @ProductList = @{ $data };
227
 
228
#my @ProductList = @{ getData (\@displayFields, \@whereClause, $DBTABLE, $FORM{sortby}, $curpage, $pagelimit) };
229
my $x = scalar @ProductList; # How many results were returned?
230
 
231
# If the user is trying to download the Excel file, send it to them and then exit out.
232
if ($FORM{excel}) {
233
  exportExcel (\@ProductList, "MVP_Class_List");
234
  exit;
235
}
236
 
237
my @shifts;
238
if ($FORM{shiftinclude} eq "true") {
239
  my @SIWhere; # = ("year(date) = '$YEAR'");
240
  push @SIWhere, "RCid = $ORCUSER->{RCid}", "dept='CLA'";
241
  my ($d, $c) = getData (\@displayFields, \@SIWhere, 'v_shift', $FORM{sortby});
242
  @shifts = @{ $d };
243
}
244
 
245
my $signedOnAs = $username ? "Welcome, $username. ".$h->a ({ href=>"index.pl", onClick=>"document.cookie = 'RCAUTH=; expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/';return true;" }, "[Log Out]") : "You are not signed in.";
246
 
247
# Set some cookie stuff...
248
my $path = `dirname $ENV{REQUEST_URI}`; chomp $path; $path .= '/' unless $path eq "/";
249
my $queryCookie = cookie(-NAME=>$prefscookie,
250
			-VALUE=>"$QUERY_STRING",
251
			-PATH=>"$path",
252
			-EXPIRES=>'+365d');
253
 
254
my $SIChecked;
255
if ($FORM{shiftinclude}) {
256
  $SIChecked = $h->input ({ type=>"checkbox", name=>"shiftinclude", value=>"true", checked=>[], onClick=>'submit();' });
257
} else {
258
  $SIChecked = $h->input ({ type=>"checkbox", name=>"shiftinclude", value=>"true", onClick=>'submit();' });
259
}
260
 
261
# Print the header
262
print header(-cookie=>[$RCAUTH_cookie,$queryCookie]);
263
 
264
# 	print "<!-- FORM \n\n";				# Debug code to dump the FORM to a html comment
265
#	print "I'm catching updates!!!\n\n";
266
#	foreach $key (sort (keys %FORM))		#	Must be done after the header is written!
267
# 		{ print "\t$key:  $FORM{$key}\n"; }
268
# 	print "--> \n\n";
269
#
270
#
271
# 	print "<!-- ENV \n\n";				# Debug code to dump the ENV to a html comment
272
# 	foreach $key (sort (keys %ENV))			#	Must be done after the header is written!
273
# 		{ print "\t$key:  $ENV{$key}\n"; }
274
# 	print "--> \n\n";
275
#
276
# 	print "\n\n\n\n<!-- $QUERY_STRING --> \n\n\n\n";
277
 
278
 
279
#------------------
280
 
281
# Toggle the autoload fields within the table elements
282
our ($onClick, $onChange);   # (also used in scanFunctions)
283
my ($radiobutton, $refreshbutton, $sortby);
284
if ($FORM{autoload}) {
285
	$onClick = "onClick='submit();'";
286
	$onChange = "onChange='page.value = 1; submit();'";
287
  $radiobutton = $h->div ({ class=>'autoload' },
288
    ["Autoload Changes: ",
289
    $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>1, onClick=>'submit();', checked=>[] }), "On ",
290
    $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>0, onClick=>'submit();' }), "Off ",
291
    ]);
292
  $sortby = $h->select ({name=>"sortby", onChange=>'submit();' }, [ map { $FORM{sortby} eq $_ ? $h->option ({ value=>$_, selected=>[] }, $NAME{$_}) : $h->option ({ value=>$_ }, $NAME{$_}) } @displayFields ]);
293
} else {
294
  $onClick = "";
295
	$onChange = "onChange='page.value = 1;'";
296
  $radiobutton = $h->div ({ class=>'autoload' },
297
    ["Autoload Changes: ",
298
    $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>1, onClick=>'submit();' }), "On ",
299
    $h->input ({ type=>"radio", name=>'autoload', class=>'accent', value=>0, onClick=>'submit();', checked=>[] }), "Off ",
300
    ]);
301
  $refreshbutton = $h->input ({ type=>"button", value=>"Refresh", onClick=>"submit(); return false;" });
302
  $sortby = $h->select ({name=>"sortby" }, [ map { $FORM{sortby} eq $_ ? $h->option ({ value=>$_, selected=>[] }, $NAME{$_}) : $h->option ({ value=>$_ }, $NAME{$_}) } @displayFields ]);
303
}
304
 
305
 
306
 
307
 
308
print start_html (-title => $pageTitle, -style => {'src' => $stylesheet} );
309
 
310
print $h->open ('form', { action=>url, method=>'POST', name=>'Req' });
311
print $h->input ({ type=>"hidden", name=>"excel", value=>0 });
312
print $h->div ({ class => "accent pageheader" }, [
313
  $h->h1 ($pageTitle),
314
  $h->div ({ class=>"sp0" }, [
315
    $h->div ({ class=>"spLeft" }, [
316
      $radiobutton
317
    ]),
318
    $h->div ({ class=>"spRight" }, [
319
      $h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),
320
      $refreshbutton
321
    ]),
322
  ]),
323
]);
324
 
325
# Print the Hidden fields' check boxes (if there are any)
326
 
327
my $c = 1;
328
my @hiddencheckboxes;
329
my @hiddenrows;
330
foreach my $field (sort { $NAME{$a} cmp $NAME{$b}; } @hideFields) {
331
  if ($FORM{autoload}) {
332
    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} ]);
333
  } else {
334
    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} ]);
335
  }
336
  if ($c++ % 4 == 0) {
337
    push @hiddenrows, $h->div ({ class=>'rTableRow' }, [ @hiddencheckboxes ]);
338
    @hiddencheckboxes = [];
339
  }
340
}
341
push @hiddenrows, $h->div ({ class=>'rTableRow' }, [ @hiddencheckboxes ]) unless --$c % 4 == 0;
342
 
343
 
344
if (scalar @hideFields) {
345
  my @topleft;
346
  push @topleft, $h->div ({ class=>"nowrap" }, "Hidden Columns:");
347
  push @topleft, $h->div ({ class=>'rTable' }, [ @hiddenrows ]);
348
 
349
  print $h->div ({ class=>"sp0" }, [
350
    $h->div ({ class=>"spLeft"  }, [ @topleft ]),
351
    $h->div ({ class=>"spRight" }, [
352
      $signedOnAs, $h->br,
353
      "Show my classes: ", $SIChecked, $h->br,
354
      $h->input ({ type=>"button", value=>"Block Personal Time", onClick=>"window.location.href='manage_personal_time.pl'" }),
355
    ])
356
  ]);
357
}
358
 
359
# Print the main table...............................................
360
 
361
print $h->open ('div', { class=>'rTable' });
362
 
363
my @tmptitlerow;
364
foreach my $f (@displayFields)	{  # Print the Column headings
365
  if (inArray ($f, \@staticFields)) {
366
    push @tmptitlerow, $h->div ({ class=>'rTableHead' }, [ $h->input ({ type=>"hidden", name=>$f, value=>"true" }), $NAME{$f} ]);
367
  } else {
368
    if ($FORM{autoload}) {
369
      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} ]);
370
    } else {
371
      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} ]);
372
    }
373
  }
374
}
375
 
376
# Print the filter boxes...
377
print $h->div ({ class=>'rTableHeading' }, [ @tmptitlerow ], [ map { $h->div ({ class=>'rTableCell filters' }, filter ($_)) } @displayFields ], $h->div ({ class=>"rTableCell" }));
378
 
379
if ($FORM{shiftinclude}) {  # Include all of the user's shifts at the top
380
  foreach my $t (@shifts)	{
381
	  print $h->div ({ class=>'rTableRow highlighted' }, [ map { $h->div ({ class=>'rTableCell' }, exists &{"modify_".$_} ? &{"modify_".$_} ($t) : $t->{$_}) } @displayFields ]);
382
  }
383
  print $h->hr ({ width=>"500%" });
384
}
385
 
386
# Print the things
387
foreach my $t (@ProductList)	{
388
  my @display = map { $h->div ({ class=>'rTableCell' }, exists &{"modify_".$_} ? &{"modify_".$_} ($t) : $t->{$_}) } @displayFields;
389
  if ($t->{signedup}) {
390
	  print $h->div ({ class=>'rTableRow highlighted' }, [ @display ]);
391
  } else {
392
	  print $h->div ({ class=>'rTableRow shaded' }, [ @display ]);
393
  }
394
}
395
 
396
 
397
 
398
 
399
print $h->close ('div');
400
 
401
# close things out................................................
402
 
403
my $pages = $pagelimit eq "All" ? 1 : int( $datacount / $pagelimit + 0.99 );
404
if ($curpage > $pages) { $curpage = $pages; }
405
 
406
my @pagerange;
407
if ($pages <= 5 ) {
408
  @pagerange = 1 .. $pages;
409
} else {
410
  if ($curpage <= 3) {
411
    @pagerange = (1, 2, 3, 4, ">>");
412
  } elsif ($curpage >= $pages - 2) {
413
    @pagerange = ("<<", $pages-3, $pages-2, $pages-1, $pages);
414
  } else {
415
    @pagerange = ("<<", $curpage-1, $curpage, $curpage+1, ">>");
416
  }
417
}
418
 
419
my @excelcode;
420
push @excelcode, $h->br;
421
push @excelcode, $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.]");
422
 
423
 
424
print $h->br; # print $h->br;
425
print $h->div ({ class=>"sp0" }, [
426
    $h->div ({ class=>"spLeft" }, [
427
      $h->div ({ class=>"footer" }, [
428
        "To bookmark, save, or send this exact view, use the ",
429
        $h->a ({ href=>'', onClick=>"window.document.Req.method = 'GET'; Req.submit(); return false;" }, "[Full URL]"),
430
        $h->br,
431
        "If this page is displaying oddly, ", $h->a ({ href=>url ()."?ignoreCookie=1" }, "[Reset Your View]"),
432
        @excelcode,
433
        $h->br,
434
        "This page was displayed on ", currentTime (),
435
        $h->br,
436
        "Please direct questions, problems, and concerns to Officials.RollerCon.Schedule\@gmail.com",
437
#        $h->br,
438
#        "Displaying: ", $h->select ({ name=>"year", onchange=>"Req.submit();" }, [ @yearoptions ])
439
      ])
440
    ]),
441
    $h->div ({ class=>"spRight" }, [
442
      $h->h5 ([
443
               "$x of $datacount Record". ($x == 1 ? "" : "s") ." Displayed", $h->br,
444
               "Sorted by ", $sortby, $h->br,
445
               "Displaying ", $h->select ({ name=>"limit", onChange=>"page.value = 1; submit();" }, [ map { $pagelimit == $_ ? $h->option ({ selected=>[] }, $_) : $h->option ($_) } @pagelimitoptions ]), " Per Page", $h->br,
446
               ( $pages > 1 ? ( join " ", map { $_ == $curpage ? "<B>$_</b>" :
447
                                                $_ eq "<<"     ? $h->a ({ onClick=>qq{Req.page.value=1; Req.submit();} }, "$_") :
448
                                                $_ eq ">>"     ? $h->a ({ onClick=>qq{Req.page.value=$pages; Req.submit();} }, "$_") :
449
                                                                 $h->a ({ onClick=>qq{Req.page.value=$_; Req.submit();} }, "[$_]") } @pagerange ) : "" ), $h->br,
450
               $h->input ({ type=>"hidden", name=>"page", value=>$curpage })
451
      ])
452
    ]),
453
]);
454
 
455
#print $h->br; # print $h->br;
456
#print $h->h5 ("$x Record(s) Displayed");
457
#print $h->div ({ class=>"footer" }, [
458
#  "To bookmark, save, or send this exact view, use the ",
459
#  $h->a ({ href=>'', onClick=>"window.document.Req.method = 'GET'; Req.submit(); return false;" }, "[Full URL]"),
460
#  $h->br,
461
#  "This page was displayed on $now",
462
#  $h->br,
463
#  "Please direct questions, problems, and concerns to noone\@gmail.com"
464
#]);
465
 
466
 
467
print $h->close('form');
468
print $h->close('html');