Subversion Repositories VORC

Rev

Rev 241 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 bgadell 1
#!/usr/bin/perl
2
 
3
# Redirect error messages to a log of my choosing. (it's annoying to filter for errors in the shared env)
4
my $error_log_path = $ENV{SERVER_NAME} eq "volunteers.rollercon.com" ? "/home3/rollerco/logs/" : "/tmp/";
5
close STDERR;
6
open STDERR, '>>', $error_log_path.'vorc_error.log' or warn "Failed to open redirected logfile ($0): $!";
7
#warn "Redirecting errors to ${error_log_path}vorc_error.log";
8
 
9
use strict;
10
use cPanelUserConfig;
11
use WebDB;
12
use HTML::Tiny;
13
use RollerCon;
226 - 14
use CGI qw/param header start_html url url_param/;
56 bgadell 15
my $h = HTML::Tiny->new( mode => 'html' );
16
 
17
my %F;
18
 
19
my $cookie_string = authenticate (1) || die;
20
our ($EML, $PWD, $LVL) = split /&/, $cookie_string;
21
my $user = getUser ($EML);
22
$user->{department} = convertDepartments $user->{department};
23
my $username = $user->{derby_name};
24
my $RCid = $user->{RCid};
25
my $RCAUTH_cookie = CGI::Cookie->new(-name=>'RCAUTH',-value=>"$cookie_string",-expires=>"+30m");
26
my $YEAR = 1900 + (localtime)[5];
27
 
28
 
29
my $pageTitle = "View Game";
30
my $homeURL = "/schedule/";
31
my $DBTable = "game";
32
my %FIELDS = (
33
	id            => [qw(GameID        5     auto        static )],
34
	title         => [qw(Title         10    text         )],
35
	team1         => [qw(Team1         15    text      required )],
36
	team2         => [qw(Team2         20    text      required )],
37
	date          => [qw(Date          25    date        required )],
38
	time          => [qw(Start         30    time        required )],
39
	end_time      => [qw(End           35    time        required )],
40
	track         => [qw(Location      40    text        required )],
41
	level         => [qw(Level         45    text        required )],
42
	restrictions  => [qw(Restrictions  50    select        required )],
43
	type          => [qw(Type          55    select        required )],
44
	notes         => [qw(Notes         60    textarea       )],
45
);
46
 
47
 
48
my %fieldDisplayName = map  { $_ => $FIELDS{$_}->[0]   } keys %FIELDS;
49
my %fieldType        = map  { $_ => $FIELDS{$_}->[2]   } keys %FIELDS;
50
my @requiredFields   = sort fieldOrder grep { defined $FIELDS{$_}->[3] } keys %FIELDS;
51
my @DBFields   = sort fieldOrder grep { $fieldType{$_} =~ /^(text|select|number|switch|date|time|auto)/ } keys %FIELDS;
52
my @ROFields   = sort fieldOrder grep { $fieldType{$_} =~ /^(readonly)/ } keys %FIELDS;
53
my $primary = $DBFields[0];
54
 
55
sub fieldOrder {
56
	$FIELDS{$a}->[1] <=> $FIELDS{$b}->[1];
57
}
58
 
59
sub saveForm {
60
  error ("ERROR: Only SysAdmins can change games.") unless $LVL >= RollerCon::ADMIN;
61
 
62
  my $FTS = shift;
63
 
64
  my $dbh = WebDB::connect ();
65
#  if ($FTS->{$DBFields[0]} eq "NEW") {
66
    $dbh->do (
67
      "REPLACE INTO $DBTable (".
68
      join (", ", @DBFields)
69
      .") VALUES (". join (", ", map { '?' } @DBFields) .")",
70
    	undef,
71
    	map { $FTS->{$_} } @DBFields
72
    );
73
    if (!$FTS->{$primary}) {
74
      ($FTS->{$primary}) = $dbh->selectrow_array ("select max($primary) from $DBTable");
75
    }
76
    logit ($RCid, "$username edited a game (".join (", ", map { $FTS->{$_} } @DBFields).")");
77
 
78
	$dbh->disconnect ();	 # stored into database successfully.
79
	return $FTS->{$primary};
80
}
81
 
