Rev 73 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/usr/bin/perl# Redirect error messages to a log of my choosing. (it's annoying to filter for errors in the shared env)my $error_log_path = $ENV{SERVER_NAME} eq "volunteers.rollercon.com" ? "/home3/rollerco/logs/" : "/tmp/";close STDERR;open STDERR, '>>', $error_log_path.'vorc_error.log' or warn "Failed to open redirected logfile ($0): $!";#warn "Redirecting errors to ${error_log_path}vorc_error.log";use strict;use cPanelUserConfig;use WebDB;use HTML::Tiny;use RollerCon;use CGI qw/param header start_html url/;my $h = HTML::Tiny->new( mode => 'html' );my %F;my $cookie_string = authenticate (1) || die;our ($EML, $PWD, $LVL) = split /&/, $cookie_string;my $user = getUser ($EML);$user->{department} = convertDepartments $user->{department};my $username = $user->{derby_name};my $RCid = $user->{RCid};my $RCAUTH_cookie = CGI::Cookie->new(-name=>'RCAUTH',-value=>"$cookie_string",-expires=>"+30m");my $YEAR = 1900 + (localtime)[5];my $pageTitle = "View Game";my $homeURL = "/schedule/";my $DBTable = "game";my %FIELDS = (id => [qw(GameID 5 auto static )],title => [qw(Title 10 text )],team1 => [qw(Team1 15 text required )],team2 => [qw(Team2 20 text required )],date => [qw(Date 25 date required )],time => [qw(Start 30 time required )],end_time => [qw(End 35 time required )],track => [qw(Location 40 text required )],level => [qw(Level 45 text required )],restrictions => [qw(Restrictions 50 select required )],type => [qw(Type 55 select required )],notes => [qw(Notes 60 textarea )],);my %fieldDisplayName = map { $_ => $FIELDS{$_}->[0] } keys %FIELDS;my %fieldType = map { $_ => $FIELDS{$_}->[2] } keys %FIELDS;my @requiredFields = sort fieldOrder grep { defined $FIELDS{$_}->[3] } keys %FIELDS;my @DBFields = sort fieldOrder grep { $fieldType{$_} =~ /^(text|select|number|switch|date|time|auto)/ } keys %FIELDS;my @ROFields = sort fieldOrder grep { $fieldType{$_} =~ /^(readonly)/ } keys %FIELDS;my $primary = $DBFields[0];sub fieldOrder {$FIELDS{$a}->[1] <=> $FIELDS{$b}->[1];}sub saveForm {error ("ERROR: Only SysAdmins can change games.") unless $LVL >= RollerCon::ADMIN;my $FTS = shift;my $dbh = WebDB::connect ();# if ($FTS->{$DBFields[0]} eq "NEW") {$dbh->do ("REPLACE INTO $DBTable (".join (", ", @DBFields).") VALUES (". join (", ", map { '?' } @DBFields) .")",undef,map { $FTS->{$_} } @DBFields);if (!$FTS->{$primary}) {($FTS->{$primary}) = $dbh->selectrow_array ("select max($primary) from $DBTable");}logit ($RCid, "$username edited a game (".join (", ", map { $FTS->{$_} } @DBFields).")");$dbh->disconnect (); # stored into database successfully.return $FTS->{$primary};}sub delete_item {error ("ERROR: Only SysAdmins can delete games.") unless $LVL >= RollerCon::ADMIN;my $X = shift;my $dbh = WebDB::connect ();$dbh->do ("delete from $DBTable where $primary = ?", undef, $X->{$primary});$dbh->disconnect ();logit ($RCid, "$username deleted Game ($X->{$primary})");print "Game Deleted: $X->{$primary}", $h->br;print &formField ("Cancel", "Back", "POSTSAVE");}print header (),start_html (-title => $pageTitle, -style => {'src' => "/style.css"} );print $h->div ({ class => "accent pageheader" }, [$h->h1 ($pageTitle),$h->div ({ class=>"sp0" }, [$h->div ({ class=>"spLeft" }, []),$h->div ({ class=>"spRight" }, [$h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),]),]),]);my %GETFORM = map { split /=/ } split /&/, $ENV{QUERY_STRING};my $choice = param ("choice") || $GETFORM{choice} // "";if ($choice eq "Save") {process_form ();} elsif (defined (param ($primary)) || $GETFORM{$primary}) {my $thing = param ($primary) || $GETFORM{$primary};if ($choice eq "Delete") {delete_item ({ $primary => $thing });} else {display_form ({ $primary => $thing }, $choice);}} else {display_form (); # blank form}print $h->close ("html");sub display_form {my $R = shift;my $view = shift // "";my $actionbutton;$view = "View" unless $LVL >= RollerCon::ADMIN;if ($view eq "POSTSAVE" and $R->{$primary} eq "NEW") {print &formField ("Cancel", "Back", "POSTSAVE");return;}if ($R) {# we're dealing with an existing thing. Get the current values out of the DB...my $dbh = WebDB::connect ();@F{@DBFields} = $dbh->selectrow_array ("SELECT ". join (", ", @DBFields) ." FROM $DBTable WHERE $primary = ?",undef, $R->{$primary});$dbh->disconnect ();# did we find a record?error ("Cannot find a database entry for Game with id: '$R->{$primary}'") unless defined $F{$DBFields[0]};# If the DB returns a null value, HTML::Tiny doesn't like it, so make sure nulls are converted to empty strings.map { $F{$_} = "" unless $F{$_} } @DBFields;if ($view eq "Update") {# We'd like to update that thing, give the user a form...print $h->p ("Updating Game: $R->{$primary}...");foreach (@DBFields) {$F{$_} = formField ($_, $F{$_});}$actionbutton = formField ("choice", "Save");$actionbutton .= formField ("Cancel");} elsif ($view eq "Copy") {# We'd like to copy that thing, give the user a form...print $h->p ("Copying Game: $R->{$primary}...");foreach (@DBFields) {$F{$_} = formField ($_, $F{$_});}# $F{$DBFields[0]} = "COPY".$h->input ({ type=>"hidden", name=>$DBFields[0], value=> "NEW" });$actionbutton = formField ("choice", "Save");$actionbutton .= formField ("Cancel");} else {# We're just looking at it...print $h->p ("Viewing Game: $R->{$primary}...");$F{$DBFields[0]} .= $h->input ({ type=>"hidden", name=>$DBFields[0], value=> $F{$DBFields[0]} });# Put the time fields into the user's preferencemap { $F{$_} = convertTime $F{$_} } grep { $fieldType{$_} eq "time" } keys %FIELDS;$actionbutton = formField ("choice", "Update") unless $LVL < RollerCon::ADMIN;if ($view eq "POSTSAVE" or $choice eq "View") {$actionbutton .= formField ("Cancel", "Back", "POSTSAVE");} else {$actionbutton .= formField ("Cancel", "Back");}}} else {error ("No Game ID provided.") unless $LVL >= RollerCon::ADMIN;print $h->p ("Adding a new Game...");foreach (@DBFields) {$F{$_} = formField ($_);}# $F{$DBFields[0]} = "NEW".$h->input ({ type=>"hidden", name=>$DBFields[0], value=> "NEW" });$actionbutton = formField ("choice", "Save");$actionbutton .= formField ("Cancel");}print $h->open ("form", { action => url (), name=>"Req", method=>"POST" });print $h->div ({ class=>"sp0" },$h->div ({ class=>"rTable" }, [ map ({$h->div ({ class=>"rTableRow" }, [$h->div ({ class=>"rTableCell right top", style=>"font-size:unset;" }, "$fieldDisplayName{$_}: "),$h->div ({ class=>"rTableCell", style=>"font-size:unset;" }, $F{$_})])} sort fieldOrder keys %FIELDS),]));print $actionbutton;print $h->close ("form");use DateTime;use DateTime::Duration;my $now = DateTime->now (time_zone => 'America/Los_Angeles');my ($yyyy, $mm, $dd) = split /\-/, $F{date};my $cutoff = DateTime->new(year => $yyyy,month => $mm,day => $dd,hour => 5,minute => 0,second => 0,time_zone => 'America/Los_Angeles');my $dbh = WebDB::connect ();if ($F{$primary} !~ /^(NEW|COPY)/) {print $h->br, $h->br;print $h->div ({ class=>"index", style=>"max-width:610px" }, [ $h->p ({ class=>"heading" }, [ "Officiating Sign-ups:" ]),$h->ul ( [ map { $h->li ({ class=>"shaded", style=>"margin:4px;" },$h->div ({ class=>"lisp0" }, [$h->div ({ class=>"liLeft", style=>"width:40%" }, [ $$_[0], ": " ]),$h->div ({ class=>"liRight", style=>"width:60%" },$$_[2] ? ($$_[2] == $RCid and $now < $cutoff) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), " ", $h->button ({ onClick=>"if (confirm('Really? Delete $$_[3] from this game?')==true) { window.open('make_shift_change.pl?change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP") ]: ($user->{department}->{OFF} > 1 or $LVL > 4) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), " ", $h->button ({ onClick=>"if (confirm('Really? Delete $$_[3] from this game?')==true) { window.open('make_shift_change.pl?change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP"), ' ', $h->button ({ onClick=>"if (confirm('Really? $$_[3] was a no show?')==true) { window.open('make_shift_change.pl?noshow=true&change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "NO SHOW") ]: [ "FILLED" ]: ($user->{department}->{OFF} > 1 or $LVL > 4) ? $h->button ({ onClick=>"window.open('make_shift_change.pl?change=lookup&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "ADD USER"): ($user->{department}->{OFF} > 0 and signUpEligible ($user, $R) and $now < $cutoff) ? $h->button ({ onClick=>"window.open('make_shift_change.pl?change=add&RCid=$RCid&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "SIGN UP"): "")])) } @{$dbh->selectall_arrayref ("select name, role, RCid, derby_name from v_shift_officiating where id = ?", undef, $R->{$primary})} ])]);# print $h->br;print $h->div ({ class=>"index", style=>"max-width:610px" }, [ $h->p ({ class=>"heading" }, [ "Announcer Sign-ups:" ]),$h->ul ( [ map { $h->li ({ class=>"shaded", style=>"margin:4px;" },$h->div ({ class=>"lisp0" }, [$h->div ({ class=>"liLeft", style=>"width:50%" }, [ $$_[0], ": " ]),$h->div ({ class=>"liRight", style=>"width:50%" },$$_[2] ? ($$_[2] == $RCid and $now < $cutoff) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), " ", $h->button ({ onClick=>"if (confirm('Really? Delete $$_[3] from this game?')==true) { window.open('make_shift_change.pl?change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP") ]: ($user->{department}->{ANN} > 1 or $LVL > 4) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), " ", $h->button ({ onClick=>"if (confirm('Really? Delete $$_[3] from this game?')==true) { window.open('make_shift_change.pl?change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "DROP"), ' ', $h->button ({ onClick=>"if (confirm('Really? $$_[3] was a no show?')==true) { window.open('make_shift_change.pl?noshow=true&change=del&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false; }" }, "NO SHOW") ]: [ "FILLED" ]: ($user->{department}->{ANN} > 1 or $LVL > 4) ? $h->button ({ onClick=>"window.open('make_shift_change.pl?change=lookup&RCid=$$_[2]&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "ADD USER"): ($user->{department}->{ANN} > 0 and signUpEligible ($user, $R) and $now < $cutoff) ? $h->button ({ onClick=>"window.open('make_shift_change.pl?change=add&RCid=$RCid&id=$R->{$primary}&role=$$_[1]','Confirm Shift Change','resizable,height=260,width=370'); return false;" }, "SIGN UP"): "")])) } @{$dbh->selectall_arrayref ("select name, role, RCid, derby_name from v_shift_announcer where id = ?", undef, $R->{$primary})} ])]);}$dbh->disconnect;}sub process_form {error ("ERROR: Only SysAdmins can change games.") unless $LVL >= RollerCon::ADMIN;my %FORM;foreach (keys %FIELDS) {if ($fieldType{$_} =~ /^text/ and $_ ne "title") {$FORM{$_} = WebDB::trim param ($_) // "";} else {$FORM{$_} = param ($_) // "";}}$FORM{autoapprove} = 0 unless $FORM{autoapprove};# check for required fieldsmy @errors = ();foreach (@requiredFields) {push @errors, "$fieldDisplayName{$_} is missing." if $FORM{$_} eq "" and $FIELDS{$_}->[3] ne "static";}if (@errors) {print $h->div ({ class=>"error" }, [$h->p ("The following errors occurred:"),$h->ul ($h->li (@errors)),$h->p ("Please click your Browser's Back button to\n". "return to the previous page and correct the problem.")]);return;} # Form was okay.$FORM{$primary} = saveForm (\%FORM);print $h->p ({ class=>"success" }, "Game successfully saved.");display_form ({ $primary=>$FORM{$primary} }, "POSTSAVE");}sub error {my $msg = shift;print $h->p ({ class=>"error" }, "Error: $msg");print $h->close("html");exit (0);}sub formField {my $name = shift;my $value = shift // '';my $context = shift // '';my $type = $fieldType{$name} // "button";if ($type eq "button") {if ($name eq "Cancel") {if ($context eq "POSTSAVE") {return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"window.location.href = \"games.pl\"; return false;" });} else {return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"history.back(); return false;" });}} else {return $h->input ({ type=>"submit", value => $value, name=>$name })}} elsif ($type eq "textarea") {return $h->tag ("textarea", {name => $name,override => 1,cols => 30,rows => 4}, $value);} elsif ($type eq "select") {no strict;return &{"select_".$name} ($value);} elsif ($type eq "auto") {return $value.$h->input ({ type=>"hidden", name=>$name, value=>$value });} elsif ($type eq "time") {return $h->input ({name => $name,type => $type,value => $value,step => 900,required => [],override => 1,size => 30});} elsif ($type eq "number") {return $h->input ({ name=>$name, type=>"number", value=>$value, step=>1 });} elsif ($type eq "switch") {if ($value) {return $h->label ({ class=>"switch" }, [$h->input ({ type=>"checkbox", name=>$name, value=>1, checked=>[] }), $h->span ({ class=>"slider round" })]);} else {return $h->label ({ class=>"switch" }, [$h->input ({ type=>"checkbox", name=>$name, value=>1 }), $h->span ({ class=>"slider round" })]);}} else {use tableViewer;if (inArray ($name, \@requiredFields)) {return $h->input ({name => $name,type => $type,value => $value,required => [],override => 1,size => 30});} else {return $h->input ({name => $name,type => $type,value => $value,override => 1,size => 30});}}}sub select_restrictions {my $selection = shift // "";my @options = ("");my $sub_name = (caller(0))[3];$sub_name =~ s/^main::select_//;my $dbh = WebDB::connect ();push @options, map { @{$_} } @{$dbh->selectall_arrayref ("select distinct restrictions from game where restrictions <> '' order by restrictions")};$dbh->disconnect ();return $h->select ({ name=>$sub_name }, [ map { $_ eq $selection ? $h->option ({selected=>[]}, $_) : $h->option ($_) } @options ]);}sub select_type {my $selection = shift // "";my @options = ("");my $sub_name = (caller(0))[3];$sub_name =~ s/^main::select_//;my $dbh = WebDB::connect ();push @options, map { @{$_} } @{$dbh->selectall_arrayref ("select distinct type from staff_template order by type")};$dbh->disconnect ();return $h->select ({ name=>$sub_name }, [ map { $_ eq $selection ? $h->option ({selected=>[]}, $_) : $h->option ($_) } @options ]);}