| … | |
… | |
| 38 | |
38 | |
| 39 | #FIXME get these values from global course environment (see subroutines as well) |
39 | #FIXME get these values from global course environment (see subroutines as well) |
| 40 | my $default_msg_file = 'default.msg'; |
40 | my $default_msg_file = 'default.msg'; |
| 41 | my $old_default_msg_file = 'old_default.msg'; |
41 | my $old_default_msg_file = 'old_default.msg'; |
| 42 | |
42 | |
|
|
43 | |
| 43 | # store data |
44 | # store data |
| 44 | $self->{defaultFrom} = 'FIXME from'; |
45 | $self->{defaultFrom} = 'FIXME from'; |
| 45 | $self->{defaultReply} = 'FIXME reply'; |
46 | $self->{defaultReply} = 'FIXME reply'; |
| 46 | $self->{rows} = (defined($r->param('rows'))) ? $r->param('rows') : $ce->{mail}->{editor_window_rows}; |
47 | $self->{rows} = (defined($r->param('rows'))) ? $r->param('rows') : $ce->{mail}->{editor_window_rows}; |
| 47 | $self->{columns} = (defined($r->param('columns'))) ? $r->param('columns') : $ce->{mail}->{editor_window_columns}; |
48 | $self->{columns} = (defined($r->param('columns'))) ? $r->param('columns') : $ce->{mail}->{editor_window_columns}; |
| 48 | $self->{default_msg_file} = $default_msg_file; |
49 | $self->{default_msg_file} = $default_msg_file; |
| 49 | $self->{old_default_msg_file} = $old_default_msg_file; |
50 | $self->{old_default_msg_file} = $old_default_msg_file; |
| 50 | $self->{merge_file} = (defined($r->param('merge_file'))) ? $r->param('merge_file') : 'None'; |
51 | $self->{merge_file} = (defined($r->param('merge_file' ))) ? $r->param('merge_file') : 'None'; |
|
|
52 | $self->{preview_user} = (defined($r->param('preview_user'))) ? $r->param('preview_user') : 'Yourself'; |
|
|
53 | |
|
|
54 | |
|
|
55 | ############################################################################################# |
|
|
56 | # gather database data |
|
|
57 | ############################################################################################# |
|
|
58 | # FIXME this might be better done in body? We don't always need all of this data. or do we? |
|
|
59 | my @users = sort $db->listUsers; |
|
|
60 | my @user_records = (); |
|
|
61 | push(@user_records,$db->getUser($_)) foreach (@users); |
|
|
62 | |
|
|
63 | # store data |
|
|
64 | $self->{ra_users} = \@users; |
|
|
65 | $self->{ra_user_records} = \@user_records; |
|
|
66 | |
|
|
67 | ############################################################################################# |
|
|
68 | # gather list of recipients |
|
|
69 | ############################################################################################# |
|
|
70 | my @send_to = (); |
|
|
71 | #FIXME this (radio) is a lousy name |
|
|
72 | my $recipients = $r->param('radio'); |
|
|
73 | if ($recipients eq 'all_students') { #only active students #FIXME status check?? |
|
|
74 | foreach my $ur (@user_records) { |
|
|
75 | push(@send_to,$ur->user_id) if $ur->status eq 'C' and not($ur->user_id =~ /practice/); |
|
|
76 | } |
|
|
77 | } elsif ($recipients eq 'studentID' ) { |
|
|
78 | @send_to = $r->param('classList'); |
|
|
79 | } else { |
|
|
80 | warn "Don't understand recipient list |$recipients|"; |
|
|
81 | } |
|
|
82 | $self->{ra_send_to} = \@send_to; |
| 51 | ################################################################# |
83 | ################################################################# |
| 52 | # Check the validity of the input file name |
84 | # Check the validity of the input file name |
| 53 | ################################################################# |
85 | ################################################################# |
| 54 | my $input_file = ''; |
86 | my $input_file = ''; |
| 55 | #make sure an input message file was submitted and exists |
87 | #make sure an input message file was submitted and exists |
| … | |
… | |
| 71 | "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(), |
103 | "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(), |
| 72 | "Using contents of the default message $default_msg_file instead.", |
104 | "Using contents of the default message $default_msg_file instead.", |
| 73 | ); |
105 | ); |
| 74 | } |
106 | } |
| 75 | } else { |
107 | } else { |
| 76 | $input_file = $default_msg_file; |
108 | $input_file = $default_msg_file; |
| 77 | } |
109 | } |
| 78 | $self->{input_file}=$input_file; |
110 | $self->{input_file} =$input_file; |
| 79 | |
111 | |
| 80 | ################################################################# |
112 | ################################################################# |
| 81 | # Determine the file name to save message into |
113 | # Determine the file name to save message into |
| 82 | ################################################################# |
114 | ################################################################# |
| 83 | my $output_file = 'FIXME no output file specified'; |
115 | my $output_file = 'FIXME no output file specified'; |
| … | |
… | |
| 142 | $self->{replyTo} = $replyTo; |
174 | $self->{replyTo} = $replyTo; |
| 143 | $self->{subject} = $subject; |
175 | $self->{subject} = $subject; |
| 144 | $self->{r_text} = $r_text; |
176 | $self->{r_text} = $r_text; |
| 145 | |
177 | |
| 146 | |
178 | |
|
|
179 | |
|
|
180 | ################################################################################### |
|
|
181 | #Determine the appropriate script action from the buttons |
|
|
182 | ################################################################################### |
|
|
183 | # first time actions |
|
|
184 | # open new file |
|
|
185 | # open default file |
|
|
186 | # choose merge file actions |
|
|
187 | # chose merge button |
|
|
188 | # option actions |
|
|
189 | # 'reset rows' |
|
|
190 | |
|
|
191 | # save actions |
|
|
192 | # "save" button |
|
|
193 | # "save as" button |
|
|
194 | # "save as default" button |
|
|
195 | # preview actions |
|
|
196 | # 'preview' button |
|
|
197 | # email actions |
|
|
198 | # 'entire class' |
|
|
199 | # 'selected studentIDs' |
|
|
200 | # error actions (various) |
|
|
201 | |
|
|
202 | |
| 147 | ############################################################################################# |
203 | ############################################################################################# |
| 148 | # if no form is submitted, gather data needed to produce the mail form and return |
204 | # if no form is submitted, gather data needed to produce the mail form and return |
| 149 | ############################################################################################# |
205 | ############################################################################################# |
| 150 | |
206 | my $to = $r->param('To'); |
|
|
207 | my $script_action = ''; |
|
|
208 | |
|
|
209 | |
| 151 | if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window' |
210 | if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window' |
| 152 | or $action eq 'Choose merge file' ){ |
211 | or $action eq 'Choose merge file' ){ |
| 153 | # warn "FIXME action is |$action| no further initialization required"; |
212 | # warn "FIXME action is |$action| no further initialization required"; |
| 154 | return ''; |
213 | return ''; |
| 155 | } |
214 | } |
| … | |
… | |
| 162 | # If form is submitted deal with filled out forms |
221 | # If form is submitted deal with filled out forms |
| 163 | # and various actions resulting from different buttons |
222 | # and various actions resulting from different buttons |
| 164 | ############################################################################################# |
223 | ############################################################################################# |
| 165 | |
224 | |
| 166 | |
225 | |
| 167 | my $to = $r->param('To'); |
226 | |
| 168 | |
|
|
| 169 | |
|
|
| 170 | |
|
|
| 171 | ################################################################################### |
|
|
| 172 | #Determine the appropriate script action from the buttons |
|
|
| 173 | ################################################################################### |
|
|
| 174 | # save actions |
|
|
| 175 | # "save" button |
|
|
| 176 | # "save as" button |
|
|
| 177 | # "save as default" button |
|
|
| 178 | # preview actions |
|
|
| 179 | # 'preview' button |
|
|
| 180 | # email actions |
|
|
| 181 | # 'entire class' |
|
|
| 182 | # 'selected studentIDs' |
|
|
| 183 | # option actions |
|
|
| 184 | # 'reset rows' |
|
|
| 185 | # error actions (various) |
|
|
| 186 | |
|
|
| 187 | my $script_action = ''; |
|
|
| 188 | # user_errors |
227 | # user_errors |
| 189 | # save |
228 | # save |
| 190 | # save as |
229 | # save as |
| 191 | # save as default |
230 | # save as default |
| 192 | # send mail |
231 | # send mail |
| … | |
… | |
| 228 | # Save the message |
267 | # Save the message |
| 229 | ################################################################# |
268 | ################################################################# |
| 230 | $self->saveProblem($temp_body, "${emailDirectory}/$output_file" ); |
269 | $self->saveProblem($temp_body, "${emailDirectory}/$output_file" ); |
| 231 | $self->{message} .= "Message saved to file <code>${emailDirectory}/$output_file</code>."; |
270 | $self->{message} .= "Message saved to file <code>${emailDirectory}/$output_file</code>."; |
| 232 | # warn "FIXME saving to ${emailDirectory}/$output_file"; |
271 | # warn "FIXME saving to ${emailDirectory}/$output_file"; |
| 233 | } elsif ($action eq 'preview') { |
272 | } elsif ($action eq 'Preview') { |
| 234 | |
273 | $self->{response} = 'preview'; |
| 235 | |
274 | |
| 236 | } elsif ($action eq 'Send Email') { |
275 | } elsif ($action eq 'Send Email') { |
| 237 | |
276 | |
| 238 | |
277 | |
| 239 | |
278 | |
| … | |
… | |
| 243 | } |
282 | } |
| 244 | |
283 | |
| 245 | #if Save button was clicked |
284 | #if Save button was clicked |
| 246 | if (( $r->param('action') eq 'Save') && defined($r->param('body')) && defined($r->param('savefilename'))) { |
285 | if (( $r->param('action') eq 'Save') && defined($r->param('body')) && defined($r->param('savefilename'))) { |
| 247 | |
286 | |
| 248 | # my $temp_body = $body; |
|
|
| 249 | # $temp_body =~ s/\r\n/\n/g; |
|
|
| 250 | # $temp_body = "From: " . $from . "\n" . |
|
|
| 251 | # "Reply-To: " . $replyTo . "\n" . |
|
|
| 252 | # "Subject: " . $subject . "\n" . |
|
|
| 253 | # "Message: \n" . $temp_body; |
|
|
| 254 | # |
|
|
| 255 | # saveProblem($temp_body, $savefilename); |
|
|
| 256 | # $messageFileName = $savefilename; |
|
|
| 257 | |
287 | |
| 258 | #if Save As button was clicked |
288 | #if Save As button was clicked |
| 259 | } elsif (( $r->param('action') eq 'Save as:') && defined($r->param('body')) && defined($r->param('savefilename'))) { |
289 | } elsif (( $r->param('action') eq 'Save as:') && defined($r->param('body')) && defined($r->param('savefilename'))) { |
| 260 | |
290 | |
| 261 | # $messageFileName = $savefilename; |
|
|
| 262 | # |
|
|
| 263 | # if ($messageFileName =~ /^[~.]/ || $messageFileName =~ /\.\./) { |
|
|
| 264 | # $self->submission_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory (you can't use ../blah/blah). Please specify a different file or move the needed file to the email directory"); |
|
|
| 265 | # } |
|
|
| 266 | # |
|
|
| 267 | # |
|
|
| 268 | # my $temp_body = $body; |
|
|
| 269 | # $temp_body =~ s/\r\n/\n/g; |
|
|
| 270 | # $temp_body = join("", |
|
|
| 271 | # "From: $from \nReply-To: $replyTo)\n" , |
|
|
| 272 | # "Subject: $subject\n" , |
|
|
| 273 | # "Message: \n $temp_body"); |
|
|
| 274 | # |
|
|
| 275 | # saveNewProblem($temp_body, $messageFileName); |
|
|
| 276 | |
291 | |
| 277 | #if Save As Default button was clicked |
|
|
| 278 | } elsif (( $r->param('action') eq 'save_as_default') && defined($r->param('body'))) { |
292 | } elsif (( $r->param('action') eq 'save_as_default') && defined($r->param('body'))) { |
| 279 | |
293 | |
| 280 | # my $temp_body; |
|
|
| 281 | # $temp_body = $r->param('body'); |
|
|
| 282 | # $temp_body =~ s/\r\n/\n/g; |
|
|
| 283 | # |
|
|
| 284 | # #get default.msg and back it up in default.old.msg |
|
|
| 285 | # open DEFAULT, "$emailDirectory/$default_msg_file"; |
|
|
| 286 | # $temp_body = <DEFAULT>; |
|
|
| 287 | # close DEFAULT; |
|
|
| 288 | # |
|
|
| 289 | # if ( -e "$emailDirectory/$old_default_msg_file") { |
|
|
| 290 | # # saveProblem($temp_body, $old_default_msg_file); |
|
|
| 291 | # } else { |
|
|
| 292 | # # saveNewProblem($temp_body, $old_default_msg_file); |
|
|
| 293 | # } |
|
|
| 294 | # |
|
|
| 295 | # #save new default message as default.msg |
|
|
| 296 | # $temp_body = $body; |
|
|
| 297 | # $temp_body =~ s/\r\n/\n/g; |
|
|
| 298 | # $temp_body = join("", |
|
|
| 299 | # "From: $from \nReply-To: $replyTo)\n" , |
|
|
| 300 | # "Subject: $subject\n" , |
|
|
| 301 | # "Message: \n $temp_body"); |
|
|
| 302 | # |
|
|
| 303 | # # saveProblem($temp_body, $default_msg_file); |
|
|
| 304 | # $messageFileName = $default_msg_file; |
|
|
| 305 | |
294 | |
| 306 | #if Send Email button was clicked |
|
|
| 307 | } elsif ( $r->param('action') eq 'Send Email' ) { |
295 | } elsif ( $r->param('action') eq 'Send Email' ) { |
| 308 | |
296 | |
| 309 | my @studentID = (); |
297 | my @studentID = (); |
| 310 | |
298 | |
| 311 | if ($r->param('To') eq 'classList' && defined($r->param('classList')) && $r->param('classList') ne 'None') { |
299 | if ($r->param('To') eq 'classList' && defined($r->param('classList')) && $r->param('classList') ne 'None') { |
| … | |
… | |
| 372 | # } |
360 | # } |
| 373 | } else { |
361 | } else { |
| 374 | $self->submission_error('You didn\'t select any recipients. Make sure you select either all student in the course, individual students or a whole classlist.'); |
362 | $self->submission_error('You didn\'t select any recipients. Make sure you select either all student in the course, individual students or a whole classlist.'); |
| 375 | } |
363 | } |
| 376 | |
364 | |
| 377 | my $mergeFile = ''; |
365 | # my $mergeFile = ''; |
| 378 | |
366 | # |
| 379 | #the radio button named 'merge' determines whether to take the selected mergefile |
367 | # #the radio button named 'merge' determines whether to take the selected mergefile |
| 380 | #or one that was typed in. A error message is given if select one and use the other |
368 | # #or one that was typed in. A error message is given if select one and use the other |
| 381 | $mergeFile = $scoringDirectory . $r->param('mergeFiles') |
369 | # $mergeFile = $scoringDirectory . $r->param('mergeFiles') |
| 382 | if ($r->param('merge') eq 'mergeFiles' && defined($r->param('mergeFiles')) && $r->param('mergeFiles') ne 'None'); |
370 | # if ($r->param('merge') eq 'mergeFiles' && defined($r->param('mergeFiles')) && $r->param('mergeFiles') ne 'None'); |
| 383 | |
371 | # |
| 384 | $mergeFile = $templateDirectory . $r->param('mergeFile') |
372 | # $mergeFile = $templateDirectory . $r->param('mergeFile') |
| 385 | if ($r->param('merge') eq 'mergeFile' && defined($r->param('mergeFile')) && $r->param('mergeFile') !~ m|/$|); #does not end in a / |
373 | # if ($r->param('merge') eq 'mergeFile' && defined($r->param('mergeFile')) && $r->param('mergeFile') !~ m|/$|); #does not end in a / |
| 386 | |
374 | # |
| 387 | if ($mergeFile =~ /^[~.]/ || $mergeFile =~ /\.\./) { |
375 | # if ($mergeFile =~ /^[~.]/ || $mergeFile =~ /\.\./) { |
| 388 | $self->submission_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory. Please specify a different file or move the needed file to the email directory"); |
376 | # $self->submission_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory. Please specify a different file or move the needed file to the email directory"); |
| 389 | } |
377 | # } |
| 390 | if ($r->param('body') =~ /(\$COL\[.*?\])/ && !(-e $mergeFile)) { |
378 | # if ($r->param('body') =~ /(\$COL\[.*?\])/ && !(-e $mergeFile)) { |
| 391 | $self->submission_error("In order to use the \$COL[] you must specify a merge file. The file you specified does not exist. Also, make sure you selected the right checkbox."); |
379 | # $self->submission_error("In order to use the \$COL[] you must specify a merge file. The file you specified does not exist. Also, make sure you selected the right checkbox."); |
| 392 | } |
380 | # } |
| 393 | |
381 | # |
| 394 | |
382 | |
| 395 | my %mergeAArray = (); |
383 | my %mergeAArray = (); |
| 396 | # unless ($mergeFile eq '') {%mergeAArray = &delim2aa($mergeFile);} |
384 | # unless ($mergeFile eq '') {%mergeAArray = &delim2aa($mergeFile);} |
| 397 | # |
385 | # |
| 398 | |
386 | |
| … | |
… | |
| 469 | |
457 | |
| 470 | |
458 | |
| 471 | |
459 | |
| 472 | } #end initialize |
460 | } #end initialize |
| 473 | |
461 | |
| 474 | sub fieldEditHTML { |
462 | # sub fieldEditHTML { |
| 475 | my ($self, $fieldName, $value, $properties) = @_; |
463 | # my ($self, $fieldName, $value, $properties) = @_; |
| 476 | my $size = $properties->{size}; |
464 | # my $size = $properties->{size}; |
| 477 | my $type = $properties->{type}; |
465 | # my $type = $properties->{type}; |
| 478 | my $access = $properties->{access}; |
466 | # my $access = $properties->{access}; |
| 479 | my $items = $properties->{items}; |
467 | # my $items = $properties->{items}; |
| 480 | my $synonyms = $properties->{synonyms}; |
468 | # my $synonyms = $properties->{synonyms}; |
| 481 | |
469 | # |
| 482 | |
470 | # |
| 483 | if ($access eq "readonly") { |
471 | # if ($access eq "readonly") { |
| 484 | return $value; |
472 | # return $value; |
| 485 | } |
473 | # } |
| 486 | if ($type eq "number" or $type eq "text") { |
474 | # if ($type eq "number" or $type eq "text") { |
| 487 | return CGI::input({type=>"text", name=>$fieldName, value=>$value, size=>$size}); |
475 | # return CGI::input({type=>"text", name=>$fieldName, value=>$value, size=>$size}); |
| 488 | } |
476 | # } |
| 489 | if ($type eq "enumerable") { |
477 | # if ($type eq "enumerable") { |
| 490 | my $matched = undef; # Whether a synonym match has occurred |
478 | # my $matched = undef; # Whether a synonym match has occurred |
| 491 | |
479 | # |
| 492 | # Process synonyms for enumerable objects |
480 | # # Process synonyms for enumerable objects |
| 493 | foreach my $synonym (keys %$synonyms) { |
481 | # foreach my $synonym (keys %$synonyms) { |
| 494 | if ($synonym ne "*" and $value =~ m/$synonym/) { |
482 | # if ($synonym ne "*" and $value =~ m/$synonym/) { |
| 495 | $value = $synonyms->{$synonym}; |
483 | # $value = $synonyms->{$synonym}; |
| 496 | $matched = 1; |
484 | # $matched = 1; |
| 497 | } |
485 | # } |
| 498 | } |
486 | # } |
| 499 | if (!$matched and exists $synonyms->{"*"}) { |
487 | # if (!$matched and exists $synonyms->{"*"}) { |
| 500 | $value = $synonyms->{"*"}; |
488 | # $value = $synonyms->{"*"}; |
| 501 | } |
489 | # } |
| 502 | return CGI::popup_menu({ |
490 | # return CGI::popup_menu({ |
| 503 | name => $fieldName, |
491 | # name => $fieldName, |
| 504 | values => [keys %$items], |
492 | # values => [keys %$items], |
| 505 | default => $value, |
493 | # default => $value, |
| 506 | labels => $items, |
494 | # labels => $items, |
| 507 | }); |
495 | # }); |
| 508 | } |
496 | # } |
| 509 | } |
497 | # } |
| 510 | |
498 | |
| 511 | sub title { |
499 | sub title { |
| 512 | my $self = shift; |
500 | my $self = shift; |
| 513 | return 'Send mail to ' .$self->{ce}->{courseName}; |
501 | return 'Send mail to ' .$self->{ce}->{courseName}; |
| 514 | } |
502 | } |
| … | |
… | |
| 527 | "Send Mail to: $courseName" => '', |
515 | "Send Mail to: $courseName" => '', |
| 528 | ); |
516 | ); |
| 529 | } |
517 | } |
| 530 | |
518 | |
| 531 | sub body { |
519 | sub body { |
|
|
520 | my ($self, $setID) = @_; |
|
|
521 | my $response = (defined($self->{response}))? $self->{response} : ''; |
|
|
522 | if ($response eq 'preview') { |
|
|
523 | $self->print_preview($setID); |
|
|
524 | } else { |
|
|
525 | $self->print_form($setID); |
|
|
526 | } |
|
|
527 | |
|
|
528 | } |
|
|
529 | sub print_preview { |
|
|
530 | my ($self, $setID) = @_; |
|
|
531 | # get preview user |
|
|
532 | my $ur = $self->{db}->getUser($self->{preview_user}); |
|
|
533 | |
|
|
534 | # get merge file |
|
|
535 | my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; |
|
|
536 | my $delimiter = ','; |
|
|
537 | my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter"); |
|
|
538 | |
|
|
539 | my ($msg, $preview_header) = $self->process_message($ur,$rh_merge_data); |
|
|
540 | |
|
|
541 | my $recipients = join(" ",@{$self->{ra_send_to} }); |
|
|
542 | |
|
|
543 | return join("", '<pre>',$preview_header,$msg,"\n","\n", |
|
|
544 | '</pre>', |
|
|
545 | CGI::p('Use browser back button to return from preview mode'), |
|
|
546 | CGI::h3('Emails to be sent to the following:'), |
|
|
547 | $recipients, "\n", |
|
|
548 | |
|
|
549 | ); |
|
|
550 | |
|
|
551 | } |
|
|
552 | sub print_form { |
| 532 | my ($self, $setID) = @_; |
553 | my ($self, $setID) = @_; |
| 533 | my $r = $self->{r}; |
554 | my $r = $self->{r}; |
| 534 | my $authz = $self->{authz}; |
555 | my $authz = $self->{authz}; |
| 535 | my $user = $r->param('user'); |
556 | my $user = $r->param('user'); |
| 536 | my $db = $self->{db}; |
557 | my $db = $self->{db}; |
| … | |
… | |
| 542 | |
563 | |
| 543 | my $userTemplate = $db->newUser; |
564 | my $userTemplate = $db->newUser; |
| 544 | my $permissionLevelTemplate = $db->newPermissionLevel; |
565 | my $permissionLevelTemplate = $db->newPermissionLevel; |
| 545 | |
566 | |
| 546 | # This code will require changing if the permission and user tables ever have different keys. |
567 | # This code will require changing if the permission and user tables ever have different keys. |
| 547 | my @users = $db->listUsers; |
568 | my @users = @{ $self->{ra_users} }; |
|
|
569 | my $ra_user_records = $self->{ra_user_records}; |
|
|
570 | my %classlistLabels = ();# %$hr_classlistLabels; |
|
|
571 | foreach my $ur (@{ $ra_user_records }) { |
|
|
572 | $classlistLabels{$ur->user_id} = $ur->user_id.' '.$ur->last_name. ', '. $ur->first_name.' - '.$ur->section; |
|
|
573 | } |
| 548 | |
574 | |
| 549 | # This table can be consulted when display-ready forms of field names are needed. |
|
|
| 550 | # my %prettyFieldNames = map {$_ => $_} ($userTemplate->FIELDS(), $permissionLevelTemplate->FIELDS()); |
|
|
| 551 | # @prettyFieldNames{qw( |
|
|
| 552 | # user_id |
|
|
| 553 | # first_name |
|
|
| 554 | # last_name |
|
|
| 555 | # email_address |
|
|
| 556 | # student_id |
|
|
| 557 | # status |
|
|
| 558 | # section |
|
|
| 559 | # recitation |
|
|
| 560 | # comment |
|
|
| 561 | # permission |
|
|
| 562 | # )} = ( |
|
|
| 563 | # "User ID", |
|
|
| 564 | # "First Name", |
|
|
| 565 | # "Last Name", |
|
|
| 566 | # "E-mail", |
|
|
| 567 | # "Student ID", |
|
|
| 568 | # "Status", |
|
|
| 569 | # "Section", |
|
|
| 570 | # "Recitation", |
|
|
| 571 | # "Comment", |
|
|
| 572 | # "Perm. Level" |
|
|
| 573 | # ); |
|
|
| 574 | |
575 | |
| 575 | # my %fieldProperties = ( |
|
|
| 576 | # user_id => { |
|
|
| 577 | # type => "text", |
|
|
| 578 | # size => 8, |
|
|
| 579 | # access => "readonly", |
|
|
| 580 | # }, |
|
|
| 581 | # first_name => { |
|
|
| 582 | # type => "text", |
|
|
| 583 | # size => 10, |
|
|
| 584 | # access => "readwrite", |
|
|
| 585 | # }, |
|
|
| 586 | # last_name => { |
|
|
| 587 | # type => "text", |
|
|
| 588 | # size => 10, |
|
|
| 589 | # access => "readwrite", |
|
|
| 590 | # }, |
|
|
| 591 | # email_address => { |
|
|
| 592 | # type => "text", |
|
|
| 593 | # size => 20, |
|
|
| 594 | # access => "readwrite", |
|
|
| 595 | # }, |
|
|
| 596 | # student_id => { |
|
|
| 597 | # type => "text", |
|
|
| 598 | # size => 11, |
|
|
| 599 | # access => "readwrite", |
|
|
| 600 | # }, |
|
|
| 601 | # status => { |
|
|
| 602 | # type => "enumerable", |
|
|
| 603 | # size => 4, |
|
|
| 604 | # access => "readwrite", |
|
|
| 605 | # items => { |
|
|
| 606 | # "C" => "Enrolled", |
|
|
| 607 | # "D" => "Drop", |
|
|
| 608 | # "A" => "Audit", |
|
|
| 609 | # }, |
|
|
| 610 | # synonyms => { |
|
|
| 611 | # qr/^[ce]/i => "C", |
|
|
| 612 | # qr/^[dw]/i => "D", |
|
|
| 613 | # qr/^a/i => "A", |
|
|
| 614 | # "*" => "C", |
|
|
| 615 | # } |
|
|
| 616 | # }, |
|
|
| 617 | # section => { |
|
|
| 618 | # type => "text", |
|
|
| 619 | # size => 4, |
|
|
| 620 | # access => "readwrite", |
|
|
| 621 | # }, |
|
|
| 622 | # recitation => { |
|
|
| 623 | # type => "text", |
|
|
| 624 | # size => 4, |
|
|
| 625 | # access => "readwrite", |
|
|
| 626 | # }, |
|
|
| 627 | # comment => { |
|
|
| 628 | # type => "text", |
|
|
| 629 | # size => 20, |
|
|
| 630 | # access => "readwrite", |
|
|
| 631 | # }, |
|
|
| 632 | # permission => { |
|
|
| 633 | # type => "number", |
|
|
| 634 | # size => 2, |
|
|
| 635 | # access => "readwrite", |
|
|
| 636 | # } |
|
|
| 637 | # ); |
|
|
| 638 | |
|
|
| 639 | |
|
|
| 640 | |
|
|
| 641 | ############################################################################################################## |
576 | ############################################################################################################## |
| 642 | |
577 | |
| 643 | # my ($ar_sortedNames, $hr_classlistLabels) = getClasslistFilesAndLabels($course); |
578 | |
| 644 | # my @sortedNames = @$ar_sortedNames; |
|
|
| 645 | my %classlistLabels = ();# %$hr_classlistLabels; |
|
|
| 646 | unshift(@users, "Yourself"); |
|
|
| 647 | $classlistLabels{None} = 'Yourself'; |
|
|
| 648 | my $from = $self->{from}; |
579 | my $from = $self->{from}; |
| 649 | my $subject = $self->{subject}; |
580 | my $subject = $self->{subject}; |
| 650 | my $replyTo = $self->{replyTo}; |
581 | my $replyTo = $self->{replyTo}; |
| 651 | my $columns = $self->{columns}; |
582 | my $columns = $self->{columns}; |
| 652 | my $rows = $self->{rows}; |
583 | my $rows = $self->{rows}; |
| … | |
… | |
| 654 | my $input_file = $self->{input_file}; |
585 | my $input_file = $self->{input_file}; |
| 655 | my $output_file = $self->{output_file}; |
586 | my $output_file = $self->{output_file}; |
| 656 | my @sorted_messages = $self->get_message_file_names; |
587 | my @sorted_messages = $self->get_message_file_names; |
| 657 | my @sorted_merge_files = $self->get_merge_file_names; |
588 | my @sorted_merge_files = $self->get_merge_file_names; |
| 658 | my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; |
589 | my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; |
| 659 | |
590 | my $delimiter = ','; |
| 660 | |
591 | my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter"); |
|
|
592 | my @merge_keys = keys %$rh_merge_data; |
|
|
593 | my $preview_user = $self->{preview_user}; |
|
|
594 | my $preview_record = $db->getUser($preview_user); |
|
|
595 | |
|
|
596 | ############################################################################################# |
|
|
597 | |
| 661 | print CGI::start_form({method=>"post", action=>$r->uri()}); |
598 | print CGI::start_form({method=>"post", action=>$r->uri()}); |
| 662 | #create list of sudents |
599 | print $self->hidden_authen_fields(); |
| 663 | # show professors's name and email address |
600 | ############################################################################################# |
| 664 | # show replyTo field and From field |
601 | # begin upper table |
|
|
602 | ############################################################################################# |
|
|
603 | |
| 665 | print CGI::start_table({-border=>'2', -cellpadding=>'4'}); |
604 | print CGI::start_table({-border=>'2', -cellpadding=>'4'}); |
| 666 | print CGI::Tr({-align=>'left',-valign=>'VCENTER'}, |
605 | print CGI::Tr({-align=>'left',-valign=>'VCENTER'}, |
|
|
606 | ############################################################################################# |
|
|
607 | # first column |
|
|
608 | ############################################################################################# |
|
|
609 | |
| 667 | CGI::td("Message file: $input_file","\n",CGI::br(), |
610 | CGI::td("Message file: $input_file","\n",CGI::br(), |
| 668 | CGI::submit(-name=>'action', -value=>'Open'), ' ',"\n", |
611 | CGI::submit(-name=>'action', -value=>'Open'), ' ',"\n", |
| 669 | #CGI::textfield(-name=>'openfilename', -size => 20, -value=> "$input_file", -override=>1), "\n",CGI::br(), |
|
|
| 670 | CGI::popup_menu(-name=>'openfilename', |
612 | CGI::popup_menu(-name=>'openfilename', |
| 671 | -values=>\@sorted_messages, |
613 | -values=>\@sorted_messages, |
| 672 | -default=>$input_file |
614 | -default=>$input_file |
| 673 | ), "\n",CGI::br(), |
615 | ), "\n",CGI::br(), |
| 674 | |
616 | |
| 675 | "Save file to: $output_file","\n",CGI::br(), |
617 | "Save file to: $output_file","\n",CGI::br(), |
| 676 | "\n", 'From:',' ', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1), |
618 | "\n", 'From:',' ', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1), |
| 677 | "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1), |
619 | "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1), |
| 678 | "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>40, -override=>1), |
620 | "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>35, -override=>1), |
| 679 | ), |
621 | ), |
|
|
622 | ############################################################################################# |
|
|
623 | # second column |
|
|
624 | ############################################################################################# |
| 680 | CGI::td({-align=>'left'}, |
625 | CGI::td({-align=>'left'}, |
| 681 | CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'], |
626 | CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'], |
| 682 | -labels=>{all_students=>'All active students',studentID => 'Select recipients'}, |
627 | -labels=>{all_students=>'All active students',studentID => 'Select recipients'}, |
| 683 | -default=>'studentID', |
628 | -default=>'studentID', |
| 684 | -linebreak=>1), |
629 | -linebreak=>1), |
| … | |
… | |
| 686 | CGI::popup_menu(-name=>'classList', |
631 | CGI::popup_menu(-name=>'classList', |
| 687 | -values=>\@users, |
632 | -values=>\@users, |
| 688 | -labels=>\%classlistLabels, |
633 | -labels=>\%classlistLabels, |
| 689 | -size => 10, |
634 | -size => 10, |
| 690 | -multiple => 1, |
635 | -multiple => 1, |
| 691 | -default=>'Yourself' |
636 | -default=>$user |
| 692 | ), |
637 | ), |
| 693 | |
638 | |
| 694 | |
639 | |
| 695 | ), |
640 | ), |
|
|
641 | ############################################################################################# |
|
|
642 | # third column |
|
|
643 | ############################################################################################# |
| 696 | CGI::td({align=>'left'}, |
644 | CGI::td({align=>'left'}, |
|
|
645 | "Merge file is: $merge_file", CGI::br(), |
| 697 | CGI::submit(-name=>'action', -value=>'Choose merge file'), |
646 | CGI::submit(-name=>'action', -value=>'Choose merge file'),CGI::br(), |
| 698 | CGI::popup_menu(-name=>'merge_file', |
647 | CGI::popup_menu(-name=>'merge_file', |
| 699 | -values=>\@sorted_merge_files, |
648 | -values=>\@sorted_merge_files, |
| 700 | -default=>$merge_file, |
649 | -default=>$merge_file, |
| 701 | ), "\n",CGI::br(), |
650 | ), "\n",CGI::hr(),CGI::br(), |
| 702 | CGI::submit(-name=>'preview', -value=>'preview',-label=>'Preview')," email to ", |
651 | CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview')," email to ", |
| 703 | CGI::popup_menu(-name=>'classList', |
652 | CGI::popup_menu(-name=>'preview_user', |
| 704 | -values=>\@users, |
653 | -values=>\@users, |
| 705 | -labels=>\%classlistLabels, |
654 | #-labels=>\%classlistLabels, |
| 706 | -default=>'Yourself' |
655 | -default=>$preview_user, |
| 707 | ), |
656 | ), |
| 708 | CGI::br(),CGI::br(), |
657 | CGI::hr(), |
| 709 | CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(), |
658 | CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(), |
| 710 | " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows), |
659 | " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows), |
| 711 | " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns), |
660 | " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns), |
| 712 | CGI::br(),CGI::br(), |
661 | CGI::br(),CGI::br(), |
| 713 | #show available macros |
662 | #show available macros |
| … | |
… | |
| 716 | -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'], |
665 | -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'], |
| 717 | -labels=>{''=>'list of insertable macros', |
666 | -labels=>{''=>'list of insertable macros', |
| 718 | '$SID'=>'$SID - Student ID', |
667 | '$SID'=>'$SID - Student ID', |
| 719 | '$FN'=>'$FN - First name', |
668 | '$FN'=>'$FN - First name', |
| 720 | '$LN'=>'$LN - Last name', |
669 | '$LN'=>'$LN - Last name', |
| 721 | '$SECTION'=>'$SECTION - Student\'s Section', |
670 | '$SECTION'=>'$SECTION', |
| 722 | '$RECITATION'=>'$RECITATION', |
671 | '$RECITATION'=>'$RECITATION', |
| 723 | '$STATUS'=>'$STATUS - C, Audit, Drop, etc.', |
672 | '$STATUS'=>'$STATUS - C, Audit, Drop, etc.', |
| 724 | '$EMAIL'=>'$EMAIL - Email address', |
673 | '$EMAIL'=>'$EMAIL - Email address', |
| 725 | '$LOGIN'=>'$LOGIN - Login', |
674 | '$LOGIN'=>'$LOGIN - Login', |
| 726 | '$COL[3]'=>'$COL[3] - 3rd column in merge file', |
675 | '$COL[3]'=>'$COL[3] - 3rd col', |
| 727 | '$COL[-1]'=>'$COL[-1] - Last column' |
676 | '$COL[-1]'=>'$COL[-1] - Last column' |
| 728 | } |
677 | } |
| 729 | ), "\n", |
678 | ), "\n", |
| 730 | ), |
679 | ), |
| 731 | |
680 | |
| 732 | ); # end Tr |
681 | ); # end Tr |
| 733 | print CGI::end_table(); |
682 | print CGI::end_table(); |
|
|
683 | ############################################################################################# |
|
|
684 | # end upper table |
|
|
685 | ############################################################################################# |
|
|
686 | |
|
|
687 | # show merge file |
|
|
688 | # print "<pre>",(map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} 0..8),"</pre>"; |
|
|
689 | # print CGI::popup_menu( |
|
|
690 | # -name=>'dummyName2', |
|
|
691 | # -values=>\@merge_keys, |
|
|
692 | # -labels=>$rh_merge_data, |
|
|
693 | # -multiple=>1, |
|
|
694 | # -size =>2, |
|
|
695 | # |
|
|
696 | # ), "\n",CGI::br(); |
|
|
697 | # warn "merge keys ", join( " ",@merge_keys); |
|
|
698 | ############################################################################################# |
|
|
699 | # merge file fragment and message text area field |
|
|
700 | ############################################################################################# |
|
|
701 | |
|
|
702 | my @tmp2= @{$rh_merge_data->{ $db->getUser($preview_user)->student_id } }; |
|
|
703 | print CGI::pre("",data_format(0..($#tmp2)),"\n", data_format(@tmp2)); |
| 734 | #create a textbox with the subject and a textarea with the message |
704 | #create a textbox with the subject and a textarea with the message |
| 735 | |
|
|
| 736 | #print actual body of message |
705 | #print actual body of message |
| 737 | |
706 | |
| 738 | print "\n", CGI::p( $self->{message}) if defined($self->{message}); |
707 | print "\n", CGI::p( $self->{message}) if defined($self->{message}); |
| 739 | print "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1)); |
708 | print "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1)); |
| 740 | |
709 | |
| 741 | #create all necessary action buttons |
710 | ############################################################################################# |
|
|
711 | # action button table |
|
|
712 | ############################################################################################# |
| 742 | print CGI::table( { -border=>2,-cellpadding=>4}, |
713 | print CGI::table( { -border=>2,-cellpadding=>4}, |
| 743 | CGI::Tr( |
714 | CGI::Tr( |
| 744 | CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n", |
715 | CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n", |
| 745 | CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n", |
716 | CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n", |
| 746 | CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'), |
717 | CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'), |
| … | |
… | |
| 750 | ) |
721 | ) |
| 751 | ); |
722 | ); |
| 752 | |
723 | |
| 753 | ############################################################################################################## |
724 | ############################################################################################################## |
| 754 | |
725 | |
| 755 | print $self->hidden_authen_fields(); |
|
|
| 756 | # print CGI::submit({name=>"save_classlist", value=>"Save Changes to Users"}); |
|
|
| 757 | print CGI::end_form(); |
726 | print CGI::end_form(); |
| 758 | return ""; |
727 | return ""; |
| 759 | } |
728 | } |
| 760 | |
729 | |
| 761 | ############################################################################## |
730 | ############################################################################## |
| … | |
… | |
| 841 | @mergeFiles = sort @mergeFiles; |
810 | @mergeFiles = sort @mergeFiles; |
| 842 | # warn "FIXME scoring directory $scoringDirectory merge Files", join(" ", @mergeFiles); |
811 | # warn "FIXME scoring directory $scoringDirectory merge Files", join(" ", @mergeFiles); |
| 843 | unshift(@mergeFiles, 'None'); |
812 | unshift(@mergeFiles, 'None'); |
| 844 | return @mergeFiles; |
813 | return @mergeFiles; |
| 845 | } |
814 | } |
|
|
815 | |
|
|
816 | sub read_merge_file { |
|
|
817 | my $self = shift; |
|
|
818 | my $fileName = shift; |
|
|
819 | my $delimiter = shift; |
|
|
820 | $delimiter = ',' unless defined($delimiter); |
|
|
821 | my $scoringDirectory= $self->{ce}->{courseDirs}->{scoring}; |
|
|
822 | my $filePath = "$scoringDirectory/$fileName"; |
|
|
823 | # Takes a delimited file as a parameter and returns an |
|
|
824 | # associative array with the first field as the key. |
|
|
825 | # Blank lines are skipped. White space is removed |
|
|
826 | my(@dbArray,$key,%assocArray,$dbString); |
|
|
827 | local(*FILE); |
|
|
828 | open(FILE, "$filePath") or $self->submission_error("Can't open file $filePath"); |
|
|
829 | my $index=0; |
|
|
830 | while (<FILE>){ |
|
|
831 | unless ($_ =~ /\S/) {next;} ## skip blank lines |
|
|
832 | chomp; |
|
|
833 | @{$dbArray[$index]} =$self->getRecord($_,$delimiter); |
|
|
834 | $key =$dbArray[$index][0]; |
|
|
835 | #@dbArray = map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @dbArray; |
|
|
836 | #$dbString = join(" | ",@dbArray); |
|
|
837 | $assocArray{$key}=$dbArray[$index]; |
|
|
838 | $index++; |
|
|
839 | } |
|
|
840 | close(FILE); |
|
|
841 | return \%assocArray; |
|
|
842 | } |
|
|
843 | sub getRecord { |
|
|
844 | my $self = shift; |
|
|
845 | my $line = shift; |
|
|
846 | my $delimiter = shift; |
|
|
847 | $delimiter = ',' unless defined($delimiter); |
|
|
848 | |
|
|
849 | # Takes a delimited line as a parameter and returns an |
|
|
850 | # array. Note that all white space is removed. If the |
|
|
851 | # last field is empty, the last element of the returned |
|
|
852 | # array is also empty (unlike what the perl split command |
|
|
853 | # would return). E.G. @lineArray=&getRecord(\$delimitedLine). |
|
|
854 | |
|
|
855 | my(@lineArray); |
|
|
856 | $line.=$delimiter; # add 'A' to end of line so that |
|
|
857 | # last field is never empty |
|
|
858 | @lineArray = split(/\s*${delimiter}\s*/,$line); |
|
|
859 | $lineArray[0] =~s/^\s*//; # remove white space from first element |
|
|
860 | @lineArray; |
|
|
861 | } |
|
|
862 | |
|
|
863 | sub process_message { |
|
|
864 | my $self = shift; |
|
|
865 | my $ur = shift; |
|
|
866 | my $rh_merge_data = shift; |
|
|
867 | my $text = defined($self->{r_text}) ? ${ $self->{r_text} }: |
|
|
868 | 'FIXME no text was produced by initialization!!'; |
|
|
869 | #user macros that can be used in the email message |
|
|
870 | my $SID = $ur->student_id; |
|
|
871 | my $FN = $ur->first_name; |
|
|
872 | my $LN = $ur->last_name; |
|
|
873 | my $SECTION = $ur->section; |
|
|
874 | my $RECITATION = $ur->recitation; |
|
|
875 | my $STATUS = $ur->status; |
|
|
876 | my $EMAIL = $ur->email_address; |
|
|
877 | my $LOGIN = $ur->user_id; |
|
|
878 | # get record from merge file |
|
|
879 | # FIXME this is inefficient. The info should be cached |
|
|
880 | my @COL = @{$rh_merge_data->{$SID} }; |
|
|
881 | |
|
|
882 | my $endCol = @COL; |
|
|
883 | # for safety, only evaluate special variables |
|
|
884 | my $tmp = $text; |
|
|
885 | $tmp =~ s/(\$SID)/eval($1)/ge; |
|
|
886 | $tmp =~ s/(\$LN)/eval($1)/ge; |
|
|
887 | $tmp =~ s/(\$FN)/eval($1)/ge; |
|
|
888 | $tmp =~ s/(\$STATUS)/eval($1)/ge; |
|
|
889 | $tmp =~ s/(\$SECTION)/eval($1)/ge; |
|
|
890 | $tmp =~ s/(\$RECITATION)/eval($1)/ge; |
|
|
891 | $tmp =~ s/(\$EMAIL)/eval($1)/ge; |
|
|
892 | $tmp =~ s/(\$LOGIN)/eval($1)/ge; |
|
|
893 | $tmp =~ s/\$COL\[ *-/\$COL\[$endCol-/g; |
|
|
894 | $tmp =~ s/(\$COL\[.*?\])/eval($1)/ge; |
|
|
895 | |
|
|
896 | my $preview_header = CGI::pre("",data_format(0..($#COL)),"\n", data_format(@COL)). |
|
|
897 | CGI::h3( "This sample mail would be sent to $EMAIL"); |
|
|
898 | |
|
|
899 | |
|
|
900 | my $msg = join("", |
|
|
901 | "To: " , $ur->email_address,"\n", |
|
|
902 | "From: " , $self->{from} , "\n" , |
|
|
903 | "Reply-To: " , $self->{replyTo} , "\n" , |
|
|
904 | "Subject: " , $self->{subject} , "\n" ,"\n" , |
|
|
905 | $tmp , "\n" |
|
|
906 | ); |
|
|
907 | |
|
|
908 | $msg =~ s/\r//g; |
|
|
909 | return $msg, $preview_header; |
|
|
910 | } |
|
|
911 | sub data_format { |
|
|
912 | map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @_; |
|
|
913 | } |
| 846 | 1; |
914 | 1; |