82
sub delete_item {
83
  error ("ERROR: Only SysAdmins can delete games.") unless $LVL >= RollerCon::ADMIN;
84
 
85
  my $X = shift;
86
  my $dbh = WebDB::connect ();
87
 
88
  $dbh->do ("delete from $DBTable where $primary = ?", undef, $X->{$primary});
89
 
90
  $dbh->disconnect ();
91
  logit ($RCid, "$username deleted Game ($X->{$primary})");
92
  print "Game Deleted: $X->{$primary}", $h->br;
93
  print &formField ("Cancel", "Back", "POSTSAVE");
94
}
95
 
96
 
97
 
98
print header (),
99
			start_html (-title => $pageTitle, -style => {'src' => "/style.css"} );
100
 
101
print $h->div ({ class => "accent pageheader" }, [
102
  $h->h1 ($pageTitle),
103
  $h->div ({ class=>"sp0" }, [
104
    $h->div ({ class=>"spLeft" }, [
105
    ]),
106
    $h->div ({ class=>"spRight" }, [
107
      $h->input ({ type=>"button", value=>"Home", onClick=>"window.location.href='$homeURL'" }),
108
    ]),
109
  ]),
110
]);
111
 
112
my %GETFORM = map { split /=/ } split /&/, $ENV{QUERY_STRING};
113
my $choice = param ("choice") || $GETFORM{choice} // "";
114
if ($choice eq "Save") {
115
	process_form ();
226 - 116
} elsif (defined (param ($primary)) || $GETFORM{$primary} || url_param ($primary)) {
117
  my $thing = param ($primary) || $GETFORM{$primary}; $thing //= url_param ($primary);
56 bgadell 118
  if ($choice eq "Delete") {
119
    delete_item ({ $primary => $thing });
120
  } else {
121
	  display_form ({ $primary => $thing }, $choice);
122
	}
123
} else {
124
	display_form (); # blank form
125
}
126
 
127
print $h->close ("html");
128
 
