Annotation of loncom/interface/lonrequestcourse.pm, revision 1.11
1.1 raeburn 1: # The LearningOnline Network
2: # Request a course
3: #
1.11 ! raeburn 4: # $Id: lonrequestcourse.pm,v 1.10 2009/08/12 12:40:33 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:
47: =back
48:
49: =cut
50:
51: package Apache::lonrequestcourse;
52:
53: use strict;
54: use Apache::Constants qw(:common :http);
55: use Apache::lonnet;
56: use Apache::loncommon;
57: use Apache::lonlocal;
1.8 raeburn 58: use Apache::loncoursequeueadmin;
1.4 raeburn 59: use LONCAPA qw(:DEFAULT :match);
1.1 raeburn 60:
61: sub handler {
62: my ($r) = @_;
63: if ($r->header_only) {
64: &Apache::loncommon::content_type($r,'text/html');
65: $r->send_http_header;
66: return OK;
67: }
68: &Apache::loncommon::content_type($r,'text/html');
69: $r->send_http_header;
70:
1.2 raeburn 71: &Apache::lonhtmlcommon::clear_breadcrumbs();
72: my $dom = &get_course_dom();
1.1 raeburn 73: my $action = $env{'form.action'};
74: my $state = $env{'form.state'};
1.2 raeburn 75:
76: my %stored;
77: my $jscript;
78: if ((defined($state)) && (defined($action))) {
79: my %elements = &form_elements($dom);
80: if (($action eq 'view') && ($state ne 'crstype')) {
81: if (defined($env{'form.request_id'})) {
82: %stored = &retrieve_settings($dom,$env{'form.request_id'});
83: }
84: }
85: my $elementsref = {};
86: if (ref($elements{$action}) eq 'HASH') {
87: if (ref($elements{$action}{$state}) eq 'HASH') {
88: $elementsref = $elements{$action}{$state};
89: }
90: }
91: $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
92: }
93:
94: if ($state eq 'personnel') {
95: $jscript .= "\n".&Apache::loncommon::userbrowser_javascript();
96: }
97:
98: my $loaditems = &onload_action($action,$state);
99:
100: my %states;
101: $states{'view'} = ['pick_request','details','review','process'];
102: $states{'log'} = ['filter','display'];
103: $states{'new'} = ['courseinfo','enrollment','personnel','review','process'];
104: if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) {
105: unless ($env{'form.state'} eq 'crstype') {
106: unshift (@{$states{'new'}},'codepick');
107: }
108: }
109:
110: foreach my $key (keys(%states)) {
111: if (ref($states{$key}) eq 'ARRAY') {
112: unshift (@{$states{$key}},'crstype');
113: }
114: }
115:
1.3 raeburn 116: my %trail = (
1.10 raeburn 117: crstype => 'Course Request Action',
118: codepick => 'Category',
119: courseinfo => 'Description',
120: enrollment => 'Enrollment',
121: personnel => 'Personnel',
122: review => 'Review',
123: process => 'Result',
124: pick_request => 'Display Summary',
1.3 raeburn 125: );
126:
1.2 raeburn 127: my $page = 0;
1.3 raeburn 128: my $crumb;
1.2 raeburn 129: if (defined($action)) {
130: my $done = 0;
131: my $i=0;
132: if (ref($states{$action}) eq 'ARRAY') {
133: while ($i<@{$states{$action}} && !$done) {
134: if ($states{$action}[$i] eq $state) {
135: $page = $i;
136: $done = 1;
137: }
138: $i++;
139: }
140: }
1.3 raeburn 141: for (my $i=0; $i<@{$states{$action}}; $i++) {
142: if ($state eq $states{$action}[$i]) {
143: &Apache::lonhtmlcommon::add_breadcrumb(
144: {text=>"$trail{$state}"});
145: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
146: last;
147: } else {
148: if (($state eq 'process') && ($i > 0)) {
149: &Apache::lonhtmlcommon::add_breadcrumb(
150: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[0]')",
151: text=>"$trail{$states{$action}[$i]}"});
152: } else {
153: &Apache::lonhtmlcommon::add_breadcrumb(
154: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[$i]')",
155: text=>"$trail{$states{$action}[$i]}"});
156: }
157: }
158: }
159: } else {
160: &Apache::lonhtmlcommon::add_breadcrumb(
161: {text=>'Pick Action'});
162: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
1.2 raeburn 163: }
164:
1.1 raeburn 165: my %can_request;
166: my $canreq = &check_can_request($dom,\%can_request);
167: if ($action eq 'new') {
168: if ($canreq) {
169: if ($state eq 'crstype') {
1.3 raeburn 170: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,
171: $crumb);
1.1 raeburn 172: } else {
1.2 raeburn 173: &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
1.3 raeburn 174: $loaditems,$crumb);
1.1 raeburn 175: }
176: } else {
1.3 raeburn 177: $r->print(&header('Course Requests').$crumb.
1.1 raeburn 178: '<div class="LC_warning">'.
179: &mt('You do not have privileges to request creation of courses.').
1.2 raeburn 180: '</div>'.&Apache::loncommon::end_page());
1.1 raeburn 181: }
182: } elsif ($action eq 'view') {
1.10 raeburn 183: if ($state eq 'crstype') {
1.11 ! raeburn 184: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb);
! 185: } else {
! 186: &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
! 187: $loaditems,$crumb);
1.10 raeburn 188: }
1.1 raeburn 189: } elsif ($action eq 'log') {
1.3 raeburn 190: &print_request_logs($jscript,$loaditems,$crumb);
1.1 raeburn 191: } else {
1.3 raeburn 192: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb);
1.1 raeburn 193: }
194: return OK;
195: }
196:
1.2 raeburn 197: sub header {
198: my ($bodytitle,$jscript,$loaditems,$jsextra) = @_;
199: if ($jscript) {
1.6 raeburn 200: $jscript = '<script type="text/javascript">'."\n".
201: '// <![CDATA['."\n".
202: $jscript."\n".'// ]]>'."\n".'</script>'."\n";
1.2 raeburn 203: }
204: if ($loaditems) {
1.3 raeburn 205: $loaditems = {'add_entries' => $loaditems,};
206: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra,$loaditems);
207: } else {
208: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra);
209: }
1.2 raeburn 210: }
211:
212: sub form_elements {
213: my ($dom) = @_;
214: my %elements =
215: (
216: new => {
217: crstype => {
218: crstype => 'selectbox',
219: action => 'selectbox',
220: },
221: courseinfo => {
222: cdescr => 'text',
223: clonecourse => 'text',
224: clonedomain => 'selectbox',
225: datemode => 'radio',
226: dateshift => 'text',
227: },
228: enrollment => {
229: startaccess_month => 'selectbox',
230: startaccess_hour => 'selectbox',
231: endaccess_month => 'selectbox',
232: endaccess_hour => 'selectbox',
233: startaccess_day => 'text',
234: startaccess_year => 'text',
235: startaccess_minute => 'text',
236: startaccess_second => 'text',
237: endaccess_day => 'text',
238: endaccess_year => 'text',
239: endaccess_minute => 'text',
240: endaccess_second => 'text',
241: no_end_date => 'checkbox',
242: },
243: personnel => {
244: persontotal => 'hidden',
245: addperson => 'checkbox',
246: },
247: },
248: view => {
249: crstype => {
250: crstype => 'selectbox',
251: action => 'selectbox',
252: },
253: },
254: );
255: my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem);
256: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
257: \%cat_order,\@code_order);
258: my $numtitles = scalar(@codetitles);
259: if ($numtitles) {
260: my %extras;
261: $lastitem = pop(@codetitles);
262: $extras{'instcode_'.$lastitem} = 'text';
263: foreach my $item (@codetitles) {
264: $extras{'instcode_'.$item} = 'selectbox';
265: }
266: $elements{'new'}{'codepick'} = \%extras;
267: }
268: if (&Apache::lonnet::auto_run('',$dom)) {
269: my %extras = (
270: sectotal => 'hidden',
271: startenroll_month => 'selectbox',
272: startenroll_hour => 'selectbox',
273: endenroll_month => 'selectbox',
274: endenroll_hour => 'selectbox',
275: startenroll_day => 'text',
276: startenroll_year => 'text',
277: startenroll_minute => 'text',
278: startenroll_second => 'text',
279: endenroll_day => 'text',
280: endenroll_year => 'text',
281: endenroll_minute => 'text',
282: endenroll_second => 'text',
283: crosslisttotal => 'hidden',
284: addcrosslist => 'checkbox',
285: autoadds => 'radio',
286: autodrops => 'radio',
287: );
288: if ($env{'form.sectotal'} > 0) {
289: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
290: $extras{'sec_'.$i} = 'checkbox',
291: $extras{'secnum_'.$i} = 'text',
292: $extras{'loncapasec_'.$i} = 'checkbox',
293: }
294: }
295: my $crosslisttotal = $env{'form.crosslisttotal'};
296: if (!defined($crosslisttotal)) {
297: $crosslisttotal = 1;
298: }
299: if ($crosslisttotal > 0) {
300: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
301: if ($numtitles) {
302: $extras{'crosslist_'.$i.'_'.$lastitem} = 'text';
303: }
304: if (@codetitles > 0) {
305: foreach my $item (@codetitles) {
306: $extras{'crosslist_'.$i.'_'.$item} = 'selectbox';
307: }
308: }
309: $extras{'crosslist_'.$i} = 'checkbox';
310: $extras{'crosslist_'.$i.'_instsec'} = 'text',
311: $extras{'crosslist_'.$i.'_lcsec'} = 'text',
312: }
313: }
314: my %mergedhash = (%{$elements{'new'}{'enrollment'}},%extras);
315: %{$elements{'new'}{'enrollment'}} = %mergedhash;
316: }
317: my %people;
318: my $persontotal = $env{'form.persontotal'};
319: if (!defined($persontotal)) {
320: $persontotal = 1;
321: }
322: for (my $i=0; $i<$persontotal; $i++) {
323: $people{'person_'.$i.'_uname'} = 'text',
324: $people{'person_'.$i.'_dom'} = 'selectbox',
325: $people{'person_'.$i.'_hidedom'} = 'hidden',
326: $people{'person_'.$i.'_first'} = 'text',
327: $people{'person_'.$i.'_last'} = 'text',
328: $people{'person_'.$i.'_email'} = 'text',
329: $people{'person_'.$i.'_role'} = 'selectbox',
330: $people{'person_'.$i.'_sec'} = 'selectbox',
331: $people{'person_'.$i.'_newsec'} = 'text',
332: $people{'person_'.$i.'_sections'} = 'hidden',
333: }
334: my %personnelhash = (%{$elements{'new'}{'personnel'}},%people);
335: %{$elements{'new'}{'personnel'}} = %personnelhash;
336: return %elements;
337: }
338:
339: sub onload_action {
340: my ($action,$state) = @_;
341: my %loaditems;
342: if (($action eq 'new') || ($action eq 'view')) {
343: $loaditems{'onload'} = 'javascript:setFormElements(document.requestcrs)';
344: }
345: return \%loaditems;
346: }
347:
1.1 raeburn 348: sub check_can_request {
349: my ($dom,$can_request) = @_;
350: my $canreq = 0;
1.4 raeburn 351: my ($types,$typename) = &course_types();
352: if ((ref($can_request) eq 'HASH') && (ref($types) eq 'ARRAY')) {
353: foreach my $type (@{$types}) {
1.1 raeburn 354: if (&Apache::lonnet::usertools_access($env{'user.name'},
355: $env{'user.domain'},
356: $type,undef,'requestcourses')) {
357: $canreq ++;
358: if ($dom eq $env{'user.domain'}) {
359: $can_request->{$type} = 1;
360: }
361: }
362: if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
363: my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type});
364: if (@curr > 0) {
365: $canreq ++;
366: unless ($dom eq $env{'user.domain'}) {
367: if (grep(/^\Q$dom\E$/,@curr)) {
368: $can_request->{$type} = 1;
369: }
370: }
371: }
372: }
373: }
374: }
375: return $canreq;
376: }
377:
1.4 raeburn 378: sub course_types {
379: my @types = ('official','unofficial','community');
380: my %typename = (
381: official => 'Official course',
382: unofficial => 'Unofficial course',
383: community => 'Community',
384: );
385: return (\@types,\%typename);
386: }
387:
388:
1.1 raeburn 389: sub print_main_menu {
1.3 raeburn 390: my ($r,$can_request,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.4 raeburn 391: my ($types,$typename) = &course_types();
1.1 raeburn 392: my $onchange;
393: unless ($env{'form.interface'} eq 'textual') {
394: $onchange = 1;
395: }
396:
1.2 raeburn 397: my $nextstate_setter = "\n";
398: if (ref($states) eq 'HASH') {
399: foreach my $key (keys(%{$states})) {
400: if (ref($states->{$key}) eq 'ARRAY') {
401: $nextstate_setter .=
402: " if (actionchoice == '$key') {
403: nextstate = '".$states->{$key}[1]."';
404: }
405: ";
406: }
407: }
408: }
1.1 raeburn 409:
1.2 raeburn 410: my $js = <<"END";
1.1 raeburn 411:
1.2 raeburn 412: function nextPage(formname) {
413: var crschoice = document.requestcrs.crstype.value;
414: var actionchoice = document.requestcrs.action.value;
415: if (check_can_request(crschoice,actionchoice) == true) {
416: if ((actionchoice == 'new') && (crschoice == 'official')) {
417: nextstate = 'codepick';
418: } else {
419: $nextstate_setter
420: }
1.1 raeburn 421: formname.state.value= nextstate;
422: formname.submit();
423: }
424: return;
425: }
426:
1.2 raeburn 427: function check_can_request(crschoice,actionchoice) {
1.1 raeburn 428: var official = '';
429: var unofficial = '';
430: var community = '';
431: END
432:
433: foreach my $item (keys(%{$can_request})) {
434: $js .= "
435: $item = 1;
436: ";
437: }
438: my %lt = &Apache::lonlocal::texthash(
439: official => 'You are not permitted to request creation of an official course in this domain.',
440: unofficial => 'You are not permitted to request creation of an unofficial course in this domain.',
441: community => 'You are not permitted to request creation of a community this domain.',
442: all => 'You must choose a specific course type when making a new course request.\\nAll types is not allowed.',
443: );
444: $js .= <<END;
445: if (crschoice == 'official') {
446: if (official != 1) {
447: alert("$lt{'official'}");
448: return false;
449: }
450: } else {
451: if (crschoice == 'unofficial') {
452: if (unofficial != 1) {
453: alert("$lt{'unofficial'}");
454: return false;
455: }
456: } else {
457: if (crschoice == 'community') {
458: if (community != 1) {
459: alert("$lt{'community'}");
460: return false;
461: }
462: } else {
463: if (actionchoice == 'new') {
464: alert("$lt{'all'}");
465: return false;
466: }
467: }
468: }
469: }
470: return true;
471: }
472:
473: END
474:
1.3 raeburn 475: $r->print(&header('Course Requests',$js.$jscript,$loaditems).$crumb.
476: '<div>'.
1.1 raeburn 477: '<form name="domforcourse" method="post" action="/adm/requestcourse">'.
478: &Apache::lonhtmlcommon::start_pick_box().
1.8 raeburn 479: &Apache::lonhtmlcommon::row_title('Course Domain').
1.1 raeburn 480: &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange));
481: if (!$onchange) {
482: $r->print(' <input type="submit" name="godom" value="'.
483: &mt('Change').'" />');
484: }
485: $r->print(&Apache::lonhtmlcommon::row_closure(1).
486: &Apache::lonhtmlcommon::end_pick_box().'</form></div>');
487:
1.2 raeburn 488: my $formname = 'requestcrs';
1.1 raeburn 489: my $nexttext = &mt('Next');
490: $r->print('<div><form name="'.$formname.'" method="post" action="/adm/requestcourse">'.
491: &Apache::lonhtmlcommon::start_pick_box().
492: &Apache::lonhtmlcommon::row_title('Action').'
493: <input type="hidden" name="showdom" value="'.$dom.'" />
494: <select size="1" name="action" >
1.2 raeburn 495: <option value="new">'.&mt('New request').'</option>
1.1 raeburn 496: <option value="view">'.&mt('View/Modify/Cancel pending requests').'</option>
497: <option value="log">'.&mt('View request history').'</option>
498: </select>'.
499: &Apache::lonhtmlcommon::row_closure().
500: &Apache::lonhtmlcommon::row_title('Course Type').'
501: <select size="1" name="crstype">
1.4 raeburn 502: <option value="any">'.&mt('All types').'</option>');
503: if ((ref($types) eq 'ARRAY') && (ref($typename) eq 'HASH')) {
504: foreach my $type (@{$types}) {
505: my $selected = '';
506: if ($type eq 'official') {
507: $selected = ' selected="selected"';
508: }
509: $r->print('<option value="'.$type.'"'.$selected.'>'.$typename->{$type}.
510: '</option>'."\n");
511: }
512: }
513: $r->print('</select>
1.1 raeburn 514: <input type="hidden" name="state" value="crstype" />'.
515: &Apache::lonhtmlcommon::row_closure(1).
516: &Apache::lonhtmlcommon::end_pick_box().'<br />
1.2 raeburn 517: <input type="button" name="next" value="'.$nexttext.'" onclick="javascript:nextPage(document.'.$formname.')" />
1.1 raeburn 518: </form></div>');
519: $r->print(&Apache::loncommon::end_page());
520: return;
521: }
522:
523: sub request_administration {
1.3 raeburn 524: my ($r,$action,$state,$page,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.2 raeburn 525: my $js;
526: if (($action eq 'new') || ($action eq 'view')) {
527: $js = <<END;
1.1 raeburn 528:
529: function nextPage(formname,nextstate) {
530: formname.state.value= nextstate;
531: formname.submit();
532: }
533: function backPage(formname,prevstate) {
534: formname.state.value = prevstate;
535: formname.submit();
536: }
537:
538: END
1.2 raeburn 539: }
540: if ($action eq 'new') {
541: my $jsextra;
1.1 raeburn 542: unless (($state eq 'review') || ($state eq 'process')) {
1.2 raeburn 543: $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom);
1.1 raeburn 544: }
1.3 raeburn 545: $r->print(&header('Request a course',$js.$jscript,$loaditems,$jsextra).$crumb);
1.8 raeburn 546: &print_request_form($r,$action,$state,$page,$states,$dom);
1.2 raeburn 547: } elsif ($action eq 'view') {
1.3 raeburn 548: $r->print(&header('Manage course requests',$js.$jscript,$loaditems).$crumb);
1.11 ! raeburn 549: if ($state eq 'pick_request') {
! 550: $r->print(&print_request_status($dom));
! 551: }
1.1 raeburn 552: } elsif ($action eq 'log') {
1.11 ! raeburn 553: $r->print(&coursereq_log('View request log',$jscript,$loaditems).$crumb);
1.1 raeburn 554: }
1.2 raeburn 555: $r->print(&Apache::loncommon::end_page());
1.1 raeburn 556: return;
557: }
558:
559: sub print_request_form {
1.2 raeburn 560: my ($r,$action,$state,$page,$states,$dom) = @_;
1.1 raeburn 561: my $formname = 'requestcrs';
1.2 raeburn 562: my ($next,$prev,$message,$output,$codepicker,$crstype);
563: $prev = $states->{$action}[$page-1];
564: $next = $states->{$action}[$page+1];
1.4 raeburn 565: my %navtxt = &Apache::lonlocal::texthash (
1.10 raeburn 566: prev => 'Back',
1.4 raeburn 567: next => 'Next',
568: );
1.2 raeburn 569: $crstype = $env{'form.crstype'};
1.1 raeburn 570: $r->print('<form name="'.$formname.'" method="post" action="/adm/requestcourse">');
1.2 raeburn 571: my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
1.1 raeburn 572: if ($crstype eq 'official') {
1.2 raeburn 573: if ($env{'form.instcode'} ne '') {
574: $instcode = $env{'form.instcode'};
575: }
576: }
577: if ($prev eq 'codepick') {
1.4 raeburn 578: if ($crstype eq 'official') {
579: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
580: \%cat_order,\@code_order);
581: }
1.2 raeburn 582: if (@code_order > 0) {
583: my $message;
584: if ($instcode eq '') {
1.1 raeburn 585: foreach my $item (@code_order) {
1.2 raeburn 586: $instcode .= $env{'form.instcode_'.$item};
1.1 raeburn 587: }
1.2 raeburn 588: $r->print('<input type="hidden" name="instcode" value="'.$instcode.'" />'."\n");
1.1 raeburn 589: }
590: if ($instcode ne '') {
1.2 raeburn 591: $code_chk = &Apache::lonnet::auto_validate_instcode('',$dom,$instcode);
1.1 raeburn 592: if ($code_chk eq 'ok') {
593: $message = '<div class="LC_info">'.
594: &mt('The chosen course category [_1] is valid.','<b>'.
1.2 raeburn 595: $instcode.'</b>').'</div>';
1.1 raeburn 596: } else {
597: $message = '<div class="LC_warning">'.
598: &mt('No course was found matching your choice of institutional course category.');
599: if ($code_chk ne '') {
600: $message .= '<br />'.$code_chk;
601: }
602: $message .= '</div>';
603: }
1.2 raeburn 604: } else {
605: $message = '<div class="LC_warning">'.
606: &mt('No course was found matching your choice of institutional course category.');
1.1 raeburn 607: }
1.2 raeburn 608: unless ($code_chk eq 'ok') {
609: $prev = 'crstype';
610: }
611: $r->print($message);
1.1 raeburn 612: }
1.2 raeburn 613: }
614: if ($prev eq 'crstype') {
1.4 raeburn 615: if ($crstype eq 'official') {
616: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
617: \%cat_order,\@code_order);
618: }
1.2 raeburn 619: if (@code_order > 0) {
1.1 raeburn 620: $codepicker = &coursecode_form($dom,'instcode',\@codetitles,
621: \%cat_titles,\%cat_order);
1.2 raeburn 622: if ($codepicker) {
623: $r->print('<div>'.&Apache::lonhtmlcommon::start_pick_box().$codepicker.
624: &Apache::lonhtmlcommon::end_pick_box().'</div>');
625: } else {
626: $r->print(&courseinfo_form($dom,$formname,$crstype));
627: }
628: } else {
629: $r->print(&courseinfo_form($dom,$formname,$crstype));
1.1 raeburn 630: }
1.2 raeburn 631: } elsif ($prev eq 'codepick') {
632: $r->print(&courseinfo_form($dom,$formname,$crstype));
633: } elsif ($state eq 'enrollment') {
1.4 raeburn 634: if ($crstype eq 'official') {
635: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
636: \%cat_order,\@code_order);
637: }
1.2 raeburn 638: $r->print(&print_enrollment_menu($formname,$instcode,$dom,\@codetitles,
639: \%cat_titles,\%cat_order,\@code_order));
640: } elsif ($state eq 'personnel') {
1.8 raeburn 641: $r->print(&print_personnel_menu($dom,$formname,$crstype));
1.4 raeburn 642: } elsif ($state eq 'review') {
643: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
644: \%cat_order,\@code_order);
645: $r->print(&print_review($formname,$dom,\@codetitles,\%cat_titles,\%cat_order,
646: \@code_order));
647: $navtxt{'next'} = &mt('Submit course request');
1.10 raeburn 648: } elsif ($state eq 'process') {
649: if ($crstype eq 'official') {
650: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
651: \%cat_order,\@code_order);
652: }
653: my $result = &print_request_outcome($dom,\@codetitles,\@code_order);
1.1 raeburn 654: }
1.2 raeburn 655: my @excluded = ('counter');
656: my %elements = &form_elements($dom);
657: if (ref($states) eq 'HASH') {
658: if (ref($states->{$action}) eq 'ARRAY') {
659: my @items = @{$states->{$action}};
660: my $numitems = scalar(@items);
661: if ($numitems) {
662: for (my $i=$numitems-1; $i>=0; $i--) {
663: if (ref($elements{$action}) eq 'HASH') {
664: if (ref($elements{$action}{$items[$i]}) eq 'HASH') {
665: foreach my $key (keys(%{$elements{$action}{$items[$i]}})) {
666: push(@excluded,$key);
667: }
668: }
669: }
670: last if ($items[$i] eq $state);
671: }
672: }
673: }
674: }
675: if (grep(/^instcode_/,@excluded)) {
676: push(@excluded,'instcode');
1.1 raeburn 677: }
1.2 raeburn 678: $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</form>');
1.4 raeburn 679: &display_navbuttons($r,$formname,$prev,$navtxt{'prev'},$next,$navtxt{'next'});
1.1 raeburn 680: return;
681: }
682:
1.2 raeburn 683: sub print_enrollment_menu {
684: my ($formname,$instcode,$dom,$codetitles,$cat_titles,$cat_order,$code_order) =@_;
685: my ($sections,$autoenroll,$access_dates);
686: my $starttime = time;
687: my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
688:
689: my %accesstitles = (
690: 'start' => 'Default start access',
691: 'end' => 'Default end accss',
692: );
693: my %enrolltitles = (
694: 'start' => 'Start auto-enrollment',
695: 'end' => 'End auto-enrollment',
696: );
697: if ($env{'form.crstype'} eq 'official') {
698: if (&Apache::lonnet::auto_run('',$dom)) {
699: my ($section_form,$crosslist_form,$autoenroll_form);
700: $section_form = &inst_section_selector($dom,$instcode);
701: my $crosslisttotal = $env{'form.crosslisttotal'};
702: if (!defined($crosslisttotal)) {
703: $crosslisttotal = 1;
704: }
705: if ($env{'form.addcrosslist'}) {
706: $crosslisttotal ++;
707: }
708: for (my $i=0; $i<$crosslisttotal; $i++) {
709: $crosslist_form .= &coursecode_form($dom,'crosslist',$codetitles,
710: $cat_titles,$cat_order,$i);
711: }
712: if ($crosslist_form) {
713: $crosslist_form .=
714: &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
715: '<input name="crosslisttotal" type="hidden" value="'.$crosslisttotal.'" />'.
716: '<input name="addcrosslist" type="checkbox" value="'.$crosslisttotal.'"'.
717: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
718: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1);
719: }
720: if ($section_form || $crosslist_form) {
721: $sections = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
722: $section_form.$crosslist_form.
723: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
724: }
725: $autoenroll_form =
726: &Apache::lonhtmlcommon::row_title(&mt('Add registered students automatically')).
727: '<span class="LC_nobreak"><label>'.
728: '<input type="radio" name="autoadds" value="1">'.
729: &mt('Yes').'</label>'.(' 'x3).'<label>'.
730: '<input type="radio" name="autoadds" value="0" checked="checked">'.
731: &mt('No').'</label></span>'.
732: &Apache::lonhtmlcommon::row_closure().
733: &Apache::lonhtmlcommon::row_title(&mt('Drop unregistered students automatically')).
734: '<span class="LC_nobreak"><label>'.
735: '<input type="radio" name="autodrops" value="1">'.
736: &mt('Yes').'</label>'.(' 'x3).'<label>'.
737: '<input type="radio" name="autodrops" value="0" checked="checked">'.
738: &mt('No').'</label></span>'.
739: &Apache::lonhtmlcommon::row_closure().
740: &date_setting_table($starttime,$endtime,$formname,'enroll',%enrolltitles);
741: if ($autoenroll_form) {
742: $autoenroll = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
743: $autoenroll_form.
744: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
745: }
746: }
747: }
748: my $access_dates_form =
749: &date_setting_table($starttime,$endtime,$formname,'access',%accesstitles);
750: if ($access_dates_form) {
751: $access_dates = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
752: $access_dates_form.
753: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
754: }
755: return $sections.$autoenroll.$access_dates;
756: }
757:
1.1 raeburn 758: sub inst_section_selector {
1.2 raeburn 759: my ($dom,$instcode) = @_;
760: my @sections = &Apache::lonnet::auto_get_sections(undef,$dom,$instcode);
761: my $sectotal = scalar(@sections);
1.1 raeburn 762: my $output;
1.2 raeburn 763: if ($sectotal) {
764: $output .= &Apache::lonhtmlcommon::row_title('Sections').
765: &Apache::loncommon::start_data_table().
766: &Apache::loncommon::start_data_table_row().
767: '<th>'.&mt('Include?').'<input type="hidden" name="sectotal" '.
768: 'value="'.$sectotal.'"</th>'.
769: '<th>'.&mt('Institutional Section').'</th>'.
770: '<th>'.&mt('LON-CAPA section').'</th>'.
771: &Apache::loncommon::end_data_table_row();
772: for (my $i=0; $i<@sections; $i++) {
1.1 raeburn 773: my $colflag = $i%2;
774: $output .= &Apache::loncommon::start_data_table_row().
1.2 raeburn 775: '<td><input type="checkbox" name="sec_'.$i.
776: '" checked="checked" /></td>'.
777: '<td>'.$sections[$i].
1.1 raeburn 778: '<input type="hidden" name="secnum_'.$i.'" value="'.
1.2 raeburn 779: $sections[$i].'" /></td>'.
1.1 raeburn 780: '<td><input type="text" size="10" name="loncapasec_'.$i.
1.2 raeburn 781: '" value="'.$sections[$i].'" /></td>'.
1.1 raeburn 782: &Apache::loncommon::end_data_table_row();
783: }
1.2 raeburn 784: $output .= &Apache::loncommon::end_data_table().
785: &Apache::lonhtmlcommon::row_closure();
1.1 raeburn 786: }
787: return $output;
788: }
789:
1.2 raeburn 790: sub date_setting_table {
791: my ($starttime,$endtime,$formname,$suffix,%datetitles) = @_;
792: my ($perpetual,$table);
793: my $startform = &Apache::lonhtmlcommon::date_setter($formname,'start'.$suffix,
794: $starttime,'','','',1,'','','',1);
795: my $endform = &Apache::lonhtmlcommon::date_setter($formname,'end'.$suffix,
796: $endtime,'','','',1,'','','',1);
797: if ($suffix eq 'access') {
798: $perpetual = ' <span class="LC_nobreak"><label>'.
799: '<input type="checkbox" name="no_end_date" />'.
800: &mt('No end date').'</label></span>';
801: }
802: $table = &Apache::lonhtmlcommon::row_title($datetitles{'start'}).
803: $startform.
804: &Apache::lonhtmlcommon::row_closure().
805: &Apache::lonhtmlcommon::row_title($datetitles{'end'}).
806: $endform.$perpetual.
807: &Apache::lonhtmlcommon::row_closure(1);
808: return $table;
809: }
810:
811: sub print_personnel_menu {
1.8 raeburn 812: my ($dom,$formname,$crstype) = @_;
1.2 raeburn 813: my $output = '<div>'.&Apache::lonhtmlcommon::start_pick_box();
814: my $persontotal = $env{'form.persontotal'};
815: if (!defined($persontotal)) {
816: $persontotal = 1;
817: }
818: if ($env{'form.addperson'}) {
819: $persontotal ++;
820: }
821: my $userlinktxt = &mt('Set User');
822: my @items = ('uname','dom','last','first','email','hidedom');
823:
824: my $roleoptions;
825: my @roles = &Apache::lonuserutils::roles_by_context('course');
1.8 raeburn 826: my $type = 'Course';
827: if ($crstype eq 'community') {
828: $type = 'Community';
829: }
1.2 raeburn 830: foreach my $role (@roles) {
1.8 raeburn 831: my $plrole=&Apache::lonnet::plaintext($role,$type);
1.2 raeburn 832: $roleoptions .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
833: }
834: my %customroles=&Apache::lonuserutils::my_custom_roles();
835: if (keys(%customroles) > 0) {
836: foreach my $cust (sort(keys(%customroles))) {
837: my $custrole='cr_cr_'.$env{'user.domain'}.
838: '_'.$env{'user.name'}.'_'.$cust;
839: $roleoptions .= ' <option value="'.$custrole.'">'.$cust.'</option>'."\n";
840: }
841: }
842:
843: my @currsecs;
844: if ($env{'form.sectotal'}) {
845: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
846: if (defined($env{'form.loncapasec_'.$i})) {
847: my $lcsec = $env{'form.loncapasec_'.$i};
848: unless (grep(/^\Q$lcsec\E$/,@currsecs)) {
849: push(@currsecs,$lcsec);
850: }
851: }
852: }
853: }
854:
855: my ($existtitle,$existops,$existmult,$newtitle,$seccolspan);
856: if (@currsecs) {
857: my $existsize = scalar(@currsecs);
858: if ($existsize > 3) {
859: $existsize = 3;
860: }
861: if ($existsize > 1) {
862: $existmult = ' multiple="multiple" size="'.$existsize.'" ';
863: }
864: @currsecs = sort { $a <=> $b } (@currsecs);
865: $existtitle = &mt('Official').': ';
866: $existops = '<option value="">'.&mt('None').'</option>';
867: foreach my $sec (@currsecs) {
868: $existops .= '<option value="'.$sec.'">'.$sec.'</option>'."\n";
869: }
870: $seccolspan = ' colspan="2"';
871: $newtitle = &mt('Other').': ';
872: }
873:
874: for (my $i=0; $i<$persontotal; $i++) {
875: my @linkargs = map { 'person_'.$i.'_'.$_ } (@items);
876: my $linkargstr = join("','",@linkargs);
1.7 raeburn 877: my $userlink = &Apache::loncommon::selectuser_link($formname,@linkargs,$dom,$userlinktxt);
1.2 raeburn 878: my $uname_form = '<input type="text" name="person_'.$i.'_uname" value=""'.
879: ' onFocus="this.blur();'.
1.7 raeburn 880: 'openuserbrowser('."'$formname','$linkargstr','$dom'".');" />';
1.2 raeburn 881: my $onchange = 'javascript:fix_domain('."'$formname','person_".$i."_dom',".
882: "'person_".$i."_hidedom'".');'.
1.7 raeburn 883: 'openuserbrowser('."'$formname','$linkargstr','$dom'".');';
1.2 raeburn 884: my $udom_form = &Apache::loncommon::select_dom_form($dom,'person_'.$i.'_dom','',
885: 1,$onchange).
886: '<input type="hidden" name="person_'.$i.'_hidedom" value="'.$dom.'" />';
887: my %form_elems;
888: foreach my $item (@items) {
889: next if (($item eq 'dom') || ($item eq 'uname') || ($item eq 'hidedom'));
890: $form_elems{$item} = '<input type="text" name="person_'.$i.'_'.$item.'" '.
891: 'value="" readonly="readonly" />';
892: }
893: my $roleselector = '<select name="person_'.$i.'_role">'."\n".
894: $roleoptions.'</select>';
895: my $sectionselector;
896: if (@currsecs) {
897: $sectionselector = $existtitle.'<select name="person_'.$i.'_sec"'.
898: $existmult.'>'."\n".$existops.'</select>'.(' ' x3);
899: }
900: $sectionselector .= $newtitle.
901: '<input type="text" name="person_'.$i.'_newsec" size="15" value="" />'.
902: '<input type="hidden" name="person_'.$i.'_sections" value="" />'."\n";
903:
904: $output .=
905: &Apache::lonhtmlcommon::row_title(&mt('Additional Personnel').'<br />'.
906: '<span class="LC_nobreak">'.$userlink.
907: '</span>').
908: '<table><tr><td align="center" valign="top">'.&mt('Username').'<br />'.$uname_form.'</td>'."\n".
909: '<td align="center" valign="top" colspan="2">'.&mt('Domain').'<br />'.$udom_form.'</td></tr><tr>'."\n".
910: '<td align="center" valign="top">'.&mt('First Name').'<br />'.$form_elems{'first'}.'</td>'."\n".
911: '<td align="center" valign="top">'.&mt('Last Name').'<br />'.$form_elems{'last'}.'</td>'."\n".
912: '<td align="center" valign="top">'.&mt('E-mail').'<br />'.$form_elems{email}.'</td></tr>'."\n".
913: '<tr><td align="center" valign="top">'.&mt('Role').'<br />'.$roleselector.'</td>'."\n".
914: '<td'.$seccolspan.' align="center" valign="top">'.&mt('Section(s)').'<br />'.$sectionselector.'</td>'."\n".
915: '</tr></table>'.&Apache::lonhtmlcommon::row_closure();
916: }
917: $output .= &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
918: '<input name="persontotal" type="hidden" value="'.$persontotal.'" />'.
919: '<input name="addperson" type="checkbox" value="'.$persontotal.'"'.
920: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
921: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1).
922: &Apache::lonhtmlcommon::end_pick_box().'</div>';
923: return $output;
924: }
925:
1.1 raeburn 926: sub print_request_status {
1.11 ! raeburn 927: my ($dom) = @_;
1.10 raeburn 928: my %requests = &Apache::lonnet::dumpstore('courserequests',$env{'user.domain'},
929: $env{'user.name'});
1.11 ! raeburn 930: my ($output,$formname,%queue_by_date);
1.10 raeburn 931: foreach my $key (keys(%requests)) {
932: if (ref($requests{$key}) eq 'HASH') {
933: my ($cdom,$cnum) = split('_',$key);
934: next if ($cdom ne $dom);
935: my $entry;
936: my $timestamp = $requests{$key}{'timestamp'};
937: my $crstype = $requests{$key}{'crstype'};
938: my $status = $requests{$key}{'status'};
939: next unless (($env{'form.crstype'} eq 'all') ||
940: ($env{'form.crstype'} eq $crstype));
941: next unless (($status eq 'approval') || ($status eq 'pending'));
942: if (ref($requests{$key}{'details'}) eq 'HASH') {
943: $entry = $key.':'.$crstype.':'.$requests{$key}{'details'}{'cdesc'};
944: if ($crstype eq 'official') {
945: $entry .= ':'.$requests{$key}{'details'}{'instcode'};
946: }
947: }
948: if ($entry ne '') {
949: if (exists($queue_by_date{$timestamp})) {
950: if (ref($queue_by_date{$timestamp}) eq 'ARRAY') {
951: push(@{$queue_by_date{$timestamp}},$entry);
952: }
953: } else {
954: @{$queue_by_date{$timestamp}} = ($entry);
955: }
956: }
957: }
958: }
1.11 ! raeburn 959: $formname = 'requestcrs';
1.10 raeburn 960: my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date));
1.11 ! raeburn 961: $output = '<form method="post" name="'.$formname.'" action="/adm/requestcourse" />'."\n".
1.10 raeburn 962: '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n".
963: '<input type="hidden" name="state" value="'.$env{'form.state'}.'" />'."\n".
964: '<input type="hidden" name="crstype" value="'.$env{'form.crstype'}.'" />'."\n";
965: if (@sortedtimes > 0) {
966: $output .= &Apache::loncommon::start_data_table().
967: &Apache::loncommon::start_data_table_header_row().
968: '<th>'.&mt('Action').'</th>'.
969: '<th>'.&mt('Description').'</th>';
970: if ($env{'form.crstype'} eq 'all') {
971: $output .= '<th>'.&mt('Type').'</th>';
972: }
973: if (($env{'form.crstype'} eq 'all') || ($env{'form.crstype'} eq 'official')) {
974: $output .= '<th>'.&mt('Institutional Code').'</th>';
975: }
976: $output .= '<th>'.&mt('Date requested').'</th>'.
977: &Apache::loncommon::end_data_table_header_row();
978: my $count = 0;
979: foreach my $item (@sortedtimes) {
980: my $showtime = &Apache::lonlocal::locallocaltime($item);
981: if (ref($queue_by_date{$item}) eq 'ARRAY') {
982: foreach my $request (sort(@{$queue_by_date{$item}})) {
983: my ($key,$type,$desc,$instcode) = split(':',$request);
984: my ($cdom,$cnum) = split('_',$key);
985: $output .= &Apache::loncommon::start_data_table_row().
986: '<td><input type="button" value="'.&mt('Select').'" onclick="javascript:viewrequest('."'$cdom','$cnum'".')" /></td>'.
987: '<td>'.$desc.'</td>';
988: if ($env{'form.crstype'} eq 'all') {
989: $output .= '<td>'.&course_types($type).'</td>';
990: }
991: if (($env{'form.crstype'} eq 'all') ||
992: ($env{'form.crstype'} eq 'official')) {
993: $output .= '<td>'.$instcode.'</td>';
994: }
995: $output .= '<td>'.$showtime.'</td>'.
996: &Apache::loncommon::end_data_table_row();
997: }
998: }
999: }
1000: $output .= &Apache::loncommon::end_data_table();
1001: } else {
1.11 ! raeburn 1002: $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 1003: }
1004: $output .= '
1005: <input type="button" name="prev" value="'.&mt('Back').'" onclick="javascript:backPage(document.'.$formname.",'crstype'".')" />
1.11 ! raeburn 1006: </form>';
1.10 raeburn 1007: return $output;
1.1 raeburn 1008: }
1009:
1010: sub print_request_logs {
1.10 raeburn 1011: my ($jscript,$loaditems,$crumb) = @_;
1.1 raeburn 1012: return;
1013: }
1014:
1015: sub print_review {
1.4 raeburn 1016: my ($formname,$dom,$codetitles,$cat_titles,$cat_order,$code_order) = @_;
1017: my ($types,$typename) = &course_types();
1018: my ($owner,$ownername,$owneremail);
1019: $owner = $env{'user.name'}.':'.$env{'user.domain'};
1020: $ownername = &Apache::loncommon::plainname($env{'user.name'},
1021: $env{'user.domain'},'first');
1022: my %emails = &Apache::loncommon::getemails();
1023: foreach my $email ('permanentemail','critnotification','notification') {
1024: $owneremail = $emails{$email};
1025: last if ($owneremail ne '');
1026: }
1027: my ($inst_headers,$inst_values,$crstypename,$enroll_headers,$enroll_values,
1028: $section_headers,$section_values,$personnel_headers,$personnel_values);
1029:
1030: $crstypename = $env{'form.crstype'};
1031: if (ref($typename) eq 'HASH') {
1032: unless ($typename->{$env{'form.crstype'}} eq '') {
1033: $crstypename = $typename->{$env{'form.crstype'}};
1034: }
1035: }
1036:
1037: $inst_headers = '<th>'.&mt('Description').'</th><th>'.&mt('Type').'</th>';
1038: $inst_values = '<td>'.$env{'form.cdescr'}.'</td><td>'.$crstypename.'</td>';
1039:
1040: if ($env{'form.crstype'} eq 'official') {
1041: if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH')) {
1042: foreach my $title (@{$codetitles}) {
1043: if ($env{'form.instcode_'.$title} ne '') {
1044: $inst_headers .= '<th>'.$title.'</th>';
1045: my $longitem = $env{'form.instcode_'.$title};
1046: if (ref($cat_titles->{$title}) eq 'HASH') {
1047: if ($cat_titles->{$title}{$env{'form.instcode_'.$title}} ne '') {
1048: $longitem = $cat_titles->{$title}{$env{'form.instcode_'.$title}};
1049: }
1050: }
1051: $inst_values .= '<td>'.$longitem.'</td>';
1052: }
1053: }
1054: }
1055: if (&Apache::lonnet::auto_run('',$dom)) {
1056: $enroll_headers = '<th>'.&mt('Automatic Adds').'</th>'.
1057: '<th>'.&mt('Automatic Drops').'</th>'.
1058: '<th>'.&mt('Enrollment Starts').'</th>'.
1059: '<th>'.&mt('Enrollment Ends').'</th>';
1060: $section_headers = '<th>'.&mt('Sections').'</th>'.
1061: '<th>'.&mt('Crosslistings').'</th>';
1062:
1063: my ($startenroll,$endenroll) = &dates_from_form('startenroll','endenroll');
1064: my @autoroster = (&mt('No'),&mt('Yes'));
1065: $enroll_values = '<td>'.$autoroster[$env{'form.autoadds'}].'</td>'.
1066: '<td>'.$autoroster[$env{'form.autodrops'}].'</td>'.
1067: '<td>'.&Apache::lonlocal::locallocaltime($startenroll).'</td>'.
1068: '<td>'.&Apache::lonlocal::locallocaltime($endenroll).'</td>';
1.6 raeburn 1069: $section_values = '<td><table class="LC_innerpickbox"><tr><th>'.
1070: &mt('Institutional section').'</th>'.
1071: '<th>'.&mt('LON-CAPA section').'</th></tr>';
1.5 raeburn 1072: my $secinfo;
1.4 raeburn 1073: if ($env{'form.sectotal'} > 0) {
1074: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
1075: if ($env{'form.sec_'.$i}) {
1.5 raeburn 1076: $secinfo .= '<tr><td>'.$env{'form.secnum_'.$i}.'</td><td>';
1.4 raeburn 1077: if ($env{'form.loncapasec_'.$i} ne '') {
1.5 raeburn 1078: $secinfo .= $env{'form.loncapasec_'.$i};
1079: } else {
1080: $secinfo .= &mt('None');
1.4 raeburn 1081: }
1.5 raeburn 1082: $secinfo .= '</td></tr>';
1.4 raeburn 1083: }
1084: }
1085: }
1.6 raeburn 1086: if ($secinfo eq '') {
1087: $secinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
1.5 raeburn 1088: }
1.6 raeburn 1089: $section_values .= $secinfo.'</table></td><td>'.
1090: '<table class="LC_innerpickbox"><tr><th>'.
1091: &mt('Institutional course/section').'</th>'.
1092: '<th>'.&mt('LON-CAPA section').'</th></tr>';
1.5 raeburn 1093: my $xlistinfo;
1.4 raeburn 1094: if ($env{'form.crosslisttotal'}) {
1095: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
1096: if ($env{'form.crosslist_'.$i}) {
1.5 raeburn 1097: $xlistinfo .= '<tr><td>';
1098: if (ref($code_order) eq 'ARRAY') {
1099: if (@{$code_order} > 0) {
1100: foreach my $item (@{$code_order}) {
1101: $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
1.4 raeburn 1102: }
1103: }
1104: }
1.5 raeburn 1105: $xlistinfo .= $env{'form.crosslist_'.$i.'_instsec'}.'</td><td>';
1.4 raeburn 1106: if ($env{'form.crosslist_'.$i.'_lcsec'}) {
1.5 raeburn 1107: $xlistinfo .= $env{'form.crosslist_'.$i.'_lcsec'};
1108: } else {
1109: $xlistinfo .= &mt('None');
1.4 raeburn 1110: }
1.5 raeburn 1111: $xlistinfo .= '</td></tr>';
1.4 raeburn 1112: }
1113: }
1114: }
1.6 raeburn 1115: if ($xlistinfo eq '') {
1116: $xlistinfo = '<tr><td colspan="2">'.&mt('None').'</td></tr>';
1.5 raeburn 1117: }
1.6 raeburn 1118: $section_values .= $xlistinfo.'</table></td>';
1.4 raeburn 1119: }
1120: }
1121:
1122: my %ctxt = &clone_text();
1123: $inst_headers .= '<th>'.&mt('Clone From').'</th>';
1124: if (($env{'form.clonecourse'} =~ /^$match_name$/) &&
1125: ($env{'form.clonedomain'} =~ /^$match_domain$/)) {
1126: my %coursehash =
1127: &Apache::lonnet::courseiddump($env{'form.clonedomain'},'.',1,'.','.',
1128: $env{'form.clonecourse'},undef,undef,'.');
1129: my $cloneid = $env{'form.clonedomain'}.'_'.$env{'form.clonecourse'};
1130: if (ref($coursehash{$cloneid}) eq 'HASH') {
1131: $inst_headers .= '<th>'.$ctxt{'dsh'}.'</th>';
1132: my $clonedesc = $coursehash{$cloneid}{'description'};
1133: my $cloneinst = $coursehash{$cloneid}{'inst_code'};
1134:
1135: $inst_values .= '<td>'.$clonedesc.' ';
1136: if ($cloneinst ne '') {
1137: $inst_values .= &mt('([_1] in [_2])',$cloneinst,$env{'form.clonedomain'});
1138: } else {
1139: $inst_values .= &mt('(from [_1])',$env{'form.clonedomain'});
1140: }
1141: $inst_values .= '</td><td>';
1142: if ($env{'form.datemode'} eq 'preserve') {
1143: $inst_values .= $ctxt{'pcd'};
1144: } elsif ($env{'form.datemode'} eq 'shift') {
1145: $inst_values .= &mt('Shift dates by [_1] days',$env{'form.dateshift'});
1146: } else {
1147: $inst_values .= $ctxt{'ncd'};
1148: }
1149: $inst_values .= '</td>';
1150: } else {
1151: $inst_values .= '<td>'.&mt('Unknown').'</td>';
1152: }
1153: } else {
1154: $inst_values .= '<td>'.&mt('None').'</td>';
1155: }
1156: $enroll_headers .= '<th>'.&mt('Access Starts').'</th>'.
1157: '<th>'.&mt('Access Ends').'</th>';
1158: my ($startaccess,$endaccess) = &dates_from_form('startaccess','endaccess');
1159: $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($startaccess).'</td>';
1160: if ($endaccess == 0) {
1161: $enroll_values .= '<td>'.&mt('No end date').'</td>';
1162: } else {
1163: $enroll_values .= '<td>'.&Apache::lonlocal::locallocaltime($endaccess).'</td>';
1164: }
1165:
1166: my $container = 'Course';
1167: if ($env{'form.crstype'} eq 'community') {
1168: $container = 'Community';
1169: }
1170:
1171: $personnel_headers = '<th>'.&mt('Name').'</th><th>'.&mt('Username:Domain').
1172: '</th><th>'.&mt('Role').'</th><th>'.&mt('LON-CAPA Sections').
1173: '</th>';
1174: $personnel_values .= '<tr><td>'.$ownername.'</td><td>'.$owner.'</td>'.
1175: '<td>'.&Apache::lonnet::plaintext('cc',$container).'</td>'.
1176: '<td>'.&mt('None').'</td></tr>';
1177: for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
1178: if ($env{'form.person_'.$i.'_uname'} ne '') {
1179: $personnel_values .=
1180: '<tr><td>'.$env{'form.person_'.$i.'_first'}.' '.
1181: $env{'form.person_'.$i.'_last'}.'</td>'.
1182: '<td>'.$env{'form.person_'.$i.'_uname'}.':'.
1183: $env{'form.person_'.$i.'_dom'}.'</td>'.
1184: '<td>'.&Apache::lonnet::plaintext($env{'form.person_'.$i.'_role'},
1185: $container).'</td>'.
1186: '<td>'.$env{'form.person_'.$i.'_sections'}.'</td></tr>';
1187: }
1188: }
1189: my $output = '<p>'.&mt('Review the details of the course request before submission.').'</p>'.
1190: '<div>'.&Apache::lonhtmlcommon::start_pick_box().
1191: &Apache::lonhtmlcommon::row_title(&mt('Owner')).
1.6 raeburn 1192: '<table class="LC_innerpickbox"><tr>'.
1.4 raeburn 1193: '<th>'.&mt('Name').'</th>'.
1194: '<th>'.&mt('Username:Domain').'</th>'.
1195: '<th>'.&mt('E-mail address').'</th>'.
1196: '</tr><tr>'."\n".
1197: '<td>'.$ownername.'</td><td>'.$owner.'</td>'.
1198: '<td>'.$owneremail.'</td>'.
1199: '</tr></table>'."\n".
1200: &Apache::lonhtmlcommon::row_closure().
1.5 raeburn 1201: &Apache::lonhtmlcommon::row_title(&mt('Description')).
1.4 raeburn 1202: '<table class="LC_innerpickbox"><tr>'.$inst_headers.'</tr>'."\n".
1203: '<tr>'.$inst_values.'</tr></table>'."\n".
1204: &Apache::lonhtmlcommon::row_closure().
1205: &Apache::lonhtmlcommon::row_title(&mt('Enrollment')).
1206: '<table class="LC_innerpickbox"><tr>'.$enroll_headers.'</tr>'."\n".
1207: '<tr>'.$enroll_values.'</tr></table>'."\n".
1208: &Apache::lonhtmlcommon::row_closure();
1209: if ($section_headers ne '') {
1210: $output .= &Apache::lonhtmlcommon::row_title(&mt('Sections')).
1211: '<table class="LC_innerpickbox"><tr>'.$section_headers.'</tr>'."\n".
1212: '<tr>'.$section_values.'</tr></table>'."\n".
1213: &Apache::lonhtmlcommon::row_closure();
1214: }
1215: $output .= &Apache::lonhtmlcommon::row_title(&mt('Personnel')).
1216: '<table class="LC_innerpickbox"><tr>'.$personnel_headers.'</tr>'."\n".
1217: $personnel_values.'</table>'."\n".
1218: &Apache::lonhtmlcommon::row_closure(1).
1219: &Apache::lonhtmlcommon::end_pick_box();
1.8 raeburn 1220: my $cnum = &Apache::lonnet::generate_coursenum($dom);
1221: $output .= '<input type="hidden" name="cnum" value="'.$cnum.'" />';
1.4 raeburn 1222: return $output;
1223: }
1224:
1225: sub dates_from_form {
1226: my ($startname,$endname) = @_;
1227: my $startdate = &Apache::lonhtmlcommon::get_date_from_form($startname);
1228: my $enddate = &Apache::lonhtmlcommon::get_date_from_form($endname);
1229: if ($endname eq 'endaccess') {
1230: if (exists($env{'form.no_end_date'}) ) {
1231: $enddate = 0;
1232: }
1233: }
1234: return ($startdate,$enddate);
1.1 raeburn 1235: }
1236:
1237: sub courseinfo_form {
1.2 raeburn 1238: my ($dom,$formname,$crstype) = @_;
1239: my $output = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
1240: &Apache::lonhtmlcommon::row_title('Course Description').
1241: '<input type="text" size="40" name="cdescr" />'.
1242: &Apache::lonhtmlcommon::row_closure(1).
1243: &Apache::lonhtmlcommon::end_pick_box().'</div>'.
1244: '<div>'.&clone_form($dom,$formname,$crstype).'</div>'."\n";
1.1 raeburn 1245: return $output;
1246: }
1247:
1248: sub clone_form {
1249: my ($dom,$formname,$crstype) = @_;
1250: my $type = 'Course';
1251: if ($crstype eq 'community') {
1252: $type = 'Community';
1253: }
1254: my $cloneform = &Apache::loncommon::select_dom_form($dom,'clonedomain').
1.2 raeburn 1255: &Apache::loncommon::selectcourse_link($formname,'clonecourse','clonedomain','','','',$type);
1.4 raeburn 1256: my %lt = &clone_text();
1.2 raeburn 1257: my $output .=
1258: &Apache::lonhtmlcommon::start_pick_box().
1259: &Apache::lonhtmlcommon::row_title($lt{'cid'}).'<label>'.
1260: '<input type="text" size="25" name="clonecourse" value="" onfocus="this.blur();'.
1261: 'opencrsbrowser('."'$formname','clonecourse','clonedomain','','','','$type'".');" />'.
1262: '</label>'.&Apache::lonhtmlcommon::row_closure(1).'<label>'.
1263: &Apache::lonhtmlcommon::row_title($lt{'dmn'}).'</label>'.
1264: $cloneform.'</label>'.&Apache::lonhtmlcommon::row_closure().
1265: &Apache::lonhtmlcommon::row_title($lt{'dsh'}).'<label>'.
1266: '<input type="radio" name="datemode" value="delete" /> '.$lt{'ncd'}.
1267: '</label><br /><label>'.
1268: '<input type="radio" name="datemode" value="preserve" /> '.$lt{'prd'}.
1269: '</label><br /><label>'.
1270: '<input type="radio" name="datemode" value="shift" checked="checked" /> '.
1271: $lt{'shd'}.'</label>'.
1272: '<input type="text" size="5" name="dateshift" value="365" />'.
1273: &Apache::lonhtmlcommon::row_closure(1).
1274: &Apache::lonhtmlcommon::end_pick_box();
1.1 raeburn 1275: return $output;
1276: }
1277:
1.4 raeburn 1278: sub clone_text {
1279: return &Apache::lonlocal::texthash(
1280: 'cid' => 'Course ID',
1281: 'dmn' => 'Domain',
1282: 'dsh' => 'Date Shift',
1283: 'ncd' => 'Do not clone date parameters',
1284: 'prd' => 'Clone date parameters as-is',
1285: 'shd' => 'Shift date parameters by number of days',
1286: );
1287: }
1288:
1.1 raeburn 1289: sub coursecode_form {
1.2 raeburn 1290: my ($dom,$context,$codetitles,$cat_titles,$cat_order,$num) = @_;
1.1 raeburn 1291: my $output;
1.2 raeburn 1292: my %rowtitle = (
1293: instcode => 'Course Category',
1294: crosslist => 'Cross Listed Course',
1295: );
1.1 raeburn 1296: if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH') &&
1297: (ref($cat_order))) {
1.2 raeburn 1298: my ($sel,$instsec,$lcsec);
1299: $sel = $context;
1300: if ($context eq 'crosslist') {
1301: $sel .= '_'.$num;
1302: $instsec = &mt('Institutional section').'<br />'.
1303: '<input type="text" size="10" name="'.$sel.'_instsec" />';
1304: $lcsec = &mt('LON-CAPA section').'<br />'.
1305: '<input type="text" size="10" name="'.$sel.'_lcsec" />';
1306: }
1.1 raeburn 1307: if (@{$codetitles} > 0) {
1308: my $lastitem = pop(@{$codetitles});
1.2 raeburn 1309: my $lastinput = '<input type="text" size="5" name="'.$sel.'_'. $lastitem.'" />';
1.1 raeburn 1310: if (@{$codetitles} > 0) {
1.2 raeburn 1311: $output = &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1312: '<table><tr>';
1.1 raeburn 1313: if ($context eq 'crosslist') {
1.2 raeburn 1314: $output .= '<td>'.&mt('Include?').'<br />'.
1315: '<input type="checkbox" name="'.$sel.'" value="1" /></td>';
1.1 raeburn 1316: }
1317: foreach my $title (@{$codetitles}) {
1318: if (ref($cat_order->{$title}) eq 'ARRAY') {
1319: if (@{$cat_order->{$title}} > 0) {
1320: $output .= '<td align="center">'.$title.'<br />'."\n".
1321: '<select name="'.$sel.'_'.$title.'">'."\n".
1322: ' <option value="" selected="selected">'.
1323: &mt('Select').'</option>'."\n";
1324: foreach my $item (@{$cat_order->{$title}}) {
1325: my $longitem = $item;
1326: if (ref($cat_titles->{$title}) eq 'HASH') {
1327: if ($cat_titles->{$title}{$item} ne '') {
1328: $longitem = $cat_titles->{$title}{$item};
1329: }
1330: }
1331: $output .= '<option value="'.$item.'">'.$longitem.
1332: '</option>'."\n";
1333: }
1334: }
1335: $output .= '</select></td>'."\n";
1336: }
1337: }
1338: if ($context eq 'crosslist') {
1339: $output .= '<td align="center">'.$lastitem.'<br />'."\n".
1.2 raeburn 1340: $lastinput.'</td><td align="center">'.$instsec.'</td>'.
1341: '<td align="center">'.$lcsec.'</td></tr></table>';
1.1 raeburn 1342: } else {
1343: $output .= '</tr></table>'.
1344: &Apache::lonhtmlcommon::row_closure().
1345: &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
1346: $lastinput;
1347: }
1348: } else {
1349: if ($context eq 'crosslist') {
1350: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1.2 raeburn 1351: '<table><tr>'.
1352: '<td align="center">'.$lastitem.'<br />'.$lastinput.'</td>'.
1353: '<td align="center">'.$instsec.'</td><td>'.$lcsec.'</td>'.
1354: '</tr></table>';
1.1 raeburn 1355: } else {
1356: $output .= &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
1357: $lastinput;
1358: }
1359: }
1.2 raeburn 1360: $output .= &Apache::lonhtmlcommon::row_closure(1);
1361: push(@$codetitles,$lastitem);
1362: } elsif ($context eq 'crosslist') {
1363: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1364: '<table><tr><td align="center">'.
1365: '<span class="LC_nobreak">'.&mt('Include?').
1366: '<input type="checkbox" name="'.$sel.'" value="1" /></span>'.
1367: '</td><td align="center">'.&mt('Institutional ID').'<br />'.
1368: '<input type="text" size="10" name="'.$sel.'_instsec" />'.
1369: '</td><td align="center">'.$lcsec.'</td></tr></table>'.
1370: &Apache::lonhtmlcommon::row_closure(1);
1.1 raeburn 1371: }
1372: }
1373: return $output;
1374: }
1375:
1376: sub get_course_dom {
1377: my $codedom = &Apache::lonnet::default_login_domain();
1378: if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne 'public')) {
1379: $codedom = $env{'user.domain'};
1380: if ($env{'request.role.domain'} ne '') {
1381: $codedom = $env{'request.role.domain'};
1382: }
1383: }
1384: if ($env{'form.showdom'} ne '') {
1385: if (&Apache::lonnet::domain($env{'form.showdom'}) ne '') {
1386: $codedom = $env{'form.showdom'};
1387: }
1388: }
1389: return $codedom;
1390: }
1391:
1392: sub display_navbuttons {
1393: my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
1394: $r->print('<div class="LC_navbuttons">');
1395: if ($prev) {
1396: $r->print('
1397: <input type="button" name="previous" value = "'.$prevtext.'"
1398: onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
1399: ');
1400: } elsif ($prevtext) {
1401: $r->print('
1402: <input type="button" name="previous" value = "'.$prevtext.'"
1403: onclick="javascript:history.back()"/>
1404: ');
1405: }
1406: if ($next) {
1407: $r->print('
1408: <input type="button" name="next" value="'.$nexttext.'"
1409: onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
1410: }
1411: $r->print('</div>');
1412: }
1413:
1414: sub print_request_outcome {
1.10 raeburn 1415: my ($dom,$codetitles,$code_order) = @_;
1416: my ($output,$cnum,$now,$req_notifylist,$crstype,$startenroll,$endenroll,
1417: %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig,);
1418: $cnum = $env{'form.cnum'};
1.8 raeburn 1419: unless ($cnum =~ /^$match_courseid$/) {
1420: $output = &mt('Invalid LON-CAPA course number for the new course')."\n";
1421: return $output;
1422: }
1.11 ! raeburn 1423:
1.10 raeburn 1424: %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom);
1.9 raeburn 1425: if (ref($domconfig{'requestcourses'}) eq 'HASH') {
1426: if (ref($domconfig{'requestcourses'}{'notify'}) eq 'HASH') {
1427: $req_notifylist = $domconfig{'requestcourses'}{'notify'}{'approval'};
1428: }
1429: }
1.10 raeburn 1430: $now = time;
1431: $crstype = $env{'form.crstype'};
1.8 raeburn 1432: if ($crstype eq 'official') {
1433: if (&Apache::lonnet::auto_run('',$dom)) {
1434: ($startenroll,$endenroll)=&dates_from_form('startenroll','endenroll');
1435: }
1.10 raeburn 1436: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
1437: if ($env{'form.sec_'.$i}) {
1438: if ($env{'form.secnum_'.$i} ne '') {
1439: $sections{$env{'form.secnum_'.$i}} = $env{'form.loncapasec_'.$i};
1440: }
1441: }
1442: }
1443: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
1444: if ($env{'form.crosslist_'.$i}) {
1445: my $xlistinfo = '';
1446: if (ref($code_order) eq 'ARRAY') {
1447: if (@{$code_order} > 0) {
1448: foreach my $item (@{$code_order}) {
1449: $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item};
1450: }
1451: }
1452: }
1453: $xlistinfo .= $env{'form.crosslist_'.$i.'_instsec'};
1454: $crosslistings{$xlistinfo} = $env{'form.crosslist_'.$i.'_lcsec'};
1455: }
1456: }
1457: }
1458:
1459: for (my $i=0; $i<$env{'form.persontotal'}; $i++) {
1460: my $uname = $env{'form.person_'.$i.'_uname'};
1461: my $udom = $env{'form.person_'.$i.'_uname'};
1462: if (($uname =~ /^$match_username$/) && ($udom =~ /^$match_domain$/)) {
1463: if (&Apache::lonnet::domain($udom) ne '') {
1464: $personnel{$uname.':'.$udom} = {
1465: first => $env{'form.person_'.$i.'_first'},
1466: last => $env{'form.person_'.$i.'_last'},
1467: email => $env{'form.person_'.$i.'_email'},
1468: role => $env{'form.person_'.$i.'_role'},
1469: sections => $env{'form.person_'.$i.'_sections'},
1470: };
1471: } else {
1472: push(@missingdom,$uname.':'.$udom);
1473: }
1474: } else {
1475: push(@baduname,$uname.':'.$udom);
1476: }
1.8 raeburn 1477: }
1.10 raeburn 1478:
1.8 raeburn 1479: my ($startaccess,$endaccess) = &dates_from_form('startaccess','endacess');
1480: my $details = {
1.10 raeburn 1481: owner => $env{'user.name'},
1482: domain => $env{'user.domain'},
1483: cdom => $dom,
1.11 ! raeburn 1484: cnum => $cnum,
1.10 raeburn 1485: cdesc => $env{'form.cdesc'},
1486: crstype => $env{'form.crstype'},
1487: instcode => $env{'form.instcode'},
1488: clonedomain => $env{'form.clonedomain'},
1489: clonecourse => $env{'form.clonecourse'},
1490: datemode => $env{'form.datemode'},
1491: dateshift => $env{'form.datshift'},
1492: sectotal => $env{'form.sectotal'},
1493: sections => \%sections,
1494: crosslisttotal => $env{'form.crosslisttotal'},
1495: crosslistings => \%crosslistings,
1496: autoadds => $env{'form.autoadds'},
1497: autodrops => $env{'form.autodrops'},
1498: startenroll => $startenroll,
1499: endenroll => $endenroll,
1500: startaccess => $startaccess,
1501: endaccess => $endaccess,
1502: personnel => \%personnel,
1.8 raeburn 1503: };
1504: my @inststatuses;
1.9 raeburn 1505: my $val = &get_processtype($dom,$crstype,\@inststatuses,\%domconfig);
1.8 raeburn 1506: if ($val eq '') {
1507: if ($crstype eq 'official') {
1508: $output = &mt('You are not permitted to request creation of official courses');
1509: } elsif ($crstype eq 'unofficial') {
1510: $output = &mt('You are not permitted to request creation of unofficial courses');
1511: } elsif ($crstype eq 'community') {
1512: $output = &mt('You are not permitted to request creation of communities');
1513: } else {
1514: $output = &mt('Unrecognized course type: [_1]',$crstype);
1515: }
1516: } else {
1517: my ($disposition,$message);
1518: my %reqhash = (
1.10 raeburn 1519: timestamp => $now,
1520: crstype => $crstype,
1521: details => $details,
1.8 raeburn 1522: );
1523: my $requestkey = $dom.'_'.$cnum;
1.10 raeburn 1524: if ($val eq 'autolimit=') {
1525: $disposition = 'process';
1526: } elsif ($val =~ /^autolimit=(\d+)$/) {
1527: my $limit = $1;
1.8 raeburn 1528: $disposition = &check_autolimit($env{'user.name'},$env{'user.domain'},
1.10 raeburn 1529: $dom,$crstype,$limit,\$message);
1.8 raeburn 1530: } elsif ($val eq 'validate') {
1531: $disposition =
1532: &Apache::lonnet::auto_courserequest_validation($dom,$details,
1533: \@inststatuses,\$message);
1534: } else {
1535: $disposition = 'approval';
1536: }
1537: $reqhash{'status'} = $disposition;
1538: if ($disposition eq 'rejected') {
1539: $output = &mt('Your course request was rejected.');
1540: if ($message) {
1541: $output .= '<div class="LC_warning">'.$message.'</div>';
1542: }
1543: } elsif ($disposition eq 'process') {
1544: my $type = 'Course';
1545: if ($crstype eq 'community') {
1546: $type = 'Community';
1547: }
1548: my ($logmsg,$newusermsg,$addresult,$enrollcount,$output,$keysmsg,%longroles);
1549: my @roles = &Apache::lonuserutils::roles_by_context('course');
1550: foreach my $role (@roles) {
1551: $longroles{$role}=&Apache::lonnet::plaintext($role,$type);
1552: }
1553: my %reqdetails = &build_batchcreatehash($details);
1554: my $cid = &LONCAPA::batchcreatecourse::build_course($dom,$cnum,'request',\%reqdetails,\%longroles,\$logmsg,\$newusermsg,\$addresult,\$enrollcount,\$output,\$keysmsg,$env{'user.domain'},$env{'user.name'},$cnum);
1555: $disposition = 'created';
1556: if ($cid eq $cnum) {
1557: $disposition = 'created';
1558: $output = &mt('Your course request has been processed and the course has been created.').'<br />'.&mt('You will need to logout and log-in again to be able to select a role in the course.');
1559: } else {
1560: $output = &mt('An error occurred when processing your course request.').'<br />'.&mt('You may want to review the request details and submit the request again.');
1561: }
1562: } else {
1563: my $requestid = $cnum.'_'.$disposition;
1564: my $request = {
1565: $requestid => {
1566: timestamp => $now,
1567: crstype => $crstype,
1568: ownername => $env{'user.name'},
1569: ownerdom => $env{'user.domain'},
1570: description => $env{'form.cdesc'},
1571: },
1572: };
1573: my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request,
1574: $dom);
1575: if ($putresult eq 'ok') {
1576: my %emails = &Apache::loncommon::getemails();
1577: my $address;
1578: if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) {
1579: $address = $emails{'permanentemail'};
1580: if ($address eq '') {
1581: $address = $emails{'notification'};
1582: }
1583: }
1584: $output = &mt('Your course request has been recorded.').'<br />';
1585: if ($disposition eq 'approval') {
1586: $output .= &mt('Your course request has been recorded.').'<br />'.
1587: &mt('A message will be sent to your LON-CAPA account when a domain coordinator takes action on your request.').'<br />'.
1588: &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').'<br />';
1589: if ($address ne '') {
1590: $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).'<br />';
1591: }
1592: if ($req_notifylist) {
1593: my $fullname = &Apache::loncommon::plainname($env{'user.name'},
1594: $env{'user.domain'});
1595: &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,$fullname,$now,$dom,$details);
1596: }
1597: } else {
1598: $output .= '<div class="LC_info">'.
1599: &mt('Your request has been placed in a queue pending administrative action.').'<br />'.
1600: &mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").'<br />'.
1601: &mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.').
1602: '</div>';
1603: }
1604: } else {
1605: $reqhash{'status'} = 'domainerror';
1606: $reqhash{'disposition'} = $disposition;
1607: my $warning = &mt('An error occurred saving your request in the pending requests queue.');
1608: $output = '<span class"LC_warning">'.$warning.'</span><br />';
1609:
1610: }
1611: }
1.10 raeburn 1612: my $storeresult;
1613: if ($requestkey =~ /^($match_domain)_($match_courseid)$/) {
1614: $storeresult = &Apache::lonnet::store_userdata(\%reqhash,$requestkey,
1615: 'courserequests');
1616: } else {
1617: $storeresult = 'error: invalid requestkey format';
1618: }
1.8 raeburn 1619: if ($storeresult ne 'ok') {
1620: $output .= '<span class="LC_warning">'.&mt('An error occurred saving a record of the details of your request.').'</span><br />';
1621: &logthis("Error saving course request - $requestkey for $env{'user.name'}:$env{'user.domain'} - $storeresult");
1622: }
1623: }
1624: return $output;
1625: }
1626:
1627: sub get_processtype {
1.9 raeburn 1628: my ($dom,$crstype,$inststatuses,$domconfig) = @_;
1629: return unless ((ref($inststatuses) eq 'ARRAY') && (ref($domconfig) eq 'HASH'));
1.8 raeburn 1630: my (%userenv,%settings,$val);
1631: my @options = ('autolimit','validate','approve');
1632: if ($dom eq $env{'user.domain'}) {
1633: %userenv =
1634: &Apache::lonnet::userenvironment($env{'user.domain'},$env{'user.name'},
1635: 'requestcourses.'.$crstype,'inststatus');
1636: if ($userenv{'requestcourses.'.$crstype}) {
1637: $val = $userenv{'requestcourses.'.$crstype};
1638: @{$inststatuses} = ('_custom_');
1639: } else {
1640: my ($task,%alltasks);
1.9 raeburn 1641: if (ref($domconfig->{'requestcourses'}) eq 'HASH') {
1642: %settings = %{$domconfig->{'requestcourses'}};
1.8 raeburn 1643: if (ref($settings{$crstype}) eq 'HASH') {
1644: if (($env{'user.adv'}) && (exists($settings{$crstype}{'_LC_adv'}))) {
1645: $val = $settings{$crstype}{'_LC_adv'};
1646: @{$inststatuses} = ('_LC_adv_');
1647: } else {
1648: if ($userenv{'inststatus'} ne '') {
1649: @{$inststatuses} = split(',',$userenv{'inststatus'});
1650: } else {
1651: @{$inststatuses} = ('other');
1652: }
1653: foreach my $status (@{$inststatuses}) {
1654: if (exists($settings{$crstype}{$status})) {
1655: my $value = $settings{$crstype}{$status};
1656: next unless ($value);
1657: unless (exists($alltasks{$value})) {
1658: if (ref($alltasks{$value}) eq 'ARRAY') {
1659: unless(grep(/^\Q$status\E$/,@{$alltasks{$value}})) {
1660: push(@{$alltasks{$value}},$status);
1661: }
1662: } else {
1663: @{$alltasks{$value}} = ($status);
1664: }
1665: }
1666: }
1667: }
1668: my $maxlimit = 0;
1669: foreach my $key (sort(keys(%alltasks))) {
1670: if ($key =~ /^autolimit=(\d*)$/) {
1671: if ($1 eq '') {
1672: $val ='autolimit=';
1673: last;
1674: } elsif ($1 > $maxlimit) {
1675: $maxlimit = $1;
1676: }
1677: }
1678: }
1679: if ($maxlimit) {
1680: $val = 'autolimit='.$maxlimit;
1681: } else {
1682: foreach my $option (@options) {
1683: if ($alltasks{$option}) {
1684: $val = $option;
1685: last;
1686: }
1687: }
1688: }
1689: }
1690: }
1691: }
1692: }
1693: } else {
1694: %userenv = &Apache::lonnet::userenvironment($env{'user.domain'},
1695: $env{'user.name'},'reqcrsotherdom.'.$env{'form.crstype'});
1696: if ($userenv{'reqcrsotherdom'}) {
1697: my @doms = split(',',$userenv{'reqcrsotherdom'});
1698: my $optregex = join('|',@options);
1699: if (grep(/^\Q$dom\E:($optregex=?\d*)/,@doms)) {
1700: $val = $1;
1701: }
1702: @{$inststatuses} = ('_external_');
1703: }
1704: }
1705: return $val;
1706: }
1707:
1708: sub check_autolimit {
1.10 raeburn 1709: my ($uname,$udom,$dom,$crstype,$limit,$message) = @_;
1710: my %crsroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
1711: 'userroles',['active','future'],['cc'],[$dom]);
1712: my ($types,$typename) = &course_types();
1713: my %requests = &Apache::lonnet::dumpstore('courserequests',$udom,$uname);
1714: my %count;
1715: if (ref($types) eq 'ARRAY') {
1716: foreach my $type (@{$types}) {
1717: $count{$type} = 0;
1718: }
1719: }
1720: foreach my $key (keys(%requests)) {
1721: my ($cdom,$cnum) = split('_',$key);
1722: if (exists($crsroles{$cnum.':'.$cdom.':cc'})) {
1723: if (ref($requests{$key}) eq 'HASH') {
1724: my $type = $requests{$key}{'crstype'};
1725: if ($type =~ /^official|unofficial|community$/) {
1726: $count{$type} ++;
1727: }
1728: }
1729: }
1730: }
1731: if ($count{$crstype} < $limit) {
1732: return 'process';
1733: } else {
1734: if (ref($typename) eq 'HASH') {
1735: $$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);
1736: }
1737: return 'rejected';
1738: }
1.1 raeburn 1739: return;
1740: }
1741:
1.8 raeburn 1742: sub build_batchcreatehash {
1743: my ($details) = @_;
1744: my %batchhash;
1745: if (ref($details) eq 'HASH') {
1746:
1747: }
1748: return %batchhash;
1749: }
1750:
1.2 raeburn 1751: sub retrieve_settings {
1752: my ($dom,$request_id) = @_;
1753: my %reqinfo = &get_request_settings($request_id,$dom);
1754: my %stored;
1755: $stored{'cdescr'} = &unescape($reqinfo{'description'});
1756: $stored{'startaccess'} = $reqinfo{'startaccess'};
1757: $stored{'endaccess'} = $reqinfo{'endaccess'};
1758: if ($stored{'endaccess'} == 0) {
1759: $stored{'no_end_date'} = 1;
1760: }
1761: $stored{'startenroll'} = $reqinfo{'startenroll'};
1762: $stored{'endenroll'} = $reqinfo{'endenroll'};
1763: $stored{'crosslist'} = $reqinfo{'crosslist'};
1764: $stored{'clonecourse'} = $reqinfo{'clonecourse'};
1765: $stored{'clonedomain'} = $reqinfo{'clonedomain'};
1766: $stored{'sections'} = $reqinfo{'sections'};
1767: $stored{'personnel'} = $reqinfo{'personnel'};
1768:
1769: return %stored;
1770: }
1771:
1772: sub get_request_settings {
1773: my ($request_id,$dom);
1774: }
1775:
1.1 raeburn 1776: 1;
1777:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>