Annotation of loncom/interface/lonrequestcourse.pm, revision 1.24
1.1 raeburn 1: # The LearningOnline Network
2: # Request a course
3: #
1.24 ! raeburn 4: # $Id: lonrequestcourse.pm,v 1.23 2009/08/22 21:08:39 raeburn Exp $
1.1 raeburn 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: ###
29:
30: =head1 NAME
31:
32: Apache::lonrequestcourse.pm
33:
34: =head1 SYNOPSIS
35:
36: Allows users to request creation of new courses.
37:
38: This is part of the LearningOnline Network with CAPA project
39: described at http://www.lon-capa.org.
40:
41: =head1 SUBROUTINES
42:
43: =over
44:
45: =item handler()
46:
1.12 raeburn 47: =item header()
48:
49: =item form_elements()
50:
51: =item onload_action()
52:
53: =item check_can_request()
54:
55: =item course_types()
56:
57: =item print_main_menu()
58:
59: =item request_administration()
60:
61: =item print_request_form()
62:
63: =item print_enrollment_menu()
64:
65: =item inst_section_selector()
66:
67: =item date_setting_table()
68:
69: =item print_personnel_menu()
70:
71: =item print_request_status()
72:
73: =item print_request_logs()
74:
75: =item print_review()
76:
77: =item dates_from_form()
78:
79: =item courseinfo_form()
80:
81: =item clone_form()
82:
83: =item clone_text()
84:
85: =item coursecode_form()
86:
87: =item get_course_dom()
88:
89: =item display_navbuttons()
90:
91: =item print_request_outcome()
92:
93: =item get_processtype()
94:
95: =item check_autolimit()
96:
97: =item build_batchcreatehash()
98:
99: =item retrieve_settings()
100:
101: =item get_request_settings()
102:
1.1 raeburn 103: =back
104:
105: =cut
106:
107: package Apache::lonrequestcourse;
108:
109: use strict;
110: use Apache::Constants qw(:common :http);
111: use Apache::lonnet;
112: use Apache::loncommon;
113: use Apache::lonlocal;
1.8 raeburn 114: use Apache::loncoursequeueadmin;
1.4 raeburn 115: use LONCAPA qw(:DEFAULT :match);
1.1 raeburn 116:
117: sub handler {
118: my ($r) = @_;
1.20 raeburn 119: &Apache::loncommon::content_type($r,'text/html');
120: $r->send_http_header;
1.1 raeburn 121: if ($r->header_only) {
122: return OK;
123: }
124:
1.2 raeburn 125: &Apache::lonhtmlcommon::clear_breadcrumbs();
126: my $dom = &get_course_dom();
1.1 raeburn 127: my $action = $env{'form.action'};
128: my $state = $env{'form.state'};
1.2 raeburn 129: my %stored;
130: my $jscript;
131: if ((defined($state)) && (defined($action))) {
1.16 raeburn 132: if (($action eq 'view') && ($state eq 'details')) {
133: if ((defined($env{'form.showdom'})) && (defined($env{'form.cnum'}))) {
134: my $result = &retrieve_settings($env{'form.showdom'},$env{'form.cnum'});
1.2 raeburn 135: }
136: }
1.16 raeburn 137: my %elements = &form_elements($dom);
1.2 raeburn 138: my $elementsref = {};
139: if (ref($elements{$action}) eq 'HASH') {
140: if (ref($elements{$action}{$state}) eq 'HASH') {
141: $elementsref = $elements{$action}{$state};
142: }
143: }
1.16 raeburn 144: if (($state eq 'courseinfo') && ($env{'form.clonedom'} eq '')) {
145: $env{'form.clonedom'} = $dom;
146: }
1.2 raeburn 147: $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
148: }
149:
150: if ($state eq 'personnel') {
151: $jscript .= "\n".&Apache::loncommon::userbrowser_javascript();
152: }
153:
154: my $loaditems = &onload_action($action,$state);
155:
156: my %states;
1.16 raeburn 157: $states{'view'} = ['pick_request','details','cancel','removal'];
1.2 raeburn 158: $states{'log'} = ['filter','display'];
159: $states{'new'} = ['courseinfo','enrollment','personnel','review','process'];
1.20 raeburn 160:
1.2 raeburn 161: if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) {
162: unless ($env{'form.state'} eq 'crstype') {
1.20 raeburn 163: unshift(@{$states{'new'}},'codepick');
1.2 raeburn 164: }
165: }
166:
167: foreach my $key (keys(%states)) {
168: if (ref($states{$key}) eq 'ARRAY') {
169: unshift (@{$states{$key}},'crstype');
170: }
171: }
172:
1.3 raeburn 173: my %trail = (
1.10 raeburn 174: crstype => 'Course Request Action',
175: codepick => 'Category',
176: courseinfo => 'Description',
1.16 raeburn 177: enrollment => 'Access Dates',
1.10 raeburn 178: personnel => 'Personnel',
179: review => 'Review',
180: process => 'Result',
181: pick_request => 'Display Summary',
1.16 raeburn 182: details => 'Request Details',
183: cancel => 'Cancel Request',
184: removal => 'Outcome',
1.3 raeburn 185: );
186:
1.16 raeburn 187: if (($env{'form.crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) {
188: $trail{'enrollment'} = 'Enrollment';
189: }
190:
1.2 raeburn 191: my $page = 0;
1.3 raeburn 192: my $crumb;
1.2 raeburn 193: if (defined($action)) {
194: my $done = 0;
195: my $i=0;
196: if (ref($states{$action}) eq 'ARRAY') {
197: while ($i<@{$states{$action}} && !$done) {
198: if ($states{$action}[$i] eq $state) {
199: $page = $i;
200: $done = 1;
201: }
202: $i++;
203: }
204: }
1.3 raeburn 205: for (my $i=0; $i<@{$states{$action}}; $i++) {
206: if ($state eq $states{$action}[$i]) {
207: &Apache::lonhtmlcommon::add_breadcrumb(
208: {text=>"$trail{$state}"});
209: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
210: last;
211: } else {
212: if (($state eq 'process') && ($i > 0)) {
213: &Apache::lonhtmlcommon::add_breadcrumb(
214: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[0]')",
215: text=>"$trail{$states{$action}[$i]}"});
216: } else {
217: &Apache::lonhtmlcommon::add_breadcrumb(
218: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[$i]')",
219: text=>"$trail{$states{$action}[$i]}"});
220: }
221: }
222: }
223: } else {
224: &Apache::lonhtmlcommon::add_breadcrumb(
225: {text=>'Pick Action'});
226: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
1.2 raeburn 227: }
228:
1.1 raeburn 229: my %can_request;
230: my $canreq = &check_can_request($dom,\%can_request);
231: if ($action eq 'new') {
232: if ($canreq) {
233: if ($state eq 'crstype') {
1.3 raeburn 234: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,
235: $crumb);
1.1 raeburn 236: } else {
1.2 raeburn 237: &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
1.3 raeburn 238: $loaditems,$crumb);
1.1 raeburn 239: }
240: } else {
1.3 raeburn 241: $r->print(&header('Course Requests').$crumb.
1.1 raeburn 242: '<div class="LC_warning">'.
243: &mt('You do not have privileges to request creation of courses.').
1.2 raeburn 244: '</div>'.&Apache::loncommon::end_page());
1.1 raeburn 245: }
246: } elsif ($action eq 'view') {
1.10 raeburn 247: if ($state eq 'crstype') {
1.11 raeburn 248: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb);
249: } else {
250: &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
251: $loaditems,$crumb);
1.10 raeburn 252: }
1.1 raeburn 253: } elsif ($action eq 'log') {
1.3 raeburn 254: &print_request_logs($jscript,$loaditems,$crumb);
1.1 raeburn 255: } else {
1.3 raeburn 256: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb);
1.1 raeburn 257: }
258: return OK;
259: }
260:
1.2 raeburn 261: sub header {
262: my ($bodytitle,$jscript,$loaditems,$jsextra) = @_;
263: if ($jscript) {
1.6 raeburn 264: $jscript = '<script type="text/javascript">'."\n".
265: '// <![CDATA['."\n".
266: $jscript."\n".'// ]]>'."\n".'</script>'."\n";
1.2 raeburn 267: }
268: if ($loaditems) {
1.3 raeburn 269: $loaditems = {'add_entries' => $loaditems,};
270: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra,$loaditems);
271: } else {
272: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra);
273: }
1.2 raeburn 274: }
275:
276: sub form_elements {
277: my ($dom) = @_;
278: my %elements =
279: (
280: new => {
281: crstype => {
282: crstype => 'selectbox',
283: action => 'selectbox',
1.16 raeburn 284: origcnum => 'hidden',
1.2 raeburn 285: },
286: courseinfo => {
287: cdescr => 'text',
1.13 raeburn 288: clonecrs => 'text',
289: clonedom => 'selectbox',
1.2 raeburn 290: datemode => 'radio',
291: dateshift => 'text',
292: },
293: enrollment => {
1.13 raeburn 294: accessstart_month => 'selectbox',
295: accessstart_hour => 'selectbox',
296: accessend_month => 'selectbox',
297: accessend_hour => 'selectbox',
298: accessstart_day => 'text',
299: accessstart_year => 'text',
300: accessstart_minute => 'text',
301: accessstart_second => 'text',
302: accessend_day => 'text',
303: accessend_year => 'text',
304: accessend_minute => 'text',
305: accessend_second => 'text',
1.2 raeburn 306: no_end_date => 'checkbox',
307: },
308: personnel => {
309: addperson => 'checkbox',
310: },
1.13 raeburn 311: review => {
312: cnum => 'hidden',
313: },
1.2 raeburn 314: },
315: view => {
316: crstype => {
317: crstype => 'selectbox',
318: action => 'selectbox',
319: },
320: },
321: );
1.13 raeburn 322: my %servers = &Apache::lonnet::get_servers($dom,'library');
323: my $numlib = keys(%servers);
324: if ($numlib > 1) {
325: $elements{'new'}{'courseinfo'}{'chome'} = 'selectbox';
326: } else {
327: $elements{'new'}{'courseinfo'}{'chome'} = 'hidden';
328: }
1.2 raeburn 329: my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem);
330: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
331: \%cat_order,\@code_order);
332: my $numtitles = scalar(@codetitles);
333: if ($numtitles) {
334: my %extras;
335: $lastitem = pop(@codetitles);
336: $extras{'instcode_'.$lastitem} = 'text';
337: foreach my $item (@codetitles) {
338: $extras{'instcode_'.$item} = 'selectbox';
339: }
340: $elements{'new'}{'codepick'} = \%extras;
341: }
342: if (&Apache::lonnet::auto_run('',$dom)) {
343: my %extras = (
344: sectotal => 'hidden',
1.13 raeburn 345: enrollstart_month => 'selectbox',
346: enrollstart_hour => 'selectbox',
347: enrollend_month => 'selectbox',
348: enrollend_hour => 'selectbox',
349: enrollstart_day => 'text',
350: enrollstart_year => 'text',
351: enrollstart_minute => 'text',
352: enrollstart_second => 'text',
353: enrollend_day => 'text',
354: enrollend_year => 'text',
355: enrollend_minute => 'text',
356: enrollend_second => 'text',
1.2 raeburn 357: crosslisttotal => 'hidden',
358: addcrosslist => 'checkbox',
359: autoadds => 'radio',
360: autodrops => 'radio',
361: );
362: if ($env{'form.sectotal'} > 0) {
363: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
364: $extras{'sec_'.$i} = 'checkbox',
365: $extras{'secnum_'.$i} = 'text',
1.24 ! raeburn 366: $extras{'loncapasec_'.$i} = 'text',
1.2 raeburn 367: }
368: }
369: my $crosslisttotal = $env{'form.crosslisttotal'};
1.16 raeburn 370: if ($env{'form.addcrosslist'}) {
371: $crosslisttotal ++;
372: }
1.24 ! raeburn 373: if (!$crosslisttotal) {
1.2 raeburn 374: $crosslisttotal = 1;
375: }
1.24 ! raeburn 376: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
! 377: if ($numtitles) {
! 378: $extras{'crosslist_'.$i.'_'.$lastitem} = 'text';
! 379: }
! 380: if (@codetitles > 0) {
! 381: foreach my $item (@codetitles) {
! 382: $extras{'crosslist_'.$i.'_'.$item} = 'selectbox';
1.2 raeburn 383: }
384: }
1.24 ! raeburn 385: $extras{'crosslist_'.$i} = 'checkbox';
! 386: $extras{'crosslist_'.$i.'_instsec'} = 'text',
! 387: $extras{'crosslist_'.$i.'_lcsec'} = 'text',
1.2 raeburn 388: }
389: my %mergedhash = (%{$elements{'new'}{'enrollment'}},%extras);
390: %{$elements{'new'}{'enrollment'}} = %mergedhash;
391: }
392: my %people;
393: my $persontotal = $env{'form.persontotal'};
1.16 raeburn 394: if ($env{'form.addperson'}) {
395: $persontotal ++;
396: }
397: if ((!defined($persontotal)) || (!$persontotal)) {
1.2 raeburn 398: $persontotal = 1;
399: }
400: for (my $i=0; $i<$persontotal; $i++) {
1.13 raeburn 401: $people{'person_'.$i.'_uname'} = 'text',
402: $people{'person_'.$i.'_dom'} = 'selectbox',
403: $people{'person_'.$i.'_hidedom'} = 'hidden',
404: $people{'person_'.$i.'_firstname'} = 'text',
405: $people{'person_'.$i.'_lastname'} = 'text',
406: $people{'person_'.$i.'_emailaddr'} = 'text',
407: $people{'person_'.$i.'_role'} = 'selectbox',
408: $people{'person_'.$i.'_sec'} = 'selectbox',
409: $people{'person_'.$i.'_newsec'} = 'text',
1.2 raeburn 410: }
411: my %personnelhash = (%{$elements{'new'}{'personnel'}},%people);
412: %{$elements{'new'}{'personnel'}} = %personnelhash;
413: return %elements;
414: }
415:
416: sub onload_action {
417: my ($action,$state) = @_;
418: my %loaditems;
419: if (($action eq 'new') || ($action eq 'view')) {
420: $loaditems{'onload'} = 'javascript:setFormElements(document.requestcrs)';
421: }
422: return \%loaditems;
423: }
424:
1.1 raeburn 425: sub check_can_request {
426: my ($dom,$can_request) = @_;
427: my $canreq = 0;
1.4 raeburn 428: my ($types,$typename) = &course_types();
1.19 raeburn 429: my @options = ('approval','validate','autolimit');
430: my $optregex = join('|',@options);
1.4 raeburn 431: if ((ref($can_request) eq 'HASH') && (ref($types) eq 'ARRAY')) {
432: foreach my $type (@{$types}) {
1.1 raeburn 433: if (&Apache::lonnet::usertools_access($env{'user.name'},
434: $env{'user.domain'},
435: $type,undef,'requestcourses')) {
436: $canreq ++;
437: if ($dom eq $env{'user.domain'}) {
438: $can_request->{$type} = 1;
439: }
440: }
441: if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
442: my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type});
443: if (@curr > 0) {
444: $canreq ++;
445: unless ($dom eq $env{'user.domain'}) {
1.19 raeburn 446: if (grep(/^\Q$dom\E:($optregex)(=?\d*)$/,@curr)) {
1.1 raeburn 447: $can_request->{$type} = 1;
448: }
449: }
450: }
451: }
452: }
453: }
454: return $canreq;
455: }
456:
1.4 raeburn 457: sub course_types {
458: my @types = ('official','unofficial','community');
459: my %typename = (
460: official => 'Official course',
461: unofficial => 'Unofficial course',
462: community => 'Community',
463: );
464: return (\@types,\%typename);
465: }
466:
467:
1.1 raeburn 468: sub print_main_menu {
1.3 raeburn 469: my ($r,$can_request,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.4 raeburn 470: my ($types,$typename) = &course_types();
1.1 raeburn 471: my $onchange;
472: unless ($env{'form.interface'} eq 'textual') {
473: $onchange = 1;
474: }
475:
1.2 raeburn 476: my $nextstate_setter = "\n";
477: if (ref($states) eq 'HASH') {
478: foreach my $key (keys(%{$states})) {
479: if (ref($states->{$key}) eq 'ARRAY') {
480: $nextstate_setter .=
481: " if (actionchoice == '$key') {
482: nextstate = '".$states->{$key}[1]."';
483: }
484: ";
485: }
486: }
487: }
1.1 raeburn 488:
1.2 raeburn 489: my $js = <<"END";
1.1 raeburn 490:
1.2 raeburn 491: function nextPage(formname) {
492: var crschoice = document.requestcrs.crstype.value;
493: var actionchoice = document.requestcrs.action.value;
494: if (check_can_request(crschoice,actionchoice) == true) {
495: if ((actionchoice == 'new') && (crschoice == 'official')) {
496: nextstate = 'codepick';
497: } else {
498: $nextstate_setter
499: }
1.1 raeburn 500: formname.state.value= nextstate;
501: formname.submit();
502: }
503: return;
504: }
505:
1.2 raeburn 506: function check_can_request(crschoice,actionchoice) {
1.1 raeburn 507: var official = '';
508: var unofficial = '';
509: var community = '';
510: END
511:
512: foreach my $item (keys(%{$can_request})) {
513: $js .= "
514: $item = 1;
515: ";
516: }
517: my %lt = &Apache::lonlocal::texthash(
518: official => 'You are not permitted to request creation of an official course in this domain.',
519: unofficial => 'You are not permitted to request creation of an unofficial course in this domain.',
520: community => 'You are not permitted to request creation of a community this domain.',
521: all => 'You must choose a specific course type when making a new course request.\\nAll types is not allowed.',
522: );
523: $js .= <<END;
524: if (crschoice == 'official') {
525: if (official != 1) {
526: alert("$lt{'official'}");
527: return false;
528: }
529: } else {
530: if (crschoice == 'unofficial') {
531: if (unofficial != 1) {
532: alert("$lt{'unofficial'}");
533: return false;
534: }
535: } else {
536: if (crschoice == 'community') {
537: if (community != 1) {
538: alert("$lt{'community'}");
539: return false;
540: }
541: } else {
542: if (actionchoice == 'new') {
543: alert("$lt{'all'}");
544: return false;
545: }
546: }
547: }
548: }
549: return true;
550: }
551:
552: END
553:
1.3 raeburn 554: $r->print(&header('Course Requests',$js.$jscript,$loaditems).$crumb.
555: '<div>'.
1.1 raeburn 556: '<form name="domforcourse" method="post" action="/adm/requestcourse">'.
557: &Apache::lonhtmlcommon::start_pick_box().
1.8 raeburn 558: &Apache::lonhtmlcommon::row_title('Course Domain').
1.1 raeburn 559: &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange));
560: if (!$onchange) {
561: $r->print(' <input type="submit" name="godom" value="'.
562: &mt('Change').'" />');
563: }
564: $r->print(&Apache::lonhtmlcommon::row_closure(1).
565: &Apache::lonhtmlcommon::end_pick_box().'</form></div>');
566:
1.2 raeburn 567: my $formname = 'requestcrs';
1.1 raeburn 568: my $nexttext = &mt('Next');
1.14 raeburn 569: $r->print(
570: '<div><form name="'.$formname.'" method="post" action="/adm/requestcourse">'.
1.1 raeburn 571: &Apache::lonhtmlcommon::start_pick_box().
572: &Apache::lonhtmlcommon::row_title('Action').'
573: <input type="hidden" name="showdom" value="'.$dom.'" />
574: <select size="1" name="action" >
1.2 raeburn 575: <option value="new">'.&mt('New request').'</option>
1.1 raeburn 576: <option value="view">'.&mt('View/Modify/Cancel pending requests').'</option>
577: <option value="log">'.&mt('View request history').'</option>
578: </select>'.
579: &Apache::lonhtmlcommon::row_closure().
580: &Apache::lonhtmlcommon::row_title('Course Type').'
581: <select size="1" name="crstype">
1.4 raeburn 582: <option value="any">'.&mt('All types').'</option>');
583: if ((ref($types) eq 'ARRAY') && (ref($typename) eq 'HASH')) {
584: foreach my $type (@{$types}) {
585: my $selected = '';
586: if ($type eq 'official') {
587: $selected = ' selected="selected"';
588: }
589: $r->print('<option value="'.$type.'"'.$selected.'>'.$typename->{$type}.
590: '</option>'."\n");
591: }
592: }
593: $r->print('</select>
1.1 raeburn 594: <input type="hidden" name="state" value="crstype" />'.
595: &Apache::lonhtmlcommon::row_closure(1).
596: &Apache::lonhtmlcommon::end_pick_box().'<br />
1.2 raeburn 597: <input type="button" name="next" value="'.$nexttext.'" onclick="javascript:nextPage(document.'.$formname.')" />
1.1 raeburn 598: </form></div>');
599: $r->print(&Apache::loncommon::end_page());
600: return;
601: }
602:
603: sub request_administration {
1.3 raeburn 604: my ($r,$action,$state,$page,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.2 raeburn 605: my $js;
1.16 raeburn 606: if (($action eq 'new') || (($action eq 'view') && ($state eq 'pick_request'))) {
1.2 raeburn 607: $js = <<END;
1.1 raeburn 608:
609: function nextPage(formname,nextstate) {
610: formname.state.value= nextstate;
611: formname.submit();
612: }
1.16 raeburn 613:
614: END
615: }
616: if (($action eq 'new') || ($action eq 'view')) {
617: $js .= <<END;
618:
1.1 raeburn 619: function backPage(formname,prevstate) {
620: formname.state.value = prevstate;
621: formname.submit();
622: }
623:
624: END
1.2 raeburn 625: }
626: if ($action eq 'new') {
627: my $jsextra;
1.1 raeburn 628: unless (($state eq 'review') || ($state eq 'process')) {
1.2 raeburn 629: $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom);
1.1 raeburn 630: }
1.3 raeburn 631: $r->print(&header('Request a course',$js.$jscript,$loaditems,$jsextra).$crumb);
1.8 raeburn 632: &print_request_form($r,$action,$state,$page,$states,$dom);
1.2 raeburn 633: } elsif ($action eq 'view') {
1.16 raeburn 634: my $jsextra;
635: my $formname = 'requestcrs';
636: my $prev = $states->{$action}[$page-1];
637: my $next = $states->{$action}[$page+1];
638: if ($state eq 'pick_request') {
639: $next = $states->{$action}[$page+1];
640: $jsextra = &viewrequest_javascript($formname,$next);
641: } elsif ($state eq 'details') {
642: $jsextra = &viewdetails_javascript($formname);
643:
644: } elsif ($state eq 'cancel') {
645: $jsextra = &viewcancel_javascript($formname);
646: }
647: $r->print(&header('Manage course requests',$js.$jscript.$jsextra,$loaditems).
648: $crumb);
649: my $form = '<form method="post" name="'.$formname.'" action="/adm/requestcourse" />';
1.11 raeburn 650: if ($state eq 'pick_request') {
1.16 raeburn 651: $r->print('<h3>'.&mt('Pending course requests').'</h3><div>'."\n".$form."\n".
652: &print_request_status($dom).'</form>');
653: } elsif ($state eq 'details') {
654: my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
655: my $origcnum = $env{'form.cnum'};
656: if ($origcnum eq '') {
657: $origcnum = $env{'form.origcnum'};
658: }
659: if ($env{'form.crstype'} eq 'official') {
660: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
661: \%cat_order,\@code_order);
662: }
663: $r->print('<h3>'.&mt('Course Request Details').'</h3><div>'."\n".$form."\n".
664: &print_review($formname,$dom,\@codetitles,\%cat_titles,\%cat_order,
665: \@code_order)."\n".
666: '<input name="origcnum" value="'.$origcnum.'" type="hidden" />'."\n");
667: my @excluded = &get_excluded_elements($dom,$states,'new','review');
668: push(@excluded,'origcnum');
669: $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</div>');
670: my $other = 'modify';
671: my %navtxt = &Apache::lonlocal::texthash (
672: prev => 'Back',
673: other => 'Modify Request',
674: next => 'Cancel Request',
675: );
676: &display_navbuttons($r,$formname,$prev,$navtxt{'prev'},$next,$navtxt{'next'},
677: $state,$other,$navtxt{'other'});
678: $r->print('</form>');
679: } elsif ($state eq 'cancel') {
680: my ($result,$output) = &print_cancel_request($dom,$env{'form.origcnum'});
681: $r->print('<h3>'.&mt('Cancel course request').'</h3><div>'."\n".$form."\n".
682: $output);
683: my @excluded = &get_excluded_elements($dom,$states,'view','cancel');
684: $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</div>');
685: my %navtxt = &Apache::lonlocal::texthash (
686: prev => 'Back',
687: next => 'Confirm Cancellation',
688: );
689: if ($result eq 'ok') {
690: &display_navbuttons($r,$formname,$prev,$navtxt{'prev'},$next,
691: $navtxt{'next'},$state);
692: } else {
693: &display_navbuttons($r,$formname,$prev,$navtxt{'prev'},undef,'',$state);
694: }
695: $r->print('</form>');
696: } elsif ($state eq 'removal') {
697: my $cnum = $env{'form.origcnum'};
698: my $statuskey = 'status:'.$dom.':'.$cnum;
699: my %userreqhash = &Apache::lonnet::get('courserequests',[$statuskey],
700: $env{'user.domain'},$env{'user.name'});
701: my $currstatus = $userreqhash{$statuskey};
702: my ($result,$error);
703: if (($currstatus eq 'approval') || ($currstatus eq 'pending')) {
704: my %status = (
705: $statuskey => 'cancelled',
706: );
707: my $statusresult = &Apache::lonnet::put('courserequests',\%status);
708: if ($statusresult eq 'ok') {
709: my $delresult =
710: &Apache::lonnet::del_dom('courserequestqueue',
711: [$cnum.'_'.$currstatus],$dom);
712: if ($delresult eq 'ok') {
713: $result = 'ok';
714: } else {
715: $error = &mt('An error occurred when updating the pending requests queue: [_1]',$delresult);
716: }
717: } else {
718: $error = &mt("An error occurred when updating the status of this request in the requestor's records: [_1]",$statusresult);
719: }
720: } else {
721: $error = &mt('The current status of this request could not be verified as pending approval/institutional action.');
722: }
723: $r->print('<h3>'.&mt('Request Cancellation').'</h3><div>'."\n".$form."\n".
724: '<input type="hidden" name="state" value="'.$state.'" />'."\n".
725: '<input type="hidden" name="action" value="'.$action.'" />'."\n".
726: '<input type="hidden" name="showdom" value="'.$dom.'" />'."\n".
727: '<input type="hidden" name="orignum" value="'.$cnum.'" />'."\n");
728: if ($result eq 'ok') {
729: $r->print(&mt('Your course request has been cancelled.'));
730: } else {
731: $r->print('<div class="LC_error">'.
732: &mt('The request cancellation process was not complete.').
733: '<br />'.$error.'</div>');
734: }
735: $r->print('</form>');
1.11 raeburn 736: }
1.1 raeburn 737: } elsif ($action eq 'log') {
1.11 raeburn 738: $r->print(&coursereq_log('View request log',$jscript,$loaditems).$crumb);
1.1 raeburn 739: }
1.2 raeburn 740: $r->print(&Apache::loncommon::end_page());
1.1 raeburn 741: return;
742: }
743:
744: sub print_request_form {
1.2 raeburn 745: my ($r,$action,$state,$page,$states,$dom) = @_;
1.1 raeburn 746: my $formname = 'requestcrs';
1.2 raeburn 747: my ($next,$prev,$message,$output,$codepicker,$crstype);
748: $prev = $states->{$action}[$page-1];
749: $next = $states->{$action}[$page+1];
1.4 raeburn 750: my %navtxt = &Apache::lonlocal::texthash (
1.10 raeburn 751: prev => 'Back',
1.4 raeburn 752: next => 'Next',
753: );
1.2 raeburn 754: $crstype = $env{'form.crstype'};
1.1 raeburn 755: $r->print('<form name="'.$formname.'" method="post" action="/adm/requestcourse">');
1.2 raeburn 756: my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
1.1 raeburn 757: if ($crstype eq 'official') {
1.2 raeburn 758: if ($env{'form.instcode'} ne '') {
759: $instcode = $env{'form.instcode'};
760: }
761: }
762: if ($prev eq 'codepick') {
1.4 raeburn 763: if ($crstype eq 'official') {
764: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
765: \%cat_order,\@code_order);
766: }
1.2 raeburn 767: if (@code_order > 0) {
768: my $message;
769: if ($instcode eq '') {
1.1 raeburn 770: foreach my $item (@code_order) {
1.2 raeburn 771: $instcode .= $env{'form.instcode_'.$item};
1.1 raeburn 772: }
1.2 raeburn 773: $r->print('<input type="hidden" name="instcode" value="'.$instcode.'" />'."\n");
1.1 raeburn 774: }
775: if ($instcode ne '') {
1.2 raeburn 776: $code_chk = &Apache::lonnet::auto_validate_instcode('',$dom,$instcode);
1.17 raeburn 777: if ($code_chk eq 'valid') {
1.1 raeburn 778: $message = '<div class="LC_info">'.
779: &mt('The chosen course category [_1] is valid.','<b>'.
1.2 raeburn 780: $instcode.'</b>').'</div>';
1.1 raeburn 781: } else {
782: $message = '<div class="LC_warning">'.
783: &mt('No course was found matching your choice of institutional course category.');
784: if ($code_chk ne '') {
785: $message .= '<br />'.$code_chk;
786: }
787: $message .= '</div>';
788: }
1.2 raeburn 789: } else {
790: $message = '<div class="LC_warning">'.
791: &mt('No course was found matching your choice of institutional course category.');
1.1 raeburn 792: }
1.21 raeburn 793: unless ($code_chk eq 'valid') {
1.2 raeburn 794: $prev = 'crstype';
795: }
796: $r->print($message);
1.1 raeburn 797: }
1.2 raeburn 798: }
799: if ($prev eq 'crstype') {
1.4 raeburn 800: if ($crstype eq 'official') {
801: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
802: \%cat_order,\@code_order);
803: }
1.2 raeburn 804: if (@code_order > 0) {
1.1 raeburn 805: $codepicker = &coursecode_form($dom,'instcode',\@codetitles,
806: \%cat_titles,\%cat_order);
1.2 raeburn 807: if ($codepicker) {
808: $r->print('<div>'.&Apache::lonhtmlcommon::start_pick_box().$codepicker.
809: &Apache::lonhtmlcommon::end_pick_box().'</div>');
810: } else {
1.20 raeburn 811: $next = $states->{$action}[$page+2];
1.15 raeburn 812: $r->print(&courseinfo_form($dom,$formname,$crstype,$next));
1.2 raeburn 813: }
814: } else {
1.20 raeburn 815: if ($crstype eq 'official') {
816: $next = $states->{$action}[$page+2];
817: }
1.15 raeburn 818: $r->print(&courseinfo_form($dom,$formname,$crstype,$next));
1.1 raeburn 819: }
1.2 raeburn 820: } elsif ($prev eq 'codepick') {
1.20 raeburn 821: if ($env{'form.instcode'} eq '') {
822: $prev = $states->{$action}[$page-2];
823: }
1.15 raeburn 824: $r->print(&courseinfo_form($dom,$formname,$crstype,$next));
1.2 raeburn 825: } elsif ($state eq 'enrollment') {
1.4 raeburn 826: if ($crstype eq 'official') {
827: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
828: \%cat_order,\@code_order);
829: }
1.2 raeburn 830: $r->print(&print_enrollment_menu($formname,$instcode,$dom,\@codetitles,
831: \%cat_titles,\%cat_order,\@code_order));
832: } elsif ($state eq 'personnel') {
1.8 raeburn 833: $r->print(&print_personnel_menu($dom,$formname,$crstype));
1.4 raeburn 834: } elsif ($state eq 'review') {
1.16 raeburn 835: my $cnum;
836: if ($env{'form.origcnum'} =~ /^($match_courseid)$/) {
837: $cnum = $env{'form.origcnum'};
838: } else {
839: $cnum = &Apache::lonnet::generate_coursenum($dom);
840: }
1.4 raeburn 841: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
842: \%cat_order,\@code_order);
1.16 raeburn 843: $r->print('<p>'.&mt('Review the details of the course request before submission.').'</p>'.
844: &print_review($formname,$dom,\@codetitles,\%cat_titles,\%cat_order,
845: \@code_order).
846: '<input type="hidden" name="cnum" value="'.$cnum.'" />');
1.4 raeburn 847: $navtxt{'next'} = &mt('Submit course request');
1.10 raeburn 848: } elsif ($state eq 'process') {
849: if ($crstype eq 'official') {
850: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
851: \%cat_order,\@code_order);
852: }
853: my $result = &print_request_outcome($dom,\@codetitles,\@code_order);
1.13 raeburn 854: $r->print($result);
1.1 raeburn 855: }
1.16 raeburn 856: my @excluded = &get_excluded_elements($dom,$states,$action,$state);
1.24 ! raeburn 857: if ($state eq 'personnel') {
! 858: push(@excluded,'persontotal');
! 859: }
1.16 raeburn 860: $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</form>');
861: &display_navbuttons($r,$formname,$prev,$navtxt{'prev'},$next,$navtxt{'next'},$state);
862: return;
863: }
864:
865: sub get_excluded_elements {
866: my ($dom,$states,$action,$state) = @_;
1.2 raeburn 867: my @excluded = ('counter');
868: my %elements = &form_elements($dom);
869: if (ref($states) eq 'HASH') {
870: if (ref($states->{$action}) eq 'ARRAY') {
871: my @items = @{$states->{$action}};
872: my $numitems = scalar(@items);
873: if ($numitems) {
874: for (my $i=$numitems-1; $i>=0; $i--) {
875: if (ref($elements{$action}) eq 'HASH') {
876: if (ref($elements{$action}{$items[$i]}) eq 'HASH') {
1.16 raeburn 877: foreach my $key (keys(%{$elements{$action}{$items[$i]}})) {
1.2 raeburn 878: push(@excluded,$key);
879: }
880: }
881: }
882: last if ($items[$i] eq $state);
883: }
884: }
885: }
886: }
887: if (grep(/^instcode_/,@excluded)) {
888: push(@excluded,'instcode');
1.1 raeburn 889: }
1.16 raeburn 890: return @excluded;
1.1 raeburn 891: }
892:
1.2 raeburn 893: sub print_enrollment_menu {
894: my ($formname,$instcode,$dom,$codetitles,$cat_titles,$cat_order,$code_order) =@_;
895: my ($sections,$autoenroll,$access_dates);
896: my $starttime = time;
897: my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
898:
899: my %accesstitles = (
900: 'start' => 'Default start access',
1.16 raeburn 901: 'end' => 'Default end access',
1.2 raeburn 902: );
903: my %enrolltitles = (
904: 'start' => 'Start auto-enrollment',
905: 'end' => 'End auto-enrollment',
906: );
907: if ($env{'form.crstype'} eq 'official') {
908: if (&Apache::lonnet::auto_run('',$dom)) {
909: my ($section_form,$crosslist_form,$autoenroll_form);
910: $section_form = &inst_section_selector($dom,$instcode);
911: my $crosslisttotal = $env{'form.crosslisttotal'};
1.24 ! raeburn 912: if (!$crosslisttotal) {
1.2 raeburn 913: $crosslisttotal = 1;
914: }
915: if ($env{'form.addcrosslist'}) {
916: $crosslisttotal ++;
917: }
918: for (my $i=0; $i<$crosslisttotal; $i++) {
919: $crosslist_form .= &coursecode_form($dom,'crosslist',$codetitles,
920: $cat_titles,$cat_order,$i);
921: }
922: if ($crosslist_form) {
923: $crosslist_form .=
924: &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
925: '<input name="crosslisttotal" type="hidden" value="'.$crosslisttotal.'" />'.
926: '<input name="addcrosslist" type="checkbox" value="'.$crosslisttotal.'"'.
927: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
928: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1);
929: }
930: if ($section_form || $crosslist_form) {
931: $sections = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
932: $section_form.$crosslist_form.
933: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
934: }
935: $autoenroll_form =
936: &Apache::lonhtmlcommon::row_title(&mt('Add registered students automatically')).
937: '<span class="LC_nobreak"><label>'.
938: '<input type="radio" name="autoadds" value="1">'.
939: &mt('Yes').'</label>'.(' 'x3).'<label>'.
940: '<input type="radio" name="autoadds" value="0" checked="checked">'.
941: &mt('No').'</label></span>'.
942: &Apache::lonhtmlcommon::row_closure().
943: &Apache::lonhtmlcommon::row_title(&mt('Drop unregistered students automatically')).
944: '<span class="LC_nobreak"><label>'.
945: '<input type="radio" name="autodrops" value="1">'.
946: &mt('Yes').'</label>'.(' 'x3).'<label>'.
947: '<input type="radio" name="autodrops" value="0" checked="checked">'.
948: &mt('No').'</label></span>'.
949: &Apache::lonhtmlcommon::row_closure().
950: &date_setting_table($starttime,$endtime,$formname,'enroll',%enrolltitles);
951: if ($autoenroll_form) {
952: $autoenroll = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
953: $autoenroll_form.
954: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
955: }
956: }
957: }
958: my $access_dates_form =
959: &date_setting_table($starttime,$endtime,$formname,'access',%accesstitles);
960: if ($access_dates_form) {
961: $access_dates = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
962: $access_dates_form.
963: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
964: }
965: return $sections.$autoenroll.$access_dates;
966: }
967:
1.1 raeburn 968: sub inst_section_selector {
1.2 raeburn 969: my ($dom,$instcode) = @_;
970: my @sections = &Apache::lonnet::auto_get_sections(undef,$dom,$instcode);
971: my $sectotal = scalar(@sections);
1.1 raeburn 972: my $output;
1.2 raeburn 973: if ($sectotal) {
974: $output .= &Apache::lonhtmlcommon::row_title('Sections').
975: &Apache::loncommon::start_data_table().
976: &Apache::loncommon::start_data_table_row().
977: '<th>'.&mt('Include?').'<input type="hidden" name="sectotal" '.
1.24 ! raeburn 978: 'value="'.$sectotal.'" /></th>'.
1.2 raeburn 979: '<th>'.&mt('Institutional Section').'</th>'.
980: '<th>'.&mt('LON-CAPA section').'</th>'.
981: &Apache::loncommon::end_data_table_row();
982: for (my $i=0; $i<@sections; $i++) {
1.1 raeburn 983: my $colflag = $i%2;
1.24 ! raeburn 984: my $checked = ' checked="checked"';
! 985: if ($env{'form.origcnum'}) {
! 986: $checked='';
! 987: }
1.1 raeburn 988: $output .= &Apache::loncommon::start_data_table_row().
1.2 raeburn 989: '<td><input type="checkbox" name="sec_'.$i.
1.24 ! raeburn 990: '"'.$checked.' value="1" /></td>'.
1.2 raeburn 991: '<td>'.$sections[$i].
1.1 raeburn 992: '<input type="hidden" name="secnum_'.$i.'" value="'.
1.2 raeburn 993: $sections[$i].'" /></td>'.
1.1 raeburn 994: '<td><input type="text" size="10" name="loncapasec_'.$i.
1.2 raeburn 995: '" value="'.$sections[$i].'" /></td>'.
1.1 raeburn 996: &Apache::loncommon::end_data_table_row();
997: }
1.2 raeburn 998: $output .= &Apache::loncommon::end_data_table().
999: &Apache::lonhtmlcommon::row_closure();
1.1 raeburn 1000: }
1001: return $output;
1002: }
1003:
1.2 raeburn 1004: sub date_setting_table {
1.14 raeburn 1005: my ($starttime,$endtime,$formname,$prefix,%datetitles) = @_;
1.2 raeburn 1006: my ($perpetual,$table);
1.14 raeburn 1007: my $startform = &Apache::lonhtmlcommon::date_setter($formname,$prefix.'start',
1.2 raeburn 1008: $starttime,'','','',1,'','','',1);
1.14 raeburn 1009: my $endform = &Apache::lonhtmlcommon::date_setter($formname,$prefix.'end',
1.2 raeburn 1010: $endtime,'','','',1,'','','',1);
1.14 raeburn 1011: if ($prefix eq 'access') {
1.2 raeburn 1012: $perpetual = ' <span class="LC_nobreak"><label>'.
1013: '<input type="checkbox" name="no_end_date" />'.
1014: &mt('No end date').'</label></span>';
1015: }
1016: $table = &Apache::lonhtmlcommon::row_title($datetitles{'start'}).
1017: $startform.
1018: &Apache::lonhtmlcommon::row_closure().
1019: &Apache::lonhtmlcommon::row_title($datetitles{'end'}).
1020: $endform.$perpetual.
1021: &Apache::lonhtmlcommon::row_closure(1);
1022: return $table;
1023: }
1024:
1025: sub print_personnel_menu {
1.8 raeburn 1026: my ($dom,$formname,$crstype) = @_;
1.2 raeburn 1027: my $output = '<div>'.&Apache::lonhtmlcommon::start_pick_box();
1028: my $persontotal = $env{'form.persontotal'};
1.16 raeburn 1029: if ((!defined($persontotal)) || (!$persontotal)) {
1.2 raeburn 1030: $persontotal = 1;
1031: }
1032: if ($env{'form.addperson'}) {
1033: $persontotal ++;
1034: }
1035: my $userlinktxt = &mt('Set User');
1.13 raeburn 1036: my @items = ('uname','dom','lastname','firstname','emailaddr','hidedom');
1.2 raeburn 1037:
1038: my $roleoptions;
1039: my @roles = &Apache::lonuserutils::roles_by_context('course');
1.8 raeburn 1040: my $type = 'Course';
1041: if ($crstype eq 'community') {
1042: $type = 'Community';
1043: }
1.2 raeburn 1044: foreach my $role (@roles) {
1.8 raeburn 1045: my $plrole=&Apache::lonnet::plaintext($role,$type);
1.2 raeburn 1046: $roleoptions .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
1047: }
1048: my %customroles=&Apache::lonuserutils::my_custom_roles();
1049: if (keys(%customroles) > 0) {
1050: foreach my $cust (sort(keys(%customroles))) {
1051: my $custrole='cr_cr_'.$env{'user.domain'}.
1052: '_'.$env{'user.name'}.'_'.$cust;
1053: $roleoptions .= ' <option value="'.$custrole.'">'.$cust.'</option>'."\n";
1054: }
1055: }
1056:
1057: my @currsecs;
1058: if ($env{'form.sectotal'}) {
1059: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
1060: if (defined($env{'form.loncapasec_'.$i})) {
1061: my $lcsec = $env{'form.loncapasec_'.$i};
1062: unless (grep(/^\Q$lcsec\E$/,@currsecs)) {
1063: push(@currsecs,$lcsec);
1064: }
1065: }
1066: }
1067: }
1068:
1069: my ($existtitle,$existops,$existmult,$newtitle,$seccolspan);
1070: if (@currsecs) {
1071: my $existsize = scalar(@currsecs);
1072: if ($existsize > 3) {
1073: $existsize = 3;
1074: }
1075: if ($existsize > 1) {
1076: $existmult = ' multiple="multiple" size="'.$existsize.'" ';
1077: }
1078: @currsecs = sort { $a <=> $b } (@currsecs);
1079: $existtitle = &mt('Official').': ';
1080: $existops = '<option value="">'.&mt('None').'</option>';
1081: foreach my $sec (@currsecs) {
1082: $existops .= '<option value="'.$sec.'">'.$sec.'</option>'."\n";
1083: }
1084: $seccolspan = ' colspan="2"';
1085: $newtitle = &mt('Other').': ';
1086: }
1087:
1088: for (my $i=0; $i<$persontotal; $i++) {
1089: my @linkargs = map { 'person_'.$i.'_'.$_ } (@items);
1090: my $linkargstr = join("','",@linkargs);
1.7 raeburn 1091: my $userlink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,$userlinktxt);
1.2 raeburn 1092: my $uname_form = '<input type="text" name="person_'.$i.'_uname" value=""'.
1093: ' onFocus="this.blur();'.
1.7 raeburn 1094: 'openuserbrowser('."'$formname','$linkargstr','$dom'".');" />';
1.2 raeburn 1095: my $onchange = 'javascript:fix_domain('."'$formname','person_".$i."_dom',".
1096: "'person_".$i."_hidedom'".');'.
1.7 raeburn 1097: 'openuserbrowser('."'$formname','$linkargstr','$dom'".');';
1.2 raeburn 1098: my $udom_form = &Apache::loncommon::select_dom_form($dom,'person_'.$i.'_dom','',
1099: 1,$onchange).
1100: '<input type="hidden" name="person_'.$i.'_hidedom" value="'.$dom.'" />';
1101: my %form_elems;
1102: foreach my $item (@items) {
1103: next if (($item eq 'dom') || ($item eq 'uname') || ($item eq 'hidedom'));
1104: $form_elems{$item} = '<input type="text" name="person_'.$i.'_'.$item.'" '.
1105: 'value="" readonly="readonly" />';
1106: }
1107: my $roleselector = '<select name="person_'.$i.'_role">'."\n".
1108: $roleoptions.'</select>';
1109: my $sectionselector;
1110: if (@currsecs) {
1111: $sectionselector = $existtitle.'<select name="person_'.$i.'_sec"'.
1112: $existmult.'>'."\n".$existops.'</select>'.(' ' x3);
1113: }
1114: $sectionselector .= $newtitle.
1.14 raeburn 1115: '<input type="text" name="person_'.$i.'_newsec" size="15" value="" />'."\n";
1.2 raeburn 1116: $output .=
1117: &Apache::lonhtmlcommon::row_title(&mt('Additional Personnel').'<br />'.
1118: '<span class="LC_nobreak">'.$userlink.
1119: '</span>').
1120: '<table><tr><td align="center" valign="top">'.&mt('Username').'<br />'.$uname_form.'</td>'."\n".
1121: '<td align="center" valign="top" colspan="2">'.&mt('Domain').'<br />'.$udom_form.'</td></tr><tr>'."\n".
1.13 raeburn 1122: '<td align="center" valign="top">'.&mt('First Name').'<br />'.$form_elems{'firstname'}.'</td>'."\n".
1123: '<td align="center" valign="top">'.&mt('Last Name').'<br />'.$form_elems{'lastname'}.'</td>'."\n".
1124: '<td align="center" valign="top">'.&mt('E-mail').'<br />'.$form_elems{'emailaddr'}.'</td></tr>'."\n".
1.2 raeburn 1125: '<tr><td align="center" valign="top">'.&mt('Role').'<br />'.$roleselector.'</td>'."\n".
1126: '<td'.$seccolspan.' align="center" valign="top">'.&mt('Section(s)').'<br />'.$sectionselector.'</td>'."\n".
1127: '</tr></table>'.&Apache::lonhtmlcommon::row_closure();
1128: }
1129: $output .= &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
1130: '<input name="persontotal" type="hidden" value="'.$persontotal.'" />'.
1131: '<input name="addperson" type="checkbox" value="'.$persontotal.'"'.
1132: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
1133: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1).
1134: &Apache::lonhtmlcommon::end_pick_box().'</div>';
1135: return $output;
1136: }
1137:
1.1 raeburn 1138: sub print_request_status {
1.11 raeburn 1139: my ($dom) = @_;
1.14 raeburn 1140: my %statusinfo = &Apache::lonnet::dump('courserequests',$env{'user.domain'},
1141: $env{'user.name'},'^status:'.$dom);
1142: my ($output,$formname,%queue_by_date,%typenames);
1143: if ($env{'form.crstype'} eq 'any') {
1144: %typenames = &Apache::lonlocal::texthash (
1145: official => 'Official course',
1146: unofficial => 'Unofficial course',
1147: community => 'Community',
1148: );
1149: }
1150: foreach my $key (keys(%statusinfo)) {
1151: if (($statusinfo{$key} eq 'approval') || ($statusinfo{$key} eq 'pending')) {
1152: (undef,my($cdom,$cnum)) = split(':',$key);
1153: next if ($cdom ne $dom);
1154: my $requestkey = $cdom.'_'.$cnum;
1155: if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
1156: my %history = &Apache::lonnet::restore($requestkey,'courserequests',
1157: $env{'user.domain'},$env{'user.name'});
1158: my $entry;
1159: my $timestamp = $history{'reqtime'};
1160: my $crstype = $history{'crstype'};
1161: my $disposition = $history{'disposition'};
1162: next if ((exists($history{'status'})) && ($history{'status'} eq 'created'));
1163: next unless (($env{'form.crstype'} eq 'any') ||
1164: ($env{'form.crstype'} eq $crstype));
1165: next unless (($disposition eq 'approval') ||
1166: ($disposition eq 'pending'));
1167: if (ref($history{'details'}) eq 'HASH') {
1168: $entry = $requestkey.':'.$crstype.':'.
1169: &escape($history{'details'}{'cdescr'});
1170: if ($crstype eq 'official') {
1171: $entry .= ':'.&escape($history{'details'}{'instcode'});
1172: }
1173: }
1174: if ($entry ne '') {
1175: if (exists($queue_by_date{$timestamp})) {
1176: if (ref($queue_by_date{$timestamp}) eq 'ARRAY') {
1177: push(@{$queue_by_date{$timestamp}},$entry);
1178: }
1179: } else {
1180: @{$queue_by_date{$timestamp}} = ($entry);
1.10 raeburn 1181: }
1182: }
1183: }
1184: }
1185: }
1.11 raeburn 1186: $formname = 'requestcrs';
1.10 raeburn 1187: my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date));
1.16 raeburn 1188: $output = '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
1189:
1.10 raeburn 1190: '<input type="hidden" name="state" value="'.$env{'form.state'}.'" />'."\n".
1.16 raeburn 1191: '<input type="hidden" name="crstype" value="'.$env{'form.crstype'}.'" />'."\n".
1192: '<input type="hidden" name="showdom" value="" />'."\n".
1193: '<input type="hidden" name="cnum" value="" />'."\n";
1.10 raeburn 1194: if (@sortedtimes > 0) {
1195: $output .= &Apache::loncommon::start_data_table().
1196: &Apache::loncommon::start_data_table_header_row().
1197: '<th>'.&mt('Action').'</th>'.
1.14 raeburn 1198: '<th>'.&mt('Course Description').'</th>'.
1199: '<th>'.&mt('Domain').'</th>';
1200: if ($env{'form.crstype'} eq 'any') {
1.10 raeburn 1201: $output .= '<th>'.&mt('Type').'</th>';
1202: }
1.14 raeburn 1203: if (($env{'form.crstype'} eq 'any') || ($env{'form.crstype'} eq 'official')) {
1.10 raeburn 1204: $output .= '<th>'.&mt('Institutional Code').'</th>';
1205: }
1206: $output .= '<th>'.&mt('Date requested').'</th>'.
1207: &Apache::loncommon::end_data_table_header_row();
1208: my $count = 0;
1209: foreach my $item (@sortedtimes) {
1210: my $showtime = &Apache::lonlocal::locallocaltime($item);
1211: if (ref($queue_by_date{$item}) eq 'ARRAY') {
1212: foreach my $request (sort(@{$queue_by_date{$item}})) {
1213: my ($key,$type,$desc,$instcode) = split(':',$request);
1214: my ($cdom,$cnum) = split('_',$key);
1215: $output .= &Apache::loncommon::start_data_table_row().
1.16 raeburn 1216: '<td><input type="button" value="'.&mt('Select').'" onclick="javascript:chooseRequest('."'$cdom','$cnum'".')" /></td>'.
1.14 raeburn 1217: '<td>'.&unescape($desc).'</td>'.
1218: '<td>'.$cdom.'</td>';
1219: if ($env{'form.crstype'} eq 'any') {
1220: my $typename = $typenames{$type};
1221: if ($typename eq '') {
1222: $typename = &mt('Unknown type');
1223: }
1224: $output .= '<td>'.$typename.'</td>';
1.10 raeburn 1225: }
1.14 raeburn 1226: if (($env{'form.crstype'} eq 'any') ||
1.10 raeburn 1227: ($env{'form.crstype'} eq 'official')) {
1.14 raeburn 1228: my $showinstcode;
1229: if ($type eq 'official') {
1230: $showinstcode = &unescape($instcode);
1231: } else {
1232: $showinstcode = &mt('Not applicable');
1233: }
1234: $output .= '<td>'.$showinstcode.'</td>';
1.10 raeburn 1235: }
1236: $output .= '<td>'.$showtime.'</td>'.
1237: &Apache::loncommon::end_data_table_row();
1238: }
1239: }
1240: }
1241: $output .= &Apache::loncommon::end_data_table();
1242: } else {
1.11 raeburn 1243: $output .= '<div>'.&mt('You have no matching course requests awaiting approval by a Domain Coordinator or held in a queue pending administrative action at your institution.').'</div>';
1.10 raeburn 1244: }
1245: $output .= '
1.14 raeburn 1246: <br /><input type="button" name="prev" value="'.&mt('Back').'" onclick="javascript:backPage(document.'.$formname.",'crstype'".')" />
1247: </form></div>';
1.10 raeburn 1248: return $output;
1.1 raeburn 1249: }
1250:
1.16 raeburn 1251: sub print_cancel_request {
1252: my ($dom,$cnum) = @_;
1253: my $requestkey = $dom.'_'.$cnum;
1254: my ($result,$output);
1255: if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
1256: my %history = &Apache::lonnet::restore($requestkey,'courserequests',
1257: $env{'user.domain'},$env{'user.name'});
1258: my $timestamp = $history{'reqtime'};
1259: my $crstype = $history{'crstype'};
1260: my $status = $history{'status'};
1261: if (($status eq 'cancelled') || ($status eq 'created')) {
1262: if ($status eq 'cancelled') {
1263: $output = &mt('This request has already been cancelled.');
1264: } elsif ($status eq 'created') {
1265: $output = &mt('This request has already been processed, and a course created.');
1266: }
1267: $output = &mt('No further action will be taken');
1268: } elsif (ref($history{'details'}) eq 'HASH') {
1269: my ($types,$typename) = &course_types();
1270: my $showtype = $crstype;
1271: if (defined($typename->{$crstype})) {
1272: $showtype = $typename->{$crstype};
1273: }
1274: $output = '<p>'.&Apache::loncommon::start_data_table().
1275: &Apache::loncommon::start_data_table_header_row().
1276: '<th>'.&mt('Description').'</th><th>'.&mt('Requested').'</th>'.
1277: '<th>'.&mt('Type').'</th>'.
1278: &Apache::loncommon::end_data_table_header_row().
1279: &Apache::loncommon::start_data_table_row().
1280: '<td>'.$history{details}{'cdescr'}.'</td><td>'.
1281: &Apache::lonlocal::locallocaltime($timestamp).'</td>'.
1282: '<td>'.$showtype.'</td>'.
1283: &Apache::loncommon::end_data_table_row().
1284: &Apache::loncommon::end_data_table().
1285: '<br /><div class="LC_warning">'.
1286: &mt('Cancelling the request will remove it from the queue of pending course requests').'</div>';
1287: $result = 'ok';
1288: } else {
1289: $output = '<div class="LC_error">'.&mt('No record exists for the course ID').'</div>';
1290: }
1291: } else {
1292: $output = '<div class="LC_error">'.&mt('Invalid course ID').'</div>';
1293: }
1294: return ($result,$output);
1295: }
1296:
1297: sub viewrequest_javascript {
1298: my ($formname,$next) = @_;
1299: return <<"ENDJS";
1300:
1301: function chooseRequest(cdom,cnum) {
1302: document.$formname.showdom.value = cdom;
1303: document.$formname.cnum.value = cnum;
1304: nextPage(document.$formname,'$next');
1305: }
1306:
1307: ENDJS
1308: }
1309:
1310: sub viewdetails_javascript {
1311: my ($formname) = @_;
1312: return << "ENDJS";
1313:
1314: function nextPage(formname,nextstate) {
1315: if (nextstate == "modify") {
1316: formname.state.value = "personnel";
1317: formname.action.value = "new";
1318: } else {
1319: formname.state.value = nextstate;
1320: }
1321: formname.submit();
1322: }
1323:
1324: function backPage(formname,prevstate) {
1325: formname.state.value = prevstate;
1326: formname.submit();
1327: }
1328:
1329: ENDJS
1330: }
1331:
1332: sub viewcancel_javascript {
1333: my $alert = &mt('Are you sure you want to cancel this request?\\n'.
1334: 'Your request will be removed.');
1335: return << "ENDJS";
1336: function nextPage(formname,nextstate) {
1337: if (confirm('$alert')) {
1338: formname.state.value = nextstate;
1339: formname.submit();
1340: }
1341: return;
1342: }
1343:
1344: ENDJS
1345: }
1346:
1.1 raeburn 1347: sub print_request_logs {
1.10 raeburn 1348: my ($jscript,$loaditems,$crumb) = @_;
1.1 raeburn 1349: return;
1350: }
1351:
1352: sub print_review {
1.4 raeburn 1353: my ($formname,$dom,$codetitles,$cat_titles,$cat_order,$code_order) = @_;
1354: my ($types,$typename) = &course_types();
1355: my ($owner,$ownername,$owneremail);
1356: $owner = $env{'user.name'}.':'.$env{'user.domain'};
1357: $ownername = &Apache::loncommon::plainname($env{'user.name'},
1358: $env{'user.domain'},'first');
1359: my %emails = &Apache::loncommon::getemails();
1360: foreach my $email ('permanentemail','critnotification','notification') {
1361: $owneremail = $emails{$email};
1362: last if ($owneremail ne '');
1363: }
1364: my ($inst_headers,$inst_values,$crstypename,$enroll_headers,$enroll_values,
1365: $section_headers,$section_values,$personnel_headers,$personnel_values);
1366:
1367: $crstypename = $env{'form.crstype'};
1368: if (ref($typename) eq 'HASH') {
1369: unless ($typename->{$env{'form.crstype'}} eq '') {
1370: $crstypename = $typename->{$env{'form.crstype'}};
1371: }
1372: }
1.16 raeburn 1373: my $category = 'Course';
1374: if ($env{'form.crstype'} eq 'community') {
1375: $category = 'Community';
1376: }
1.4 raeburn 1377:
1378: $inst_headers = '<th>'.&mt('Description').'</th><th>'.&mt('Type').'</th>';
1379: $inst_values = '<td>'.$env{'form.cdescr'}.'</td><td>'.$crstypename.'</td>';
1380:
1.16 raeburn 1381: my $enrollrow_title = &mt('Default Access Dates').'<br />'.
1382: '('.&Apache::lonnet::plaintext('st',$category).')';
1.4 raeburn 1383: if ($env{'form.crstype'} eq 'official') {
1384: if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH')) {
1385: foreach my $title (@{$codetitles}) {
1386: if ($env{'form.instcode_'.$title} ne '') {
1387: $inst_headers .= '<th>'.$title.'</th>';
1388: my $longitem = $env{'form.instcode_'.$title};
1389: if (ref($cat_titles->{$title}) eq 'HASH') {
1390: if ($cat_titles->{$title}{$env{'form.instcode_'.$title}} ne '') {
1391: $longitem = $cat_titles->{$title}{$env{'form.instcode_'.$title}};
1392: }
1393: }
1394: $inst_values .= '<td>'.$longitem.'</td>';
1395: }
1396: }
1397: }
1398: if (&Apache::lonnet::auto_run('',$dom)) {
1.16 raeburn 1399: $enrollrow_title = &mt('Enrollment');
1.4 raeburn 1400: $enroll_headers = '<th>'.&mt('Automatic Adds').'</th>'.
1401: '<th>'.&mt('Automatic Drops').'</th>'.
1402: '<th>'.&mt('Enrollment Starts').'</th>'.
1403: '<th>'.&mt('Enrollment Ends').'</th>';
1404: $section_headers = '<th>'.&mt('Sections').'</th>'.
1405: '<th>'.&mt('Crosslistings').'</th>';
1406:
1.13 raeburn 1407: my ($enrollstart,$enrollend) = &dates_from_form('enrollstart','enrollend');
1.4 raeburn 1408: my @autoroster = (&mt('No'),&mt('Yes'));
1409: $enroll_values = '<td>'.$autoroster[$env{'form.autoadds'}].'</td>'.
1410: '<td>'.$autoroster[$env{'form.autodrops'}].'</td>'.
1.13 raeburn 1411: '<td>'.&Apache::lonlocal::locallocaltime($enrollstart).'</td>'.
1412: '<td>'.&Apache::lonlocal::locallocaltime($enrollend).'</td>';
1.6 raeburn 1413: $section_values = '<td><table class="LC_innerpickbox"><tr><th>'.
1414: &mt('Institutional section').'</th>'.
1415: '<th>'.&mt('LON-CAPA section').'</th></tr>';
1.5 raeburn 1416: my $secinfo;
1.4 raeburn 1417: if ($env{'form.sectotal'} > 0) {
1418: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
1419: if ($env{'form.sec_'.$i}) {
1.5 raeburn 1420: $secinfo .= '<tr><td>'.$env{'form.secnum_'.$i}.'</td><td>';
1.4 raeburn 1421: if ($env{'form.loncapasec_'.$i} ne '') {
1.5 raeburn 1422: $secinfo .= $env{'form.loncapasec_'.$i};
1423: } else {
1424: $secinfo .= &mt('None');
1.4 raeburn 1425: }
1.5 raeburn 1426: $secinfo .= '</td></tr>';
1.4 raeburn 1427: }
1428: }
1429: }
1.6 raeburn 1430: if ($secinfo eq '') {
1431: $secinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
1.5 raeburn 1432: }
1.6 raeburn 1433: $section_values .= $secinfo.'</table></td><td>'.
1434: '<table class="LC_innerpickbox"><tr><th>'.
1435: &mt('Institutional course/section').'</th>'.
1436: '<th>'.&mt('LON-CAPA section').'</th></tr>';
1.5 raeburn 1437: my $xlistinfo;
1.24 ! raeburn 1438: my $crosslisttotal = $env{'form.crosslisttotal'};
! 1439: if (!$crosslisttotal) {
! 1440: $crosslisttotal = 1;
! 1441: }
! 1442: for (my $i=0; $i<$crosslisttotal; $i++) {
! 1443: if ($env{'form.crosslist_'.$i}) {
! 1444: $xlistinfo .= '<tr><td>';
! 1445: if (ref($code_order) eq 'ARRAY') {
! 1446: if (@{$code_order} > 0) {
! 1447: foreach my $item (@{$code_order}) {
! 1448: $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
1.4 raeburn 1449: }
1450: }
1451: }
1.24 ! raeburn 1452: $xlistinfo .= $env{'form.crosslist_'.$i.'_instsec'}.'</td><td>';
! 1453: if ($env{'form.crosslist_'.$i.'_lcsec'}) {
! 1454: $xlistinfo .= $env{'form.crosslist_'.$i.'_lcsec'};
! 1455: } else {
! 1456: $xlistinfo .= &mt('None');
! 1457: }
! 1458: $xlistinfo .= '</td></tr>';
1.4 raeburn 1459: }
1460: }
1.6 raeburn 1461: if ($xlistinfo eq '') {
1462: $xlistinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
1.5 raeburn 1463: }
1.24 ! raeburn 1464: $section_values .= $xlistinfo;
1.4 raeburn 1465: }
1.24 ! raeburn 1466: $section_values .= '</table></td>';
1.4 raeburn 1467: }
1468:
1469: my %ctxt = &clone_text();
1470: $inst_headers .= '<th>'.&mt('Clone From').'</th>';
1.13 raeburn 1471: if (($env{'form.clonecrs'} =~ /^$match_name$/) &&
1472: ($env{'form.clonedom'} =~ /^$match_domain$/)) {
1.15 raeburn 1473: my $canclone = &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
1474: $env{'user.domain'},$env{'form.clonecrs'}, $env{'form.clonedom'});
1475: if ($canclone) {
1476: my %courseenv = &Apache::lonnet::userenvironment($env{'form.clonedom'},
1477: $env{'form.clonecrs'},('description','internal.coursecode'));
1478: if (keys(%courseenv) > 0) {
1479: $inst_headers .= '<th>'.$ctxt{'dsh'}.'</th>';
1480: $inst_values .= '<td>'.$courseenv{'description'}.' ';
1481: my $cloneinst = $courseenv{'internal.coursecode'};
1482: if ($cloneinst ne '') {
1.18 raeburn 1483: $inst_values .= $cloneinst.' '.&mt('in').' '.$env{'form.clonedom'};
1.15 raeburn 1484: } else {
1.18 raeburn 1485: $inst_values .= &mt('from').' '.$env{'form.clonedom'};
1.15 raeburn 1486: }
1487: $inst_values .= '</td><td>';
1488: if ($env{'form.datemode'} eq 'preserve') {
1.16 raeburn 1489: $inst_values .= $ctxt{'prd'};
1.15 raeburn 1490: } elsif ($env{'form.datemode'} eq 'shift') {
1491: $inst_values .= &mt('Shift dates by [_1] days',$env{'form.dateshift'});
1492: } else {
1493: $inst_values .= $ctxt{'ncd'};
1494: }
1495: $inst_values .= '</td>';
1496: } else {
1497: $inst_values .= '<td>'.&mt('Unknown').'</td>';
1498: }
1499: } else {
1500: $inst_values .= '<td>'.&mt('Not permitted'),'</td>';
1501: }
1.4 raeburn 1502: } else {
1503: $inst_values .= '<td>'.&mt('None').'</td>';
1504: }
1505: $enroll_headers .= '<th>'.&mt('Access Starts').'</th>'.
1506: '<th>'.&mt('Access Ends').'</th>';
1.13 raeburn 1507: my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend');
1508: $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($accessstart).'</td>';
1509: if ($accessend == 0) {
1.4 raeburn 1510: $enroll_values .= '<td>'.&mt('No end date').'</td>';
1511: } else {
1.13 raeburn 1512: $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($accessend).'</td>';
1.4 raeburn 1513: }
1514:
1515: my $container = 'Course';
1516: if ($env{'form.crstype'} eq 'community') {
1517: $container = 'Community';
1518: }
1519:
1520: $personnel_headers = '<th>'.&mt('Name').'</th><th>'.&mt('Username:Domain').
1521: '</th><th>'.&mt('Role').'</th><th>'.&mt('LON-CAPA Sections').
1522: '</th>';
1523: $personnel_values .= '<tr><td>'.$ownername.'</td><td>'.$owner.'</td>'.
1524: '<td>'.&Apache::lonnet::plaintext('cc',$container).'</td>'.
1525: '<td>'.&mt('None').'</td></tr>';
1526: for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
1527: if ($env{'form.person_'.$i.'_uname'} ne '') {
1.14 raeburn 1528: my @allsecs = &Apache::loncommon::get_env_multiple('form.person_'.$i.'_sec');
1529: my $newsec = $env{'form.person_'.$i.'_newsec'};
1530: $newsec =~ s/^\s+//;
1531: $newsec =~s/\s+$//;
1532: my @newsecs = split(/[\s,;]+/,$newsec);
1533: foreach my $sec (@newsecs) {
1534: next if ($sec =~ /\W/);
1535: next if ($newsec eq 'none');
1536: if ($sec ne '') {
1537: unless (grep(/^\Q$sec\E$/,@allsecs)) {
1538: push(@allsecs,$sec);
1539: }
1540: }
1541: }
1.24 ! raeburn 1542: my $showsec;
1.14 raeburn 1543: if (@allsecs) {
1544: $showsec = join(', ',@allsecs);
1545: }
1.24 ! raeburn 1546: if ($showsec eq '') {
! 1547: $showsec = &mt('None');
! 1548: }
! 1549: if ($env{'form.person_'.$i.'_role'} eq 'cc') {
! 1550: $showsec = &mt('None');
! 1551: }
1.4 raeburn 1552: $personnel_values .=
1.13 raeburn 1553: '<tr><td>'.$env{'form.person_'.$i.'_firstname'}.' '.
1554: $env{'form.person_'.$i.'_lastname'}.'</td>'.
1.4 raeburn 1555: '<td>'.$env{'form.person_'.$i.'_uname'}.':'.
1556: $env{'form.person_'.$i.'_dom'}.'</td>'.
1557: '<td>'.&Apache::lonnet::plaintext($env{'form.person_'.$i.'_role'},
1558: $container).'</td>'.
1.14 raeburn 1559: '<td>'.$showsec.'</td></tr>';
1.4 raeburn 1560: }
1561: }
1.16 raeburn 1562: my $output =
1.4 raeburn 1563: '<div>'.&Apache::lonhtmlcommon::start_pick_box().
1564: &Apache::lonhtmlcommon::row_title(&mt('Owner')).
1.6 raeburn 1565: '<table class="LC_innerpickbox"><tr>'.
1.4 raeburn 1566: '<th>'.&mt('Name').'</th>'.
1567: '<th>'.&mt('Username:Domain').'</th>'.
1568: '<th>'.&mt('E-mail address').'</th>'.
1569: '</tr><tr>'."\n".
1570: '<td>'.$ownername.'</td><td>'.$owner.'</td>'.
1571: '<td>'.$owneremail.'</td>'.
1572: '</tr></table>'."\n".
1573: &Apache::lonhtmlcommon::row_closure().
1.5 raeburn 1574: &Apache::lonhtmlcommon::row_title(&mt('Description')).
1.4 raeburn 1575: '<table class="LC_innerpickbox"><tr>'.$inst_headers.'</tr>'."\n".
1576: '<tr>'.$inst_values.'</tr></table>'."\n".
1577: &Apache::lonhtmlcommon::row_closure().
1.16 raeburn 1578: &Apache::lonhtmlcommon::row_title($enrollrow_title).
1.4 raeburn 1579: '<table class="LC_innerpickbox"><tr>'.$enroll_headers.'</tr>'."\n".
1580: '<tr>'.$enroll_values.'</tr></table>'."\n".
1581: &Apache::lonhtmlcommon::row_closure();
1582: if ($section_headers ne '') {
1583: $output .= &Apache::lonhtmlcommon::row_title(&mt('Sections')).
1584: '<table class="LC_innerpickbox"><tr>'.$section_headers.'</tr>'."\n".
1585: '<tr>'.$section_values.'</tr></table>'."\n".
1586: &Apache::lonhtmlcommon::row_closure();
1587: }
1588: $output .= &Apache::lonhtmlcommon::row_title(&mt('Personnel')).
1589: '<table class="LC_innerpickbox"><tr>'.$personnel_headers.'</tr>'."\n".
1590: $personnel_values.'</table>'."\n".
1591: &Apache::lonhtmlcommon::row_closure(1).
1592: &Apache::lonhtmlcommon::end_pick_box();
1593: return $output;
1594: }
1595:
1596: sub dates_from_form {
1597: my ($startname,$endname) = @_;
1598: my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
1599: my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname);
1.13 raeburn 1600: if ($endname eq 'accessend') {
1.4 raeburn 1601: if (exists($env{'form.no_end_date'}) ) {
1602: $enddate = 0;
1603: }
1604: }
1605: return ($startdate,$enddate);
1.1 raeburn 1606: }
1607:
1608: sub courseinfo_form {
1.15 raeburn 1609: my ($dom,$formname,$crstype,$next) = @_;
1610: my $nodescr = &mt('You must provide a (brief) course description.');
1611: my $js_validate = <<"ENDJS";
1612: <script type="text/javascript">
1613: // <![CDATA['
1614:
1615: function validateForm() {
1616: if ((document.$formname.cdescr.value == "") || (document.$formname.cdescr.value == "undefined")) {
1617: alert('$nodescr');
1618: return;
1619: }
1620: nextPage(document.$formname,'$next');
1621: }
1622: // ]]
1623: </script>
1624:
1625: ENDJS
1626:
1627: my $output .= $js_validate."\n".'<div>'.&Apache::lonhtmlcommon::start_pick_box().
1628: &Apache::lonhtmlcommon::row_title('Course Description').
1.13 raeburn 1629: '<input type="text" size="40" name="cdescr" />';
1630: my ($home_server_pick,$numlib) =
1631: &Apache::loncommon::home_server_form_item($dom,'chome',
1632: 'default','hide');
1633: if ($numlib > 1) {
1634: $output .= &Apache::lonhtmlcommon::row_closure().
1.16 raeburn 1635: &Apache::lonhtmlcommon::row_title(&mt('Home Server for Course'));
1.13 raeburn 1636: }
1637: $output .= $home_server_pick.
1638: &Apache::lonhtmlcommon::row_closure(1).
1639: &Apache::lonhtmlcommon::end_pick_box().'</div>'.
1640: '<div>'.&clone_form($dom,$formname,$crstype).'</div>'."\n";
1.1 raeburn 1641: return $output;
1642: }
1643:
1644: sub clone_form {
1645: my ($dom,$formname,$crstype) = @_;
1646: my $type = 'Course';
1647: if ($crstype eq 'community') {
1648: $type = 'Community';
1649: }
1.13 raeburn 1650: my $cloneform = &Apache::loncommon::select_dom_form($dom,'clonedom').
1651: &Apache::loncommon::selectcourse_link($formname,'clonecrs','clonedom','','','',$type);
1.4 raeburn 1652: my %lt = &clone_text();
1.2 raeburn 1653: my $output .=
1654: &Apache::lonhtmlcommon::start_pick_box().
1655: &Apache::lonhtmlcommon::row_title($lt{'cid'}).'<label>'.
1.13 raeburn 1656: '<input type="text" size="25" name="clonecrs" value="" onfocus="this.blur();'.
1657: 'opencrsbrowser('."'$formname','clonecrs','clonedom','','','','$type'".');" />'.
1.2 raeburn 1658: '</label>'.&Apache::lonhtmlcommon::row_closure(1).'<label>'.
1659: &Apache::lonhtmlcommon::row_title($lt{'dmn'}).'</label>'.
1660: $cloneform.'</label>'.&Apache::lonhtmlcommon::row_closure().
1661: &Apache::lonhtmlcommon::row_title($lt{'dsh'}).'<label>'.
1662: '<input type="radio" name="datemode" value="delete" /> '.$lt{'ncd'}.
1663: '</label><br /><label>'.
1664: '<input type="radio" name="datemode" value="preserve" /> '.$lt{'prd'}.
1665: '</label><br /><label>'.
1666: '<input type="radio" name="datemode" value="shift" checked="checked" /> '.
1667: $lt{'shd'}.'</label>'.
1668: '<input type="text" size="5" name="dateshift" value="365" />'.
1669: &Apache::lonhtmlcommon::row_closure(1).
1670: &Apache::lonhtmlcommon::end_pick_box();
1.1 raeburn 1671: return $output;
1672: }
1673:
1.16 raeburn 1674: sub clone_text {
1.4 raeburn 1675: return &Apache::lonlocal::texthash(
1676: 'cid' => 'Course ID',
1677: 'dmn' => 'Domain',
1678: 'dsh' => 'Date Shift',
1679: 'ncd' => 'Do not clone date parameters',
1680: 'prd' => 'Clone date parameters as-is',
1681: 'shd' => 'Shift date parameters by number of days',
1682: );
1683: }
1684:
1.1 raeburn 1685: sub coursecode_form {
1.2 raeburn 1686: my ($dom,$context,$codetitles,$cat_titles,$cat_order,$num) = @_;
1.1 raeburn 1687: my $output;
1.2 raeburn 1688: my %rowtitle = (
1689: instcode => 'Course Category',
1690: crosslist => 'Cross Listed Course',
1691: );
1.1 raeburn 1692: if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH') &&
1693: (ref($cat_order))) {
1.2 raeburn 1694: my ($sel,$instsec,$lcsec);
1695: $sel = $context;
1696: if ($context eq 'crosslist') {
1697: $sel .= '_'.$num;
1698: $instsec = &mt('Institutional section').'<br />'.
1699: '<input type="text" size="10" name="'.$sel.'_instsec" />';
1700: $lcsec = &mt('LON-CAPA section').'<br />'.
1701: '<input type="text" size="10" name="'.$sel.'_lcsec" />';
1702: }
1.1 raeburn 1703: if (@{$codetitles} > 0) {
1704: my $lastitem = pop(@{$codetitles});
1.2 raeburn 1705: my $lastinput = '<input type="text" size="5" name="'.$sel.'_'. $lastitem.'" />';
1.1 raeburn 1706: if (@{$codetitles} > 0) {
1.2 raeburn 1707: $output = &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1708: '<table><tr>';
1.1 raeburn 1709: if ($context eq 'crosslist') {
1.2 raeburn 1710: $output .= '<td>'.&mt('Include?').'<br />'.
1711: '<input type="checkbox" name="'.$sel.'" value="1" /></td>';
1.1 raeburn 1712: }
1713: foreach my $title (@{$codetitles}) {
1714: if (ref($cat_order->{$title}) eq 'ARRAY') {
1715: if (@{$cat_order->{$title}} > 0) {
1716: $output .= '<td align="center">'.$title.'<br />'."\n".
1717: '<select name="'.$sel.'_'.$title.'">'."\n".
1718: ' <option value="" selected="selected">'.
1719: &mt('Select').'</option>'."\n";
1720: foreach my $item (@{$cat_order->{$title}}) {
1721: my $longitem = $item;
1722: if (ref($cat_titles->{$title}) eq 'HASH') {
1723: if ($cat_titles->{$title}{$item} ne '') {
1724: $longitem = $cat_titles->{$title}{$item};
1725: }
1726: }
1727: $output .= '<option value="'.$item.'">'.$longitem.
1728: '</option>'."\n";
1729: }
1730: }
1731: $output .= '</select></td>'."\n";
1732: }
1733: }
1734: if ($context eq 'crosslist') {
1735: $output .= '<td align="center">'.$lastitem.'<br />'."\n".
1.2 raeburn 1736: $lastinput.'</td><td align="center">'.$instsec.'</td>'.
1737: '<td align="center">'.$lcsec.'</td></tr></table>';
1.1 raeburn 1738: } else {
1739: $output .= '</tr></table>'.
1740: &Apache::lonhtmlcommon::row_closure().
1741: &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
1742: $lastinput;
1743: }
1744: } else {
1745: if ($context eq 'crosslist') {
1746: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1.2 raeburn 1747: '<table><tr>'.
1748: '<td align="center">'.$lastitem.'<br />'.$lastinput.'</td>'.
1749: '<td align="center">'.$instsec.'</td><td>'.$lcsec.'</td>'.
1750: '</tr></table>';
1.1 raeburn 1751: } else {
1752: $output .= &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
1753: $lastinput;
1754: }
1755: }
1.2 raeburn 1756: $output .= &Apache::lonhtmlcommon::row_closure(1);
1757: push(@$codetitles,$lastitem);
1758: } elsif ($context eq 'crosslist') {
1759: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1760: '<table><tr><td align="center">'.
1761: '<span class="LC_nobreak">'.&mt('Include?').
1762: '<input type="checkbox" name="'.$sel.'" value="1" /></span>'.
1763: '</td><td align="center">'.&mt('Institutional ID').'<br />'.
1764: '<input type="text" size="10" name="'.$sel.'_instsec" />'.
1765: '</td><td align="center">'.$lcsec.'</td></tr></table>'.
1766: &Apache::lonhtmlcommon::row_closure(1);
1.1 raeburn 1767: }
1768: }
1769: return $output;
1770: }
1771:
1772: sub get_course_dom {
1773: my $codedom = &Apache::lonnet::default_login_domain();
1.19 raeburn 1774: if ($env{'form.showdom'} ne '') {
1775: if (&Apache::lonnet::domain($env{'form.showdom'}) ne '') {
1776: return $env{'form.showdom'};
1777: }
1778: }
1.1 raeburn 1779: if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne 'public')) {
1.19 raeburn 1780: my ($types,$typename) = &course_types();
1781: if (ref($types) eq 'ARRAY') {
1782: foreach my $type (@{$types}) {
1783: if (&Apache::lonnet::usertools_access($env{'user.name'},
1784: $env{'user.domain'},$type,
1785: undef,'requestcourses')) {
1786: return $env{'user.domain'};
1787: }
1788: }
1789: my @possible_doms;
1790: foreach my $type (@{$types}) {
1791: my $dom_str = $env{'environment.reqcrsotherdom.'.$type};
1792: if ($dom_str ne '') {
1793: my @domains = split(',',$dom_str);
1794: foreach my $entry (@domains) {
1795: my ($extdom,$extopt) = split(':',$entry);
1796: if ($extdom eq $env{'request.role.domain'}) {
1797: return $extdom;
1798: }
1799: unless(grep(/^\Q$extdom\E$/,@possible_doms)) {
1800: push(@possible_doms,$extdom);
1801: }
1802: }
1803: }
1804: }
1805: if (@possible_doms) {
1806: @possible_doms = sort(@possible_doms);
1807: return $possible_doms[0];
1808: }
1809: }
1.1 raeburn 1810: $codedom = $env{'user.domain'};
1811: if ($env{'request.role.domain'} ne '') {
1812: $codedom = $env{'request.role.domain'};
1813: }
1814: }
1815: return $codedom;
1816: }
1817:
1818: sub display_navbuttons {
1.16 raeburn 1819: my ($r,$formname,$prev,$prevtext,$next,$nexttext,$state,$other,$othertext) = @_;
1.1 raeburn 1820: $r->print('<div class="LC_navbuttons">');
1821: if ($prev) {
1.16 raeburn 1822: $r->print('<input type="button" name="previous" value = "'.$prevtext.'" '.
1823: 'onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>'.
1824: (' 'x3));
1.1 raeburn 1825: } elsif ($prevtext) {
1.16 raeburn 1826: $r->print('<input type="button" name="previous" value = "'.$prevtext.'" '.
1827: 'onclick="javascript:history.back()"/>'.(' 'x3));
1828: }
1829: if ($state eq 'details') {
1830: $r->print(' <input type="button" name="other" value="'.$othertext.'" '.
1831: 'onclick="javascript:nextPage(document.'.$formname.','."'".$other."'".
1832: ')" />');
1.1 raeburn 1833: }
1.15 raeburn 1834: if ($state eq 'courseinfo') {
1.16 raeburn 1835: $r->print('<input type="button" name="next" value="'.$nexttext.'" '.
1836: 'onclick="javascript:validateForm();" />');
1.15 raeburn 1837: } elsif ($next) {
1.1 raeburn 1838: $r->print('
1.16 raeburn 1839: <input type="button" name="next" value="'.$nexttext.'" '.
1840: 'onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
1.1 raeburn 1841: }
1842: $r->print('</div>');
1843: }
1844:
1845: sub print_request_outcome {
1.10 raeburn 1846: my ($dom,$codetitles,$code_order) = @_;
1.13 raeburn 1847: my ($output,$cnum,$now,$req_notifylist,$crstype,$enrollstart,$enrollend,
1.10 raeburn 1848: %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig,);
1.24 ! raeburn 1849: my $sectotal = $env{'form.sectotal'};
! 1850: my $crosslisttotal = 0;
1.10 raeburn 1851: $cnum = $env{'form.cnum'};
1.8 raeburn 1852: unless ($cnum =~ /^$match_courseid$/) {
1853: $output = &mt('Invalid LON-CAPA course number for the new course')."\n";
1854: return $output;
1855: }
1.11 raeburn 1856:
1.10 raeburn 1857: %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
1.9 raeburn 1858: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
1859: if (ref($domconfig{'requestcourses'}{'notify'}) eq 'HASH') {
1860: $req_notifylist = $domconfig{'requestcourses'}{'notify'}{'approval'};
1861: }
1862: }
1.10 raeburn 1863: $now = time;
1864: $crstype = $env{'form.crstype'};
1.17 raeburn 1865: my @instsections;
1.8 raeburn 1866: if ($crstype eq 'official') {
1867: if (&Apache::lonnet::auto_run('',$dom)) {
1.13 raeburn 1868: ($enrollstart,$enrollend)=&dates_from_form('enrollstart','enrollend');
1.8 raeburn 1869: }
1.10 raeburn 1870: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
1871: if ($env{'form.sec_'.$i}) {
1872: if ($env{'form.secnum_'.$i} ne '') {
1.17 raeburn 1873: my $sec = $env{'form.secnum_'.$i};
1874: $sections{$i}{'inst'} = $sec;
1875: if (($sec ne '') && (!grep(/^\Q$sec\E$/,@instsections))) {
1876: push(@instsections,$sec);
1877: }
1.13 raeburn 1878: $sections{$i}{'loncapa'} = $env{'form.loncapasec_'.$i};
1.10 raeburn 1879: }
1880: }
1881: }
1882: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
1883: if ($env{'form.crosslist_'.$i}) {
1884: my $xlistinfo = '';
1885: if (ref($code_order) eq 'ARRAY') {
1886: if (@{$code_order} > 0) {
1887: foreach my $item (@{$code_order}) {
1888: $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
1889: }
1890: }
1891: }
1.22 raeburn 1892: $crosslistings{$i}{'instcode'} = $xlistinfo;
1.24 ! raeburn 1893: if ($xlistinfo ne '') {
! 1894: $crosslisttotal ++;
! 1895: }
1.22 raeburn 1896: $crosslistings{$i}{'instsec'} = $env{'form.crosslist_'.$i.'_instsec'};
1.13 raeburn 1897: $crosslistings{$i}{'loncapa'} = $env{'form.crosslist_'.$i.'_lcsec'};
1.10 raeburn 1898: }
1899: }
1.14 raeburn 1900: } else {
1901: $enrollstart = '';
1902: $enrollend = '';
1.10 raeburn 1903: }
1904: for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
1905: my $uname = $env{'form.person_'.$i.'_uname'};
1.16 raeburn 1906: my $udom = $env{'form.person_'.$i.'_dom'};
1.10 raeburn 1907: if (($uname =~ /^$match_username$/) && ($udom =~ /^$match_domain$/)) {
1908: if (&Apache::lonnet::domain($udom) ne '') {
1.13 raeburn 1909: unless (ref($personnel{$uname.':'.$udom}) eq 'HASH') {
1910: $personnel{$uname.':'.$udom} = {
1911: firstname => $env{'form.person_'.$i.'_firstname'},
1912: lastname => $env{'form.person_'.$i.'_lastname'},
1913: emailaddr => $env{'form.person_'.$i.'_emailaddr'},
1914: };
1915: }
1916: my $role = $env{'form.person_'.$i.'_role'};
1917: unless ($role eq '') {
1.16 raeburn 1918: if (ref($personnel{$uname.':'.$udom}{'roles'}) eq 'ARRAY') {
1.13 raeburn 1919: my @curr_roles = @{$personnel{$uname.':'.$udom}{'roles'}};
1920: unless (grep(/^\Q$role\E$/,@curr_roles)) {
1921: push(@{$personnel{$uname.':'.$udom}{'roles'}},$role);
1922: }
1923: } else {
1924: @{$personnel{$uname.':'.$udom}{'roles'}} = ($role);
1925: }
1926: if ($role eq 'cc') {
1927: @{$personnel{$uname.':'.$udom}{$role}{'usec'}} = ();
1928: } else {
1.14 raeburn 1929: my @currsec = &Apache::loncommon::get_env_multiple('form.person_'.$i.'_sec');
1930: my $newsec = $env{'form.person_'.$i.'_newsec'};
1931: $newsec =~ s/^\s+//;
1932: $newsec =~s/\s+$//;
1933: my @newsecs = split(/[\s,;]+/,$newsec);
1934: foreach my $sec (@newsecs) {
1935: next if ($sec =~ /\W/);
1936: next if ($newsec eq 'none');
1937: if ($sec ne '') {
1938: unless (grep(/^\Q$sec\E$/,@currsec)) {
1939: push(@currsec,$sec);
1.13 raeburn 1940: }
1941: }
1942: }
1943: @{$personnel{$uname.':'.$udom}{$role}{'usec'}} = @currsec;
1944: }
1945: }
1.10 raeburn 1946: } else {
1947: push(@missingdom,$uname.':'.$udom);
1948: }
1949: } else {
1950: push(@baduname,$uname.':'.$udom);
1951: }
1.8 raeburn 1952: }
1.13 raeburn 1953: my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend');
1.14 raeburn 1954: my $autodrops = 0;
1955: if ($env{'form.autodrops'}) {
1956: $autodrops = $env{'form.autodrops'};
1957: }
1958: my $autoadds = 0;
1959: if ($env{'form.autoadds'}) {
1960: $autodrops = $env{'form.autoadds'};
1961: }
1962: if ($env{'form.autoadds'}) {
1963: $autodrops = $env{'form.autoadds'};
1964: }
1965: my $instcode = '';
1966: if (exists($env{'form.instcode'})) {
1967: $instcode = $env{'form.instcode'};
1968: }
1.15 raeburn 1969: my $clonecrs = '';
1970: my $clonedom = '';
1971: if (($env{'form.clonecrs'} =~ /^($match_courseid)$/) &&
1972: ($env{'form.clonedom'} =~ /^($match_domain)$/)) {
1.16 raeburn 1973: my $clonehome = &Apache::lonnet::homeserver($env{'form.clonecrs'},
1974: $env{'form.clonedom'});
1.15 raeburn 1975: if ($clonehome ne 'no_host') {
1.16 raeburn 1976: my $canclone =
1977: &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'},
1978: $env{'user.domain'},$env{'form.clonecrs'}, $env{'form.clonedom'});
1.15 raeburn 1979: if ($canclone) {
1980: $clonecrs = $env{'form.clonecrs'};
1981: $clonedom = $env{'form.clonedom'};
1982: }
1983: }
1984: }
1.8 raeburn 1985: my $details = {
1.10 raeburn 1986: owner => $env{'user.name'},
1987: domain => $env{'user.domain'},
1988: cdom => $dom,
1.11 raeburn 1989: cnum => $cnum,
1.13 raeburn 1990: coursehome => $env{'form.chome'},
1991: cdescr => $env{'form.cdescr'},
1.10 raeburn 1992: crstype => $env{'form.crstype'},
1.14 raeburn 1993: instcode => $instcode,
1.15 raeburn 1994: clonedom => $clonedom,
1995: clonecrs => $clonecrs,
1.10 raeburn 1996: datemode => $env{'form.datemode'},
1.14 raeburn 1997: dateshift => $env{'form.dateshift'},
1998: sectotal => $sectotal,
1.10 raeburn 1999: sections => \%sections,
1.14 raeburn 2000: crosslisttotal => $crosslisttotal,
1.13 raeburn 2001: crosslists => \%crosslistings,
1.14 raeburn 2002: autoadds => $autoadds,
2003: autodrops => $autodrops,
1.13 raeburn 2004: enrollstart => $enrollstart,
2005: enrollend => $enrollend,
2006: accessstart => $accessstart,
2007: accessend => $accessend,
1.10 raeburn 2008: personnel => \%personnel,
1.8 raeburn 2009: };
2010: my @inststatuses;
1.9 raeburn 2011: my $val = &get_processtype($dom,$crstype,\@inststatuses,\%domconfig);
1.8 raeburn 2012: if ($val eq '') {
2013: if ($crstype eq 'official') {
1.19 raeburn 2014: $output = &mt('You are not permitted to request creation of official courses.');
1.8 raeburn 2015: } elsif ($crstype eq 'unofficial') {
1.19 raeburn 2016: $output = &mt('You are not permitted to request creation of unofficial courses.');
1.8 raeburn 2017: } elsif ($crstype eq 'community') {
2018: $output = &mt('You are not permitted to request creation of communities');
2019: } else {
2020: $output = &mt('Unrecognized course type: [_1]',$crstype);
2021: }
2022: } else {
1.14 raeburn 2023: my ($disposition,$message,$reqstatus);
1.8 raeburn 2024: my %reqhash = (
1.14 raeburn 2025: reqtime => $now,
1.10 raeburn 2026: crstype => $crstype,
2027: details => $details,
1.8 raeburn 2028: );
2029: my $requestkey = $dom.'_'.$cnum;
1.17 raeburn 2030: my $validationerror;
1.10 raeburn 2031: if ($val eq 'autolimit=') {
2032: $disposition = 'process';
2033: } elsif ($val =~ /^autolimit=(\d+)$/) {
2034: my $limit = $1;
1.8 raeburn 2035: $disposition = &check_autolimit($env{'user.name'},$env{'user.domain'},
1.10 raeburn 2036: $dom,$crstype,$limit,\$message);
1.8 raeburn 2037: } elsif ($val eq 'validate') {
1.21 raeburn 2038: my ($inststatuslist,$validationchk,$validation);
1.17 raeburn 2039: if (@inststatuses > 0) {
2040: $inststatuslist = join(',',@inststatuses);
2041: }
2042: my $instseclist;
2043: if (@instsections > 0) {
2044: $instseclist = join(',',@instsections);
2045: }
1.21 raeburn 2046: $validationchk =
2047: &Apache::lonnet::auto_courserequest_validation($dom,
2048: $env{'user.name'}.':'.$env{'user.domain'},$crstype,
2049: $inststatuslist,$instcode,$instseclist);
2050: if ($validationchk =~ /:/) {
2051: ($validation,$message) = split(':',$validationchk);
2052: } else {
2053: $validation = $validationchk;
2054: }
2055: if ($validation =~ /^error(.*)$/) {
1.17 raeburn 2056: $disposition = 'approval';
2057: $validationerror = $1;
1.23 raeburn 2058: } else {
2059: $disposition = $validation;
1.17 raeburn 2060: }
1.8 raeburn 2061: } else {
2062: $disposition = 'approval';
2063: }
1.14 raeburn 2064: $reqhash{'disposition'} = $disposition;
2065: $reqstatus = $disposition;
1.16 raeburn 2066: my ($modified,$queued);
1.8 raeburn 2067: if ($disposition eq 'rejected') {
2068: $output = &mt('Your course request was rejected.');
2069: if ($message) {
2070: $output .= '<div class="LC_warning">'.$message.'</div>';
2071: }
2072: } elsif ($disposition eq 'process') {
1.14 raeburn 2073: my %domdefs = &Apache::lonnet::get_domain_defaults($dom);
2074: my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles);
2075: my @roles = &Apache::lonuserutils::roles_by_context('course');
1.8 raeburn 2076: my $type = 'Course';
2077: if ($crstype eq 'community') {
2078: $type = 'Community';
2079: }
2080: foreach my $role (@roles) {
2081: $longroles{$role}=&Apache::lonnet::plaintext($role,$type);
2082: }
1.14 raeburn 2083: my $result = &Apache::loncoursequeueadmin::course_creation($dom,$cnum,
2084: 'autocreate',$details,\$logmsg,\$newusermsg,\$addresult,
2085: \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles);
2086: if ($result eq 'created') {
1.8 raeburn 2087: $disposition = 'created';
1.14 raeburn 2088: $reqstatus = 'created';
2089: $output = &mt('Your course request has been processed and the course has been created.').
2090: '<br />'.
2091: &mt('You will need to logout and log-in again to be able to select a role in the course.');
1.8 raeburn 2092: } else {
1.14 raeburn 2093: $output = '<span class="LC_error">'.
2094: &mt('An error occurred when processing your course request.').
2095: '<br />'.
2096: &mt('You may want to review the request details and submit the request again.').
2097: '</span>';
1.8 raeburn 2098: }
2099: } else {
2100: my $requestid = $cnum.'_'.$disposition;
2101: my $request = {
2102: $requestid => {
2103: timestamp => $now,
2104: crstype => $crstype,
2105: ownername => $env{'user.name'},
2106: ownerdom => $env{'user.domain'},
1.13 raeburn 2107: description => $env{'form.cdescr'},
1.8 raeburn 2108: },
2109: };
1.16 raeburn 2110: my $statuskey = 'status:'.$dom.':'.$cnum;
2111: my %userreqhash = &Apache::lonnet::get('courserequests',[$statuskey],
2112: $env{'user.domain'},$env{'user.name'});
1.17 raeburn 2113: if ($userreqhash{$statuskey} ne '') {
1.16 raeburn 2114: $modified = 1;
2115: my %queuehash = &Apache::lonnet::get_dom('courserequestqueue',
2116: [$cnum.'_approval',
2117: $cnum.'_pending'],$dom);
1.17 raeburn 2118: if (($queuehash{$cnum.'_approval'} ne '') ||
2119: ($queuehash{$cnum.'_pending'} ne '')) {
1.16 raeburn 2120: $queued = 1;
2121: }
2122: }
2123: unless ($queued) {
2124: my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request,
2125: $dom);
2126: if ($putresult eq 'ok') {
2127: $output = &mt('Your course request has been recorded.').'<br />'.
2128: ¬ification_information($disposition,$req_notifylist,
2129: $cnum,$now);
1.8 raeburn 2130: } else {
1.16 raeburn 2131: $reqstatus = 'domainerror';
2132: $reqhash{'disposition'} = $disposition;
2133: my $warning = &mt('An error occurred saving your request in the pending requests queue.');
2134: $output = '<span class"LC_warning">'.$warning.'</span><br />';
1.8 raeburn 2135: }
2136: }
2137: }
1.14 raeburn 2138: my ($storeresult,$statusresult);
1.10 raeburn 2139: if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
2140: $storeresult = &Apache::lonnet::store_userdata(\%reqhash,$requestkey,
2141: 'courserequests');
1.14 raeburn 2142: if ($storeresult eq 'ok') {
2143: my %status = (
2144: 'status:'.$dom.':'.$cnum => $reqstatus,
2145: );
2146: $statusresult = &Apache::lonnet::put('courserequests',\%status);
2147: }
1.10 raeburn 2148: } else {
2149: $storeresult = 'error: invalid requestkey format';
2150: }
1.8 raeburn 2151: if ($storeresult ne 'ok') {
1.13 raeburn 2152: $output .= '<span class="LC_warning">'.&mt('An error occurred saving a record of the details of your request: [_1].',$storeresult).'</span><br />';
2153: &Apache::lonnet::logthis("Error saving course request - $requestkey for $env{'user.name'}:$env{'user.domain'} - $storeresult");
1.14 raeburn 2154: } elsif ($statusresult ne 'ok') {
2155: $output .= '<span class="LC_warning">'.&mt('An error occurred saving a record of the status of your request: [_1].',$statusresult).'</span><br />';
2156: &Apache::lonnet::logthis("Error saving course request status for $requestkey (for $env{'user.name'}:$env{'user.domain'}) - $statusresult");
1.8 raeburn 2157: }
1.16 raeburn 2158: if ($modified && $queued && $storeresult eq 'ok') {
2159: $output .= '<p>'.&mt('Your course request has been updated').'</p>'.
2160: ¬ification_information($disposition,$req_notifylist,$cnum,$now);
2161: }
1.17 raeburn 2162: if ($validationerror ne '') {
1.19 raeburn 2163: $output .= '<span class="LC_warning">'.&mt('An error occurred validating your request with institutional data sources: [_1].',$validationerror).'</p>';
1.17 raeburn 2164: }
1.16 raeburn 2165: }
2166: return $output;
2167: }
2168:
2169: sub notification_information {
2170: my ($disposition,$req_notifylist,$cnum,$now) = @_;
2171: my %emails = &Apache::loncommon::getemails();
2172: my $address;
2173: if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
2174: $address = $emails{'permanentemail'};
2175: if ($address eq '') {
2176: $address = $emails{'notification'};
2177: }
2178: }
2179: my $output;
2180: if ($disposition eq 'approval') {
2181: $output .= &mt('A message will be sent to your LON-CAPA account when a domain coordinator takes action on your request.').'<br />'.
2182: &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').'<br />';
2183: if ($address ne '') {
2184: $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).'<br />';
2185: }
2186: if ($req_notifylist) {
2187: my $fullname = &Apache::loncommon::plainname($env{'user.name'},
2188: $env{'user.domain'});
2189: my $sender = $env{'user.name'}.':'.$env{'user.domain'};
2190: &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,"$fullname ($env{'user.name'}:$env{'user.domain'})",$cnum,$env{'form.cdescr'},$now,'coursereq',$sender);
2191: }
1.17 raeburn 2192: } elsif ($disposition eq 'pending') {
1.16 raeburn 2193: $output .= '<div class="LC_info">'.
2194: &mt('Your request has been placed in a queue pending administrative action.').'<br />'.
2195: &mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").'<br />'.
2196: &mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.').
2197: '</div>';
1.17 raeburn 2198: } else {
2199: $output .= '<div class="LC_warning">'.
2200: &mt('Your request status is: [_1].',$disposition).
2201: '</div>'
1.8 raeburn 2202: }
2203: return $output;
2204: }
2205:
2206: sub get_processtype {
1.9 raeburn 2207: my ($dom,$crstype,$inststatuses,$domconfig) = @_;
2208: return unless ((ref($inststatuses) eq 'ARRAY') && (ref($domconfig) eq 'HASH'));
1.8 raeburn 2209: my (%userenv,%settings,$val);
1.19 raeburn 2210: my @options = ('autolimit','validate','approval');
1.8 raeburn 2211: if ($dom eq $env{'user.domain'}) {
2212: %userenv =
2213: &Apache::lonnet::userenvironment($env{'user.domain'},$env{'user.name'},
2214: 'requestcourses.'.$crstype,'inststatus');
2215: if ($userenv{'requestcourses.'.$crstype}) {
2216: $val = $userenv{'requestcourses.'.$crstype};
2217: @{$inststatuses} = ('_custom_');
2218: } else {
2219: my ($task,%alltasks);
1.9 raeburn 2220: if (ref($domconfig->{'requestcourses'}) eq 'HASH') {
2221: %settings = %{$domconfig->{'requestcourses'}};
1.8 raeburn 2222: if (ref($settings{$crstype}) eq 'HASH') {
1.23 raeburn 2223: if (($env{'user.adv'}) && ($settings{$crstype}{'_LC_adv'} ne '')) {
1.8 raeburn 2224: $val = $settings{$crstype}{'_LC_adv'};
2225: @{$inststatuses} = ('_LC_adv_');
2226: } else {
2227: if ($userenv{'inststatus'} ne '') {
2228: @{$inststatuses} = split(',',$userenv{'inststatus'});
2229: } else {
1.13 raeburn 2230: @{$inststatuses} = ('default');
1.8 raeburn 2231: }
2232: foreach my $status (@{$inststatuses}) {
2233: if (exists($settings{$crstype}{$status})) {
2234: my $value = $settings{$crstype}{$status};
2235: next unless ($value);
2236: unless (exists($alltasks{$value})) {
2237: if (ref($alltasks{$value}) eq 'ARRAY') {
2238: unless(grep(/^\Q$status\E$/,@{$alltasks{$value}})) {
2239: push(@{$alltasks{$value}},$status);
2240: }
2241: } else {
2242: @{$alltasks{$value}} = ($status);
2243: }
2244: }
2245: }
2246: }
2247: my $maxlimit = 0;
1.13 raeburn 2248:
1.8 raeburn 2249: foreach my $key (sort(keys(%alltasks))) {
2250: if ($key =~ /^autolimit=(\d*)$/) {
2251: if ($1 eq '') {
2252: $val ='autolimit=';
2253: last;
2254: } elsif ($1 > $maxlimit) {
2255: $maxlimit = $1;
2256: }
2257: }
2258: }
2259: if ($maxlimit) {
2260: $val = 'autolimit='.$maxlimit;
2261: } else {
2262: foreach my $option (@options) {
2263: if ($alltasks{$option}) {
2264: $val = $option;
2265: last;
2266: }
2267: }
2268: }
2269: }
2270: }
2271: }
2272: }
2273: } else {
2274: %userenv = &Apache::lonnet::userenvironment($env{'user.domain'},
2275: $env{'user.name'},'reqcrsotherdom.'.$env{'form.crstype'});
1.19 raeburn 2276: if ($userenv{'reqcrsotherdom.'.$crstype}) {
2277: my @doms = split(',',$userenv{'reqcrsotherdom.'.$crstype});
2278: my $optregex = join('|',@options);
2279: foreach my $item (@doms) {
2280: my ($extdom,$extopt) = split(':',$item);
2281: if ($extdom eq $dom) {
2282: if ($extopt =~ /^($optregex)(=?\d*)$/) {
2283: $val = $1.$2;
2284: }
2285: last;
2286: }
1.8 raeburn 2287: }
2288: @{$inststatuses} = ('_external_');
2289: }
2290: }
2291: return $val;
2292: }
2293:
2294: sub check_autolimit {
1.10 raeburn 2295: my ($uname,$udom,$dom,$crstype,$limit,$message) = @_;
2296: my %crsroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
2297: 'userroles',['active','future'],['cc'],[$dom]);
2298: my ($types,$typename) = &course_types();
2299: my %requests = &Apache::lonnet::dumpstore('courserequests',$udom,$uname);
2300: my %count;
2301: if (ref($types) eq 'ARRAY') {
2302: foreach my $type (@{$types}) {
2303: $count{$type} = 0;
2304: }
2305: }
2306: foreach my $key (keys(%requests)) {
2307: my ($cdom,$cnum) = split('_',$key);
2308: if (exists($crsroles{$cnum.':'.$cdom.':cc'})) {
2309: if (ref($requests{$key}) eq 'HASH') {
2310: my $type = $requests{$key}{'crstype'};
2311: if ($type =~ /^official|unofficial|community$/) {
2312: $count{$type} ++;
2313: }
2314: }
2315: }
2316: }
2317: if ($count{$crstype} < $limit) {
2318: return 'process';
2319: } else {
2320: if (ref($typename) eq 'HASH') {
2321: $$message = &mt('Your request has not been processed because you have reached the limit for the number of courses of this type.').'<br />'.&mt("Your $typename->{$crstype} limit is [_1].",$limit);
2322: }
2323: return 'rejected';
2324: }
1.1 raeburn 2325: return;
2326: }
2327:
1.2 raeburn 2328: sub retrieve_settings {
1.16 raeburn 2329: my ($dom,$cnum) = @_;
2330: my ($result,%reqinfo) = &get_request_settings($dom,$cnum);
2331: if ($result eq 'ok') {
2332: if (($env{'user.name'} eq $reqinfo{'owner'}) &&
2333: ($env{'user.domain'} eq $reqinfo{'domain'})) {
2334: $env{'form.chome'} = $reqinfo{'coursehome'};
2335: $env{'form.cdescr'} = $reqinfo{'cdescr'};
2336: $env{'form.crstype'} = $reqinfo{'crstype'};
2337: &generate_date_items($reqinfo{'accessstart'},'accessstart');
2338: &generate_date_items($reqinfo{'accessend'},'accessend');
2339: if ($reqinfo{'accessend'} == 0) {
2340: $env{'form.no_end_date'} = 1;
2341: }
2342: if (($reqinfo{'crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) {
2343: &generate_date_items($reqinfo{'enrollstart'},'enrollstart');
2344: &generate_date_items($reqinfo{'enrollend'},'enrollend');
2345: }
2346: $env{'form.clonecrs'} = $reqinfo{'clonecrs'};
2347: $env{'form.clonedom'} = $reqinfo{'clonedom'};
2348: $env{'form.datemode'} = $reqinfo{'datemode'};
2349: $env{'form.dateshift'} = $reqinfo{'dateshift'};
2350: if (($reqinfo{'crstype'} eq 'official') && ($reqinfo{'instcode'} ne '')) {
2351: $env{'form.sectotal'} = $reqinfo{'sectotal'};
2352: $env{'form.crosslisttotal'} = $reqinfo{'crosslisttotal'};
2353: $env{'form.autoadds'} = $reqinfo{'autoadds'};
2354: $env{'form.autdrops'} = $reqinfo{'autodrops'};
2355: $env{'form.instcode'} = $reqinfo{'instcode'};
1.24 ! raeburn 2356: my $crscode = {
! 2357: $cnum => $reqinfo{'instcode'},
! 2358: };
! 2359: &extract_instcode($dom,'instcode',$crscode,$cnum);
1.16 raeburn 2360: }
2361: my @currsec;
2362: if (ref($reqinfo{'sections'}) eq 'HASH') {
2363: foreach my $i (sort(keys(%{$reqinfo{'sections'}}))) {
2364: if (ref($reqinfo{'sections'}{$i}) eq 'HASH') {
1.24 ! raeburn 2365: my $sec = $reqinfo{'sections'}{$i}{'inst'};
1.16 raeburn 2366: $env{'form.secnum_'.$i} = $sec;
1.24 ! raeburn 2367: $env{'form.sec_'.$i} = '1';
1.16 raeburn 2368: if (!grep(/^\Q$sec\E$/,@currsec)) {
2369: push(@currsec,$sec);
2370: }
2371: $env{'form.loncapasec_'.$i} = $reqinfo{'sections'}{$i}{'loncapa'};
2372: }
2373: }
2374: }
1.24 ! raeburn 2375: if (ref($reqinfo{'crosslists'}) eq 'HASH') {
! 2376: foreach my $i (sort(keys(%{$reqinfo{'crosslists'}}))) {
! 2377: if (ref($reqinfo{'crosslists'}{$i}) eq 'HASH') {
! 2378: $env{'form.crosslist_'.$i} = '1';
! 2379: $env{'form.crosslist_'.$i.'_instsec'} = $reqinfo{'crosslists'}{$i}{'instsec'};
! 2380: $env{'form.crosslist_'.$i.'_lcsec'} = $reqinfo{'crosslists'}{$i}{'loncapa'};
! 2381: if ($reqinfo{'crosslists'}{$i}{'instcode'} ne '') {
! 2382: my $key = $cnum.$i;
! 2383: my $crscode = {
! 2384: $key => $reqinfo{'crosslists'}{$i}{'instcode'},
! 2385: };
! 2386: &extract_instcode($dom,'crosslist',$crscode,$key,$i);
! 2387: }
1.16 raeburn 2388: }
2389: }
2390: }
2391: if (ref($reqinfo{'personnel'}) eq 'HASH') {
2392: my $i = 0;
2393: foreach my $user (sort(keys(%{$reqinfo{'personnel'}}))) {
2394: my ($uname,$udom) = split(':',$user);
2395: if (ref($reqinfo{'personnel'}{$user}) eq 'HASH') {
2396: if (ref($reqinfo{'personnel'}{$user}{'roles'}) eq 'ARRAY') {
2397: foreach my $role (sort(@{$reqinfo{'personnel'}{$user}{'roles'}})) {
2398: $env{'form.person_'.$i.'_role'} = $role;
2399: $env{'form.person_'.$i.'_firstname'} = $reqinfo{'personnel'}{$user}{'firstname'};
2400: $env{'form.person_'.$i.'_lastname'} = $reqinfo{'personnel'}{$user}{'lastname'}; ;
2401: $env{'form.person_'.$i.'_emailaddr'} = $reqinfo{'personnel'}{$user}{'emailaddr'};
2402: $env{'form.person_'.$i.'_uname'} = $uname;
2403: $env{'form.person_'.$i.'_dom'} = $udom;
2404: if (ref($reqinfo{'personnel'}{$user}{$role}) eq 'HASH') {
2405: if (ref($reqinfo{'personnel'}{$user}{$role}{'usec'}) eq 'ARRAY') {
2406: my @usecs = @{$reqinfo{'personnel'}{$user}{$role}{'usec'}};
2407: my @newsecs;
2408: if (@usecs > 0) {
2409: foreach my $sec (@usecs) {
2410: if (grep(/^\Q$sec\E/,@currsec)) {
2411: $env{'form.person_'.$i.'_sec'} = $sec;
2412: } else {
1.20 raeburn 2413: push(@newsecs,$sec);
1.16 raeburn 2414: }
2415: }
2416: }
2417: if (@newsecs > 0) {
2418: $env{'form.person_'.$i.'_newsec'} = join(',',@newsecs);
2419: }
2420: }
2421: }
2422: $i ++;
2423: }
2424: }
2425: }
2426: }
2427: $env{'form.persontotal'} = $i;
2428: }
2429: }
2430: }
2431: return $result;
2432: }
2433:
2434: sub get_request_settings {
2435: my ($dom,$cnum) = @_;
2436: my $requestkey = $dom.'_'.$cnum;
2437: my ($result,%reqinfo);
2438: if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
2439: my %history = &Apache::lonnet::restore($requestkey,'courserequests',
2440: $env{'user.domain'},$env{'user.name'});
2441: my $disposition = $history{'disposition'};
2442: if (($disposition eq 'approval') || ($disposition eq 'pending')) {
2443: if (ref($history{'details'}) eq 'HASH') {
2444: %reqinfo = %{$history{'details'}};
2445: $result = 'ok';
2446: } else {
2447: $result = 'nothash';
2448: }
2449: } else {
2450: $result = 'notqueued';
2451: }
2452: } else {
2453: $result = 'invalid';
2454: }
2455: return ($result,%reqinfo);
2456: }
1.2 raeburn 2457:
1.16 raeburn 2458: sub extract_instcode {
1.24 ! raeburn 2459: my ($cdom,$element,$crscode,$crskey,$counter) = @_;
1.16 raeburn 2460: my (%codes,@codetitles,%cat_titles,%cat_order);
1.24 ! raeburn 2461: if (&Apache::lonnet::auto_instcode_format('requests',$cdom,$crscode,\%codes,
! 2462: \@codetitles,\%cat_titles,
! 2463: \%cat_order) eq 'ok') {
! 2464: if (ref($codes{$crskey}) eq 'HASH') {
1.16 raeburn 2465: if (@codetitles > 0) {
2466: my $sel = $element;
2467: if ($element eq 'crosslist') {
2468: $sel .= '_'.$counter;
2469: }
2470: foreach my $title (@codetitles) {
1.24 ! raeburn 2471: $env{'form.'.$sel.'_'.$title} = $codes{$crskey}{$title};
1.16 raeburn 2472: }
2473: }
2474: }
2475: }
2476: return;
1.2 raeburn 2477: }
2478:
1.16 raeburn 2479: sub generate_date_items {
2480: my ($currentval,$item) = @_;
2481: if ($currentval =~ /\d+/) {
2482: my ($tzname,$sec,$min,$hour,$mday,$month,$year) =
2483: &Apache::lonhtmlcommon::get_timedates($currentval);
2484: $env{'form.'.$item.'_day'} = $mday;
2485: $env{'form.'.$item.'_month'} = $month+1;
2486: $env{'form.'.$item.'_year'} = $year;
2487: }
2488: return;
1.2 raeburn 2489: }
2490:
1.1 raeburn 2491: 1;
2492:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>