129
sub display_form  {
130
  my $R = shift;
131
  my $view = shift // "";
132
	my $actionbutton;
133
 
134
  $view = "View" unless $LVL >= RollerCon::ADMIN;
135
 
136
  if ($view eq "POSTSAVE" and $R->{$primary} eq "NEW") {
137
      print &formField ("Cancel", "Back", "POSTSAVE");
138
      return;
139
  }
140
 
141
  if ($R) {
142
    # we're dealing with an existing thing.  Get the current values out of the DB...
143
    my $dbh = WebDB::connect ();
144
 
145
	  @F{@DBFields} = $dbh->selectrow_array (
146
                     "SELECT ". join (", ", @DBFields) ." FROM $DBTable WHERE $primary = ?",
147
                      undef, $R->{$primary});
148
 
149
	  $dbh->disconnect ();
150
 
151
	  # did we find a record?
152
	  error ("Cannot find a database entry for Game with id: '$R->{$primary}'") unless defined $F{$DBFields[0]};
153
 
154
    # If the DB returns a null value, HTML::Tiny doesn't like it, so make sure nulls are converted to empty strings.
155
    map { $F{$_} = "" unless $F{$_} } @DBFields;
156
 
157
    if ($view eq "Update") {
158
      # We'd like to update that thing, give the user a form...
159
      print $h->p ("Updating Game: $R->{$primary}...");
160
 
161
      foreach (@DBFields) {
162
        $F{$_} = formField ($_, $F{$_});
163
      }
164
 
165
      $actionbutton = formField ("choice", "Save");
166
      $actionbutton .= formField ("Cancel");
167
    } elsif ($view eq "Copy") {
168
      # We'd like to copy that thing, give the user a form...
169
      print $h->p ("Copying Game: $R->{$primary}...");
170
 
171
      foreach (@DBFields) {
172
        $F{$_} = formField ($_, $F{$_});
173
      }
174
#      $F{$DBFields[0]} = "COPY".$h->input ({ type=>"hidden", name=>$DBFields[0], value=> "NEW" });
175
 
176
      $actionbutton = formField ("choice", "Save");
177
      $actionbutton .= formField ("Cancel");
178
    } else {
179
      # We're just looking at it...
180
      print $h->p ("Viewing Game: $R->{$primary}...");
181
      $F{$DBFields[0]} .= $h->input ({ type=>"hidden", name=>$DBFields[0], value=> $F{$DBFields[0]} });
182
 
183
      # Put the time fields into the user's preference
184
      map { $F{$_} = convertTime $F{$_} } grep { $fieldType{$_} eq "time" } keys %FIELDS;
185
 
186
      $actionbutton = formField ("choice", "Update") unless $LVL < RollerCon::ADMIN;
187
      if ($view eq "POSTSAVE" or $choice eq "View") {
188
        $actionbutton .= formField ("Cancel", "Back", "POSTSAVE");
189
      } else {
190
        $actionbutton .= formField ("Cancel", "Back");
191
      }
192
    }
193
  } else {
194
    error ("No Game ID provided.") unless $LVL >= RollerCon::ADMIN;
195
 
196
    print $h->p ("Adding a new Game...");
197
 
198
    foreach (@DBFields) {
199
      $F{$_} = formField ($_);
200
    }
201
#		$F{$DBFields[0]} = "NEW".$h->input ({ type=>"hidden", name=>$DBFields[0], value=> "NEW" });
202
 
203
    $actionbutton = formField ("choice", "Save");
204
    $actionbutton .= formField ("Cancel");
205
  }
206
 
207
 
208
	print $h->open ("form", { action => url (), name=>"Req", method=>"POST" });
209
	print $h->div ({ class=>"sp0" },
210
	  $h->div ({ class=>"rTable" }, [ map ({
211
      $h->div ({ class=>"rTableRow" }, [
212
        $h->div ({ class=>"rTableCell right top", style=>"font-size:unset;" }, "$fieldDisplayName{$_}: "),
213
        $h->div ({ class=>"rTableCell", style=>"font-size:unset;" }, $F{$_})
214
      ])
215
       } sort fieldOrder keys %FIELDS),
216
   ])
217
  );
218
 
219
  print $actionbutton;
220
  print $h->close ("form");
221
 
254 - 222
  if (!findConflict ($RCid, $F{id}, "game")) {
223
    use URI::Escape qw(uri_escape);
224
    my $teams = uri_escape ($F{team1}." vs. ".$F{team2});
225
    my $querystring = "choice=Save&id=NEW&role=$teams&date=$F{date}&location=$F{track}&start_time=$F{time}&end_time=$F{end_time}";
226
    print $h->p ($h->input ({ type=>"button", onClick=>"window.location.href='personal_time.pl?$querystring';", value=>"Block This Game as Personal Time" }));
227
  }
228
 
170 - 229
  print $h->p ($h->input ({ type=>"button", onClick=>"window.location.href='email_users.pl?type=game&ID=$R->{$primary}';", value=>"Email Users" })) unless $LVL < RollerCon::ADMIN;
230
 
56 bgadell 231
  use DateTime;
232
  use DateTime::Duration;
233
  my $now = DateTime->now (time_zone => 'America/Los_Angeles');
234
 	my ($yyyy, $mm, $dd) = split /\-/, $F{date};
235
	my $cutoff = DateTime->new(
236
        year => $yyyy,
237
        month => $mm,
238
        day => $dd,
239
        hour => 5,
240
        minute => 0,
241
        second => 0,
242
        time_zone => 'America/Los_Angeles'
243
  );
244
 
245
 
246
  my $dbh = WebDB::connect ();
247
  if ($F{$primary} !~ /^(NEW|COPY)/) {
248
    print $h->br, $h->br;
249
    print $h->div ({ class=>"index", style=>"max-width:610px" }, [ $h->p ({ class=>"heading" }, [ "Officiating Sign-ups:" ]),
250
      $h->ul ( [ map { $h->li ({ class=>"shaded", style=>"margin:4px;" },
251
  	    $h->div ({ class=>"lisp0" }, [
252
          $h->div ({ class=>"liLeft", style=>"width:40%" }, [ $$_[0], ":&nbsp;&nbsp;" ]),
253
          $h->div ({ class=>"liRight", style=>"width:60%" },
254
            $$_[2] ? ($$_[2] == $RCid and $now < $cutoff) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), "&nbsp;", $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") ]
255
                                                          : ($user->{department}->{OFF} > 1 or $LVL > 4) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), "&nbsp;", $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"), '&nbsp;', $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") ]
256
                                                                                                         : [ "FILLED" ]
257
                   : ($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")
258
                                                                  : ($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")
259
                                                                                                                                                       : ""
260
          )
261
        ])
62 bgadell 262
      ) } @{$dbh->selectall_arrayref ("select name, role, RCid, derby_name from v_shift_officiating where id = ?", undef, $R->{$primary})} ])
56 bgadell 263
    ]);
264
#    print $h->br;
265
    print $h->div ({ class=>"index", style=>"max-width:610px" }, [ $h->p ({ class=>"heading" }, [ "Announcer Sign-ups:" ]),
266
      $h->ul ( [ map { $h->li ({ class=>"shaded", style=>"margin:4px;" },
267
  	    $h->div ({ class=>"lisp0" }, [
268
          $h->div ({ class=>"liLeft", style=>"width:50%" }, [ $$_[0], ":&nbsp;&nbsp;" ]),
269
          $h->div ({ class=>"liRight", style=>"width:50%" },
270
            $$_[2] ? ($$_[2] == $RCid and $now < $cutoff) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), "&nbsp;", $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") ]
271
                                                          : ($user->{department}->{ANN} > 1 or $LVL > 4) ? [ $h->a ({ href=>"view_user.pl?submit=View&RCid=$$_[2]" }, $$_[3]), "&nbsp;", $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"), '&nbsp;', $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") ]
272
                                                                                                         : [ "FILLED" ]
273
                   : ($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")
274
                                                                  : ($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")
275
                                                                                                                                                        : ""
276
          )
277
        ])
241 - 278
      ) } @{$dbh->selectall_arrayref ("select name, role, RCid, derby_name from v_shift_announcer where id = ? and role <> ?", undef, $R->{$primary}, "SPO")} ])
56 bgadell 279
    ]);
280
  }
281
  $dbh->disconnect;
282
 
283
 
284
}
285
 
286
sub process_form  {
287
  error ("ERROR: Only SysAdmins can change games.") unless $LVL >= RollerCon::ADMIN;
288
 
289
  my %FORM;
290
  foreach (keys %FIELDS) {
291
  	if ($fieldType{$_} =~ /^text/ and $_ ne "title") {
292
  		$FORM{$_} = WebDB::trim param ($_) // "";
293
  	} else {
294
	  	$FORM{$_} = param ($_) // "";
295
  	}
296
  }
297
  $FORM{autoapprove} = 0 unless $FORM{autoapprove};
298
 
299
  	 # check for required fields
300
	my @errors = ();
301
	foreach (@requiredFields) {
302
		push @errors, "$fieldDisplayName{$_} is missing." if $FORM{$_} eq "" and $FIELDS{$_}->[3] ne "static";
303
	}
304
 
305
  if (@errors)	 {
306
    print $h->div ({ class=>"error" }, [
307
  	  $h->p ("The following errors occurred:"),
308
  	  $h->ul ($h->li (@errors)),
309
  	  $h->p ("Please click your Browser's Back button to\n"
310
  	  	   . "return to the previous page and correct the problem.")
311
  	]);
312
  	return;
313
  }	 # Form was okay.
314
 
315
  $FORM{$primary} = saveForm (\%FORM);
316
 
317
	print $h->p ({ class=>"success" }, "Game successfully saved.");
318
 
319
  display_form ({ $primary=>$FORM{$primary} }, "POSTSAVE");
320
}
321
 
322
sub error {
323
	my $msg = shift;
324
	print $h->p ({ class=>"error" }, "Error: $msg");
325
  print $h->close("html");
326
	exit (0);
327
}
328
 
329
sub formField {
330
	my $name  = shift;
331
	my $value = shift // '';
332
	my $context = shift // '';
333
	my $type = $fieldType{$name} // "button";
334
 
335
  if ($type eq "button") {
336
		if ($name eq "Cancel") {
337
		  if ($context eq "POSTSAVE") {
338
		    return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"window.location.href = \"games.pl\"; return false;" });
339
		  } else {
340
		    return $h->input ({ type=>"button", value => $value ne '' ? $value : "Cancel" , onClick=>"history.back(); return false;" });
341
		  }
342
		} else {
343
			return $h->input ({ type=>"submit", value => $value, name=>$name })
344
		}
345
 
346
	} elsif ($type eq "textarea") {
347
	  return $h->tag ("textarea", {
348
	    name => $name,
349
	    override => 1,
350
			cols => 30,
351
			rows => 4
352
	  }, $value);
353
 
354
  } elsif ($type eq "select") {
355
    no strict;
356
    return &{"select_".$name} ($value);
357
	}	elsif ($type eq "auto") {
358
	  return $value.$h->input ({ type=>"hidden", name=>$name, value=>$value });
359
  }	elsif ($type eq "time") {
360
	  return $h->input ({
361
	    name => $name,
362
	    type => $type,
363
	    value => $value,
364
	    step => 900,
365
	    required => [],
366
	    override => 1,
367
	    size => 30
368
	  });
369
  }	elsif ($type eq "number") {
370
    return $h->input ({ name=>$name, type=>"number", value=>$value, step=>1 });
371
  }	elsif ($type eq "switch") {
372
    if ($value) {
373
      return $h->label ({ class=>"switch" }, [$h->input ({ type=>"checkbox", name=>$name, value=>1, checked=>[] }), $h->span ({ class=>"slider round" })]);
374
    } else {
375
      return $h->label ({ class=>"switch" }, [$h->input ({ type=>"checkbox", name=>$name, value=>1 }), $h->span ({ class=>"slider round" })]);
376
    }
377
	}	else {
378
	  use tableViewer;
379
	  if (inArray ($name, \@requiredFields)) {
380
  	  return $h->input ({
381
  	    name => $name,
382
  	    type => $type,
383
  	    value => $value,
384
  	    required => [],
385
  	    override => 1,
386
  	    size => 30
387
  	  });
388
	  } else {
389
  	  return $h->input ({
390
  	    name => $name,
391
  	    type => $type,
392
  	    value => $value,
393
  	    override => 1,
394
  	    size => 30
395
  	  });
396
  	}
397
	}
398
}
399
 
400
sub select_restrictions {
401
  my $selection = shift // "";
402
  my @options = ("");
403
 
404
  my $sub_name = (caller(0))[3];
405
  $sub_name =~ s/^main::select_//;
406
 
407
  my $dbh = WebDB::connect ();
62 bgadell 408
 	push @options, map { @{$_} } @{$dbh->selectall_arrayref ("select distinct restrictions from game where restrictions <> '' order by restrictions")};
56 bgadell 409
 	$dbh->disconnect ();
410
 
411
  return $h->select ({ name=>$sub_name }, [ map { $_ eq $selection ? $h->option ({selected=>[]}, $_) : $h->option ($_) } @options ]);
412
}
413
 
414
sub select_type {
415
  my $selection = shift // "";
416
  my @options = ("");
417
 
418
  my $sub_name = (caller(0))[3];
419
  $sub_name =~ s/^main::select_//;
420
 
421
  my $dbh = WebDB::connect ();
73 bgadell 422
 	push @options, map { @{$_} } @{$dbh->selectall_arrayref ("select distinct type from staff_template order by type")};
56 bgadell 423
 	$dbh->disconnect ();
424
 
425
  return $h->select ({ name=>$sub_name }, [ map { $_ eq $selection ? $h->option ({selected=>[]}, $_) : $h->option ($_) } @options ]);
426
}