Annotation of loncom/interface/lonrequestcourse.pm, revision 1.3
1.1 raeburn 1: # The LearningOnline Network
2: # Request a course
3: #
1.3 ! raeburn 4: # $Id: lonrequestcourse.pm,v 1.2 2009/08/04 20:15:50 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;
58: use LONCAPA;
59:
60: sub handler {
61: my ($r) = @_;
62: if ($r->header_only) {
63: &Apache::loncommon::content_type($r,'text/html');
64: $r->send_http_header;
65: return OK;
66: }
67: &Apache::loncommon::content_type($r,'text/html');
68: $r->send_http_header;
69:
1.2 raeburn 70: &Apache::lonhtmlcommon::clear_breadcrumbs();
71: my $dom = &get_course_dom();
1.1 raeburn 72: my $action = $env{'form.action'};
73: my $state = $env{'form.state'};
1.2 raeburn 74:
75: my %stored;
76: my $jscript;
77: if ((defined($state)) && (defined($action))) {
78: my %elements = &form_elements($dom);
79: if (($action eq 'view') && ($state ne 'crstype')) {
80: if (defined($env{'form.request_id'})) {
81: %stored = &retrieve_settings($dom,$env{'form.request_id'});
82: }
83: }
84: my $elementsref = {};
85: if (ref($elements{$action}) eq 'HASH') {
86: if (ref($elements{$action}{$state}) eq 'HASH') {
87: $elementsref = $elements{$action}{$state};
88: }
89: }
90: $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored);
91: }
92:
93: if ($state eq 'personnel') {
94: $jscript .= "\n".&Apache::loncommon::userbrowser_javascript();
95: }
96:
97: my $loaditems = &onload_action($action,$state);
98:
99: my %states;
100: $states{'view'} = ['pick_request','details','review','process'];
101: $states{'log'} = ['filter','display'];
102: $states{'new'} = ['courseinfo','enrollment','personnel','review','process'];
103: if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) {
104: unless ($env{'form.state'} eq 'crstype') {
105: unshift (@{$states{'new'}},'codepick');
106: }
107: }
108:
109: foreach my $key (keys(%states)) {
110: if (ref($states{$key}) eq 'ARRAY') {
111: unshift (@{$states{$key}},'crstype');
112: }
113: }
114:
1.3 ! raeburn 115: my %trail = (
! 116: crstype => 'Pick Action',
! 117: codepick => 'Pick Category',
! 118: courseinfo => 'Information',
! 119: enrollment => 'Enrollment',
! 120: personnel => 'Personnel',
! 121: review => 'Review',
! 122: process => 'Result',
! 123: );
! 124:
1.2 raeburn 125: my $page = 0;
1.3 ! raeburn 126: my $crumb;
1.2 raeburn 127: if (defined($action)) {
128: my $done = 0;
129: my $i=0;
130: if (ref($states{$action}) eq 'ARRAY') {
131: while ($i<@{$states{$action}} && !$done) {
132: if ($states{$action}[$i] eq $state) {
133: $page = $i;
134: $done = 1;
135: }
136: $i++;
137: }
138: }
1.3 ! raeburn 139: for (my $i=0; $i<@{$states{$action}}; $i++) {
! 140: if ($state eq $states{$action}[$i]) {
! 141: &Apache::lonhtmlcommon::add_breadcrumb(
! 142: {text=>"$trail{$state}"});
! 143: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
! 144: last;
! 145: } else {
! 146: if (($state eq 'process') && ($i > 0)) {
! 147: &Apache::lonhtmlcommon::add_breadcrumb(
! 148: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[0]')",
! 149: text=>"$trail{$states{$action}[$i]}"});
! 150: } else {
! 151: &Apache::lonhtmlcommon::add_breadcrumb(
! 152: {href=>"javascript:backPage(document.requestcrs,'$states{$action}[$i]')",
! 153: text=>"$trail{$states{$action}[$i]}"});
! 154: }
! 155: }
! 156: }
! 157: } else {
! 158: &Apache::lonhtmlcommon::add_breadcrumb(
! 159: {text=>'Pick Action'});
! 160: $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests');
1.2 raeburn 161: }
162:
1.1 raeburn 163: my %can_request;
164: my $canreq = &check_can_request($dom,\%can_request);
165: if ($action eq 'new') {
166: if ($canreq) {
167: if ($state eq 'crstype') {
1.3 ! raeburn 168: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,
! 169: $crumb);
1.1 raeburn 170: } else {
1.2 raeburn 171: &request_administration($r,$action,$state,$page,\%states,$dom,$jscript,
1.3 ! raeburn 172: $loaditems,$crumb);
1.1 raeburn 173: }
174: } else {
1.3 ! raeburn 175: $r->print(&header('Course Requests').$crumb.
1.1 raeburn 176: '<div class="LC_warning">'.
177: &mt('You do not have privileges to request creation of courses.').
1.2 raeburn 178: '</div>'.&Apache::loncommon::end_page());
1.1 raeburn 179: }
180: } elsif ($action eq 'view') {
1.3 ! raeburn 181: &print_request_status($jscript,$loaditems,$crumb);
1.1 raeburn 182: } elsif ($action eq 'log') {
1.3 ! raeburn 183: &print_request_logs($jscript,$loaditems,$crumb);
1.1 raeburn 184: } else {
1.3 ! raeburn 185: &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb);
1.1 raeburn 186: }
187: return OK;
188: }
189:
1.2 raeburn 190: sub header {
191: my ($bodytitle,$jscript,$loaditems,$jsextra) = @_;
192: if ($jscript) {
193: $jscript = '<script type="text/javascript">'.
194: $jscript.'</script>'."\n";
195: }
196: if ($loaditems) {
1.3 ! raeburn 197: $loaditems = {'add_entries' => $loaditems,};
! 198: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra,$loaditems);
! 199: } else {
! 200: return &Apache::loncommon::start_page($bodytitle,$jscript.$jsextra);
! 201: }
1.2 raeburn 202: }
203:
204: sub form_elements {
205: my ($dom) = @_;
206: my %elements =
207: (
208: new => {
209: crstype => {
210: crstype => 'selectbox',
211: action => 'selectbox',
212: },
213: courseinfo => {
214: cdescr => 'text',
215: clonecourse => 'text',
216: clonedomain => 'selectbox',
217: datemode => 'radio',
218: dateshift => 'text',
219: },
220: enrollment => {
221: startaccess_month => 'selectbox',
222: startaccess_hour => 'selectbox',
223: endaccess_month => 'selectbox',
224: endaccess_hour => 'selectbox',
225: startaccess_day => 'text',
226: startaccess_year => 'text',
227: startaccess_minute => 'text',
228: startaccess_second => 'text',
229: endaccess_day => 'text',
230: endaccess_year => 'text',
231: endaccess_minute => 'text',
232: endaccess_second => 'text',
233: no_end_date => 'checkbox',
234: },
235: personnel => {
236: persontotal => 'hidden',
237: addperson => 'checkbox',
238: },
239: },
240: view => {
241: crstype => {
242: crstype => 'selectbox',
243: action => 'selectbox',
244: },
245: },
246: );
247: my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem);
248: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
249: \%cat_order,\@code_order);
250: my $numtitles = scalar(@codetitles);
251: if ($numtitles) {
252: my %extras;
253: $lastitem = pop(@codetitles);
254: $extras{'instcode_'.$lastitem} = 'text';
255: foreach my $item (@codetitles) {
256: $extras{'instcode_'.$item} = 'selectbox';
257: }
258: $elements{'new'}{'codepick'} = \%extras;
259: }
260: if (&Apache::lonnet::auto_run('',$dom)) {
261: my %extras = (
262: sectotal => 'hidden',
263: startenroll_month => 'selectbox',
264: startenroll_hour => 'selectbox',
265: endenroll_month => 'selectbox',
266: endenroll_hour => 'selectbox',
267: startenroll_day => 'text',
268: startenroll_year => 'text',
269: startenroll_minute => 'text',
270: startenroll_second => 'text',
271: endenroll_day => 'text',
272: endenroll_year => 'text',
273: endenroll_minute => 'text',
274: endenroll_second => 'text',
275: crosslisttotal => 'hidden',
276: addcrosslist => 'checkbox',
277: autoadds => 'radio',
278: autodrops => 'radio',
279: );
280: if ($env{'form.sectotal'} > 0) {
281: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
282: $extras{'sec_'.$i} = 'checkbox',
283: $extras{'secnum_'.$i} = 'text',
284: $extras{'loncapasec_'.$i} = 'checkbox',
285: }
286: }
287: my $crosslisttotal = $env{'form.crosslisttotal'};
288: if (!defined($crosslisttotal)) {
289: $crosslisttotal = 1;
290: }
291: if ($crosslisttotal > 0) {
292: for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) {
293: if ($numtitles) {
294: $extras{'crosslist_'.$i.'_'.$lastitem} = 'text';
295: }
296: if (@codetitles > 0) {
297: foreach my $item (@codetitles) {
298: $extras{'crosslist_'.$i.'_'.$item} = 'selectbox';
299: }
300: }
301: $extras{'crosslist_'.$i} = 'checkbox';
302: $extras{'crosslist_'.$i.'_instsec'} = 'text',
303: $extras{'crosslist_'.$i.'_lcsec'} = 'text',
304: }
305: }
306: my %mergedhash = (%{$elements{'new'}{'enrollment'}},%extras);
307: %{$elements{'new'}{'enrollment'}} = %mergedhash;
308: }
309: my %people;
310: my $persontotal = $env{'form.persontotal'};
311: if (!defined($persontotal)) {
312: $persontotal = 1;
313: }
314: for (my $i=0; $i<$persontotal; $i++) {
315: $people{'person_'.$i.'_uname'} = 'text',
316: $people{'person_'.$i.'_dom'} = 'selectbox',
317: $people{'person_'.$i.'_hidedom'} = 'hidden',
318: $people{'person_'.$i.'_first'} = 'text',
319: $people{'person_'.$i.'_last'} = 'text',
320: $people{'person_'.$i.'_email'} = 'text',
321: $people{'person_'.$i.'_role'} = 'selectbox',
322: $people{'person_'.$i.'_sec'} = 'selectbox',
323: $people{'person_'.$i.'_newsec'} = 'text',
324: $people{'person_'.$i.'_sections'} = 'hidden',
325: }
326: my %personnelhash = (%{$elements{'new'}{'personnel'}},%people);
327: %{$elements{'new'}{'personnel'}} = %personnelhash;
328: return %elements;
329: }
330:
331: sub onload_action {
332: my ($action,$state) = @_;
333: my %loaditems;
334: if (($action eq 'new') || ($action eq 'view')) {
335: $loaditems{'onload'} = 'javascript:setFormElements(document.requestcrs)';
336: }
337: return \%loaditems;
338: }
339:
1.1 raeburn 340: sub check_can_request {
341: my ($dom,$can_request) = @_;
342: my $canreq = 0;
343: if (ref($can_request) eq 'HASH') {
344: foreach my $type ('official','unofficial','community') {
345: if (&Apache::lonnet::usertools_access($env{'user.name'},
346: $env{'user.domain'},
347: $type,undef,'requestcourses')) {
348: $canreq ++;
349: if ($dom eq $env{'user.domain'}) {
350: $can_request->{$type} = 1;
351: }
352: }
353: if ($env{'environment.reqcrsotherdom.'.$type} ne '') {
354: my @curr = split(',',$env{'environment.reqcrsotherdom.'.$type});
355: if (@curr > 0) {
356: $canreq ++;
357: unless ($dom eq $env{'user.domain'}) {
358: if (grep(/^\Q$dom\E$/,@curr)) {
359: $can_request->{$type} = 1;
360: }
361: }
362: }
363: }
364: }
365: }
366: return $canreq;
367: }
368:
369: sub print_main_menu {
1.3 ! raeburn 370: my ($r,$can_request,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.1 raeburn 371: my $onchange;
372: unless ($env{'form.interface'} eq 'textual') {
373: $onchange = 1;
374: }
375:
1.2 raeburn 376: my $nextstate_setter = "\n";
377: if (ref($states) eq 'HASH') {
378: foreach my $key (keys(%{$states})) {
379: if (ref($states->{$key}) eq 'ARRAY') {
380: $nextstate_setter .=
381: " if (actionchoice == '$key') {
382: nextstate = '".$states->{$key}[1]."';
383: }
384: ";
385: }
386: }
387: }
1.1 raeburn 388:
1.2 raeburn 389: my $js = <<"END";
1.1 raeburn 390:
1.2 raeburn 391: function nextPage(formname) {
392: var crschoice = document.requestcrs.crstype.value;
393: var actionchoice = document.requestcrs.action.value;
394: if (check_can_request(crschoice,actionchoice) == true) {
395: if ((actionchoice == 'new') && (crschoice == 'official')) {
396: nextstate = 'codepick';
397: } else {
398: $nextstate_setter
399: }
1.1 raeburn 400: formname.state.value= nextstate;
401: formname.submit();
402: }
403: return;
404: }
405:
1.2 raeburn 406: function check_can_request(crschoice,actionchoice) {
1.1 raeburn 407: var official = '';
408: var unofficial = '';
409: var community = '';
410: END
411:
412: foreach my $item (keys(%{$can_request})) {
413: $js .= "
414: $item = 1;
415: ";
416: }
417: my %lt = &Apache::lonlocal::texthash(
418: official => 'You are not permitted to request creation of an official course in this domain.',
419: unofficial => 'You are not permitted to request creation of an unofficial course in this domain.',
420: community => 'You are not permitted to request creation of a community this domain.',
421: all => 'You must choose a specific course type when making a new course request.\\nAll types is not allowed.',
422: );
423: $js .= <<END;
424: if (crschoice == 'official') {
425: if (official != 1) {
426: alert("$lt{'official'}");
427: return false;
428: }
429: } else {
430: if (crschoice == 'unofficial') {
431: if (unofficial != 1) {
432: alert("$lt{'unofficial'}");
433: return false;
434: }
435: } else {
436: if (crschoice == 'community') {
437: if (community != 1) {
438: alert("$lt{'community'}");
439: return false;
440: }
441: } else {
442: if (actionchoice == 'new') {
443: alert("$lt{'all'}");
444: return false;
445: }
446: }
447: }
448: }
449: return true;
450: }
451:
452: END
453:
1.3 ! raeburn 454: $r->print(&header('Course Requests',$js.$jscript,$loaditems).$crumb.
! 455: '<div>'.
1.1 raeburn 456: '<form name="domforcourse" method="post" action="/adm/requestcourse">'.
457: &Apache::lonhtmlcommon::start_pick_box().
458: &Apache::lonhtmlcommon::row_title('Domain').
459: &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange));
460: if (!$onchange) {
461: $r->print(' <input type="submit" name="godom" value="'.
462: &mt('Change').'" />');
463: }
464: $r->print(&Apache::lonhtmlcommon::row_closure(1).
465: &Apache::lonhtmlcommon::end_pick_box().'</form></div>');
466:
1.2 raeburn 467: my $formname = 'requestcrs';
1.1 raeburn 468: my $nexttext = &mt('Next');
469: $r->print('<div><form name="'.$formname.'" method="post" action="/adm/requestcourse">'.
470: &Apache::lonhtmlcommon::start_pick_box().
471: &Apache::lonhtmlcommon::row_title('Action').'
472: <input type="hidden" name="showdom" value="'.$dom.'" />
473: <select size="1" name="action" >
1.2 raeburn 474: <option value="new">'.&mt('New request').'</option>
1.1 raeburn 475: <option value="view">'.&mt('View/Modify/Cancel pending requests').'</option>
476: <option value="log">'.&mt('View request history').'</option>
477: </select>'.
478: &Apache::lonhtmlcommon::row_closure().
479: &Apache::lonhtmlcommon::row_title('Course Type').'
480: <select size="1" name="crstype">
481: <option value="any">'.&mt('All types').'</option>
1.2 raeburn 482: <option value="official" selected="selected">'.&mt('Official course').'</option>
1.1 raeburn 483: <option value="unofficial">'.&mt('Unofficial course').'</option>
484: <option value="community">'.&mt('Community').'</option>
485: </select>
486: <input type="hidden" name="state" value="crstype" />'.
487: &Apache::lonhtmlcommon::row_closure(1).
488: &Apache::lonhtmlcommon::end_pick_box().'<br />
1.2 raeburn 489: <input type="button" name="next" value="'.$nexttext.'" onclick="javascript:nextPage(document.'.$formname.')" />
1.1 raeburn 490: </form></div>');
491: $r->print(&Apache::loncommon::end_page());
492: return;
493: }
494:
495: sub request_administration {
1.3 ! raeburn 496: my ($r,$action,$state,$page,$states,$dom,$jscript,$loaditems,$crumb) = @_;
1.2 raeburn 497: my $js;
498: if (($action eq 'new') || ($action eq 'view')) {
499: $js = <<END;
1.1 raeburn 500:
501: function nextPage(formname,nextstate) {
502: formname.state.value= nextstate;
503: formname.submit();
504: }
505: function backPage(formname,prevstate) {
506: formname.state.value = prevstate;
507: formname.submit();
508: }
509:
510: END
1.2 raeburn 511: }
512: if ($action eq 'new') {
513: my $jsextra;
1.1 raeburn 514: unless (($state eq 'review') || ($state eq 'process')) {
1.2 raeburn 515: $jsextra = "\n".&Apache::loncommon::coursebrowser_javascript($dom);
1.1 raeburn 516: }
1.3 ! raeburn 517: $r->print(&header('Request a course',$js.$jscript,$loaditems,$jsextra).$crumb);
1.1 raeburn 518: if ($state eq 'review') {
519: &print_review($r,$state,$dom);
520: } elsif ($state eq 'process') {
521: &print_request_outcome($r,$state,$dom);
522: } else {
1.2 raeburn 523: &print_request_form($r,$action,$state,$page,$states,$dom);
1.1 raeburn 524: }
1.2 raeburn 525: } elsif ($action eq 'view') {
1.3 ! raeburn 526: $r->print(&header('Manage course requests',$js.$jscript,$loaditems).$crumb);
1.1 raeburn 527: } elsif ($action eq 'log') {
1.3 ! raeburn 528: $r->print(&coursereq_log('View request log',$jscript,$loaditems).$crumb);
1.1 raeburn 529: }
1.2 raeburn 530: $r->print(&Apache::loncommon::end_page());
1.1 raeburn 531: return;
532: }
533:
534: sub print_request_form {
1.2 raeburn 535: my ($r,$action,$state,$page,$states,$dom) = @_;
1.1 raeburn 536: my $formname = 'requestcrs';
1.2 raeburn 537: my ($next,$prev,$message,$output,$codepicker,$crstype);
538: $prev = $states->{$action}[$page-1];
539: $next = $states->{$action}[$page+1];
540: $crstype = $env{'form.crstype'};
1.1 raeburn 541: $r->print('<form name="'.$formname.'" method="post" action="/adm/requestcourse">');
1.2 raeburn 542: my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk);
1.1 raeburn 543: if ($crstype eq 'official') {
544: &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles,
545: \%cat_order,\@code_order);
1.2 raeburn 546: if ($env{'form.instcode'} ne '') {
547: $instcode = $env{'form.instcode'};
548: }
549: }
550: if ($prev eq 'codepick') {
551: if (@code_order > 0) {
552: my $message;
553: if ($instcode eq '') {
1.1 raeburn 554: foreach my $item (@code_order) {
1.2 raeburn 555: $instcode .= $env{'form.instcode_'.$item};
1.1 raeburn 556: }
1.2 raeburn 557: $r->print('<input type="hidden" name="instcode" value="'.$instcode.'" />'."\n");
1.1 raeburn 558: }
559: if ($instcode ne '') {
1.2 raeburn 560: $code_chk = &Apache::lonnet::auto_validate_instcode('',$dom,$instcode);
1.1 raeburn 561: if ($code_chk eq 'ok') {
562: $message = '<div class="LC_info">'.
563: &mt('The chosen course category [_1] is valid.','<b>'.
1.2 raeburn 564: $instcode.'</b>').'</div>';
1.1 raeburn 565: } else {
566: $message = '<div class="LC_warning">'.
567: &mt('No course was found matching your choice of institutional course category.');
568: if ($code_chk ne '') {
569: $message .= '<br />'.$code_chk;
570: }
571: $message .= '</div>';
572: }
1.2 raeburn 573: } else {
574: $message = '<div class="LC_warning">'.
575: &mt('No course was found matching your choice of institutional course category.');
1.1 raeburn 576: }
1.2 raeburn 577: unless ($code_chk eq 'ok') {
578: $prev = 'crstype';
579: }
580: $r->print($message);
1.1 raeburn 581: }
1.2 raeburn 582: }
583: if ($prev eq 'crstype') {
584: if (@code_order > 0) {
1.1 raeburn 585: $codepicker = &coursecode_form($dom,'instcode',\@codetitles,
586: \%cat_titles,\%cat_order);
1.2 raeburn 587: if ($codepicker) {
588: $r->print('<div>'.&Apache::lonhtmlcommon::start_pick_box().$codepicker.
589: &Apache::lonhtmlcommon::end_pick_box().'</div>');
590: } else {
591: $r->print(&courseinfo_form($dom,$formname,$crstype));
592: }
593: } else {
594: $r->print(&courseinfo_form($dom,$formname,$crstype));
1.1 raeburn 595: }
1.2 raeburn 596: } elsif ($prev eq 'codepick') {
597: $r->print(&courseinfo_form($dom,$formname,$crstype));
598: } elsif ($state eq 'enrollment') {
599: $r->print(&print_enrollment_menu($formname,$instcode,$dom,\@codetitles,
600: \%cat_titles,\%cat_order,\@code_order));
601: } elsif ($state eq 'personnel') {
602: $r->print(&print_personnel_menu($dom,$formname));
1.1 raeburn 603: }
1.2 raeburn 604: my @excluded = ('counter');
605: my %elements = &form_elements($dom);
606: if (ref($states) eq 'HASH') {
607: if (ref($states->{$action}) eq 'ARRAY') {
608: my @items = @{$states->{$action}};
609: my $numitems = scalar(@items);
610: if ($numitems) {
611: for (my $i=$numitems-1; $i>=0; $i--) {
612: if (ref($elements{$action}) eq 'HASH') {
613: if (ref($elements{$action}{$items[$i]}) eq 'HASH') {
614: foreach my $key (keys(%{$elements{$action}{$items[$i]}})) {
615: push(@excluded,$key);
616: }
617: }
618: }
619: last if ($items[$i] eq $state);
620: }
621: }
622: }
623: }
624: if (grep(/^instcode_/,@excluded)) {
625: push(@excluded,'instcode');
1.1 raeburn 626: }
1.2 raeburn 627: $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).'</form>');
1.1 raeburn 628: &display_navbuttons($r,$formname,$prev,'Previous',$next,'Next');
629: return;
630: }
631:
1.2 raeburn 632: sub print_enrollment_menu {
633: my ($formname,$instcode,$dom,$codetitles,$cat_titles,$cat_order,$code_order) =@_;
634: my ($sections,$autoenroll,$access_dates);
635: my $starttime = time;
636: my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
637:
638: my %accesstitles = (
639: 'start' => 'Default start access',
640: 'end' => 'Default end accss',
641: );
642: my %enrolltitles = (
643: 'start' => 'Start auto-enrollment',
644: 'end' => 'End auto-enrollment',
645: );
646: if ($env{'form.crstype'} eq 'official') {
647: if (&Apache::lonnet::auto_run('',$dom)) {
648: my ($section_form,$crosslist_form,$autoenroll_form);
649: $section_form = &inst_section_selector($dom,$instcode);
650: my $crosslisttotal = $env{'form.crosslisttotal'};
651: if (!defined($crosslisttotal)) {
652: $crosslisttotal = 1;
653: }
654: if ($env{'form.addcrosslist'}) {
655: $crosslisttotal ++;
656: }
657: for (my $i=0; $i<$crosslisttotal; $i++) {
658: $crosslist_form .= &coursecode_form($dom,'crosslist',$codetitles,
659: $cat_titles,$cat_order,$i);
660: }
661: if ($crosslist_form) {
662: $crosslist_form .=
663: &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
664: '<input name="crosslisttotal" type="hidden" value="'.$crosslisttotal.'" />'.
665: '<input name="addcrosslist" type="checkbox" value="'.$crosslisttotal.'"'.
666: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
667: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1);
668: }
669: if ($section_form || $crosslist_form) {
670: $sections = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
671: $section_form.$crosslist_form.
672: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
673: }
674: $autoenroll_form =
675: &Apache::lonhtmlcommon::row_title(&mt('Add registered students automatically')).
676: '<span class="LC_nobreak"><label>'.
677: '<input type="radio" name="autoadds" value="1">'.
678: &mt('Yes').'</label>'.(' 'x3).'<label>'.
679: '<input type="radio" name="autoadds" value="0" checked="checked">'.
680: &mt('No').'</label></span>'.
681: &Apache::lonhtmlcommon::row_closure().
682: &Apache::lonhtmlcommon::row_title(&mt('Drop unregistered students automatically')).
683: '<span class="LC_nobreak"><label>'.
684: '<input type="radio" name="autodrops" value="1">'.
685: &mt('Yes').'</label>'.(' 'x3).'<label>'.
686: '<input type="radio" name="autodrops" value="0" checked="checked">'.
687: &mt('No').'</label></span>'.
688: &Apache::lonhtmlcommon::row_closure().
689: &date_setting_table($starttime,$endtime,$formname,'enroll',%enrolltitles);
690: if ($autoenroll_form) {
691: $autoenroll = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
692: $autoenroll_form.
693: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
694: }
695: }
696: }
697: my $access_dates_form =
698: &date_setting_table($starttime,$endtime,$formname,'access',%accesstitles);
699: if ($access_dates_form) {
700: $access_dates = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
701: $access_dates_form.
702: &Apache::lonhtmlcommon::end_pick_box().'</div>'."\n";
703: }
704: return $sections.$autoenroll.$access_dates;
705: }
706:
1.1 raeburn 707: sub inst_section_selector {
1.2 raeburn 708: my ($dom,$instcode) = @_;
709: my @sections = &Apache::lonnet::auto_get_sections(undef,$dom,$instcode);
710: my $sectotal = scalar(@sections);
1.1 raeburn 711: my $output;
1.2 raeburn 712: if ($sectotal) {
713: $output .= &Apache::lonhtmlcommon::row_title('Sections').
714: &Apache::loncommon::start_data_table().
715: &Apache::loncommon::start_data_table_row().
716: '<th>'.&mt('Include?').'<input type="hidden" name="sectotal" '.
717: 'value="'.$sectotal.'"</th>'.
718: '<th>'.&mt('Institutional Section').'</th>'.
719: '<th>'.&mt('LON-CAPA section').'</th>'.
720: &Apache::loncommon::end_data_table_row();
721: for (my $i=0; $i<@sections; $i++) {
1.1 raeburn 722: my $colflag = $i%2;
723: $output .= &Apache::loncommon::start_data_table_row().
1.2 raeburn 724: '<td><input type="checkbox" name="sec_'.$i.
725: '" checked="checked" /></td>'.
726: '<td>'.$sections[$i].
1.1 raeburn 727: '<input type="hidden" name="secnum_'.$i.'" value="'.
1.2 raeburn 728: $sections[$i].'" /></td>'.
1.1 raeburn 729: '<td><input type="text" size="10" name="loncapasec_'.$i.
1.2 raeburn 730: '" value="'.$sections[$i].'" /></td>'.
1.1 raeburn 731: &Apache::loncommon::end_data_table_row();
732: }
1.2 raeburn 733: $output .= &Apache::loncommon::end_data_table().
734: &Apache::lonhtmlcommon::row_closure();
1.1 raeburn 735: }
736: return $output;
737: }
738:
1.2 raeburn 739: sub date_setting_table {
740: my ($starttime,$endtime,$formname,$suffix,%datetitles) = @_;
741: my ($perpetual,$table);
742: my $startform = &Apache::lonhtmlcommon::date_setter($formname,'start'.$suffix,
743: $starttime,'','','',1,'','','',1);
744: my $endform = &Apache::lonhtmlcommon::date_setter($formname,'end'.$suffix,
745: $endtime,'','','',1,'','','',1);
746: if ($suffix eq 'access') {
747: $perpetual = ' <span class="LC_nobreak"><label>'.
748: '<input type="checkbox" name="no_end_date" />'.
749: &mt('No end date').'</label></span>';
750: }
751: $table = &Apache::lonhtmlcommon::row_title($datetitles{'start'}).
752: $startform.
753: &Apache::lonhtmlcommon::row_closure().
754: &Apache::lonhtmlcommon::row_title($datetitles{'end'}).
755: $endform.$perpetual.
756: &Apache::lonhtmlcommon::row_closure(1);
757: return $table;
758: }
759:
760: sub print_personnel_menu {
761: my ($dom,$formname) = @_;
762: my $output = '<div>'.&Apache::lonhtmlcommon::start_pick_box();
763: my $persontotal = $env{'form.persontotal'};
764: if (!defined($persontotal)) {
765: $persontotal = 1;
766: }
767: if ($env{'form.addperson'}) {
768: $persontotal ++;
769: }
770: my $userlinktxt = &mt('Set User');
771: my @items = ('uname','dom','last','first','email','hidedom');
772:
773: my $roleoptions;
774: my @roles = &Apache::lonuserutils::roles_by_context('course');
775: foreach my $role (@roles) {
776: my $plrole=&Apache::lonnet::plaintext($role);
777: $roleoptions .= ' <option value="'.$role.'">'.$plrole.'</option>'."\n";
778: }
779: my %customroles=&Apache::lonuserutils::my_custom_roles();
780: if (keys(%customroles) > 0) {
781: foreach my $cust (sort(keys(%customroles))) {
782: my $custrole='cr_cr_'.$env{'user.domain'}.
783: '_'.$env{'user.name'}.'_'.$cust;
784: $roleoptions .= ' <option value="'.$custrole.'">'.$cust.'</option>'."\n";
785: }
786: }
787:
788: my @currsecs;
789: if ($env{'form.sectotal'}) {
790: for (my $i=0; $i<$env{'form.sectotal'}; $i++) {
791: if (defined($env{'form.loncapasec_'.$i})) {
792: my $lcsec = $env{'form.loncapasec_'.$i};
793: unless (grep(/^\Q$lcsec\E$/,@currsecs)) {
794: push(@currsecs,$lcsec);
795: }
796: }
797: }
798: }
799:
800: my ($existtitle,$existops,$existmult,$newtitle,$seccolspan);
801: if (@currsecs) {
802: my $existsize = scalar(@currsecs);
803: if ($existsize > 3) {
804: $existsize = 3;
805: }
806: if ($existsize > 1) {
807: $existmult = ' multiple="multiple" size="'.$existsize.'" ';
808: }
809: @currsecs = sort { $a <=> $b } (@currsecs);
810: $existtitle = &mt('Official').': ';
811: $existops = '<option value="">'.&mt('None').'</option>';
812: foreach my $sec (@currsecs) {
813: $existops .= '<option value="'.$sec.'">'.$sec.'</option>'."\n";
814: }
815: $seccolspan = ' colspan="2"';
816: $newtitle = &mt('Other').': ';
817: }
818:
819: for (my $i=0; $i<$persontotal; $i++) {
820: my @linkargs = map { 'person_'.$i.'_'.$_ } (@items);
821: my $linkargstr = join("','",@linkargs);
822: my $userlink = &Apache::loncommon::selectuser_link($formname,@linkargs,$userlinktxt);
823: my $uname_form = '<input type="text" name="person_'.$i.'_uname" value=""'.
824: ' onFocus="this.blur();'.
825: 'openuserbrowser('."'$formname','$linkargstr'".');" />';
826: my $onchange = 'javascript:fix_domain('."'$formname','person_".$i."_dom',".
827: "'person_".$i."_hidedom'".');'.
828: 'openuserbrowser('."'$formname','$linkargstr'".');';
829: my $udom_form = &Apache::loncommon::select_dom_form($dom,'person_'.$i.'_dom','',
830: 1,$onchange).
831: '<input type="hidden" name="person_'.$i.'_hidedom" value="'.$dom.'" />';
832: my %form_elems;
833: foreach my $item (@items) {
834: next if (($item eq 'dom') || ($item eq 'uname') || ($item eq 'hidedom'));
835: $form_elems{$item} = '<input type="text" name="person_'.$i.'_'.$item.'" '.
836: 'value="" readonly="readonly" />';
837: }
838: my $roleselector = '<select name="person_'.$i.'_role">'."\n".
839: $roleoptions.'</select>';
840: my $sectionselector;
841: if (@currsecs) {
842: $sectionselector = $existtitle.'<select name="person_'.$i.'_sec"'.
843: $existmult.'>'."\n".$existops.'</select>'.(' ' x3);
844: }
845: $sectionselector .= $newtitle.
846: '<input type="text" name="person_'.$i.'_newsec" size="15" value="" />'.
847: '<input type="hidden" name="person_'.$i.'_sections" value="" />'."\n";
848:
849: $output .=
850: &Apache::lonhtmlcommon::row_title(&mt('Additional Personnel').'<br />'.
851: '<span class="LC_nobreak">'.$userlink.
852: '</span>').
853: '<table><tr><td align="center" valign="top">'.&mt('Username').'<br />'.$uname_form.'</td>'."\n".
854: '<td align="center" valign="top" colspan="2">'.&mt('Domain').'<br />'.$udom_form.'</td></tr><tr>'."\n".
855: '<td align="center" valign="top">'.&mt('First Name').'<br />'.$form_elems{'first'}.'</td>'."\n".
856: '<td align="center" valign="top">'.&mt('Last Name').'<br />'.$form_elems{'last'}.'</td>'."\n".
857: '<td align="center" valign="top">'.&mt('E-mail').'<br />'.$form_elems{email}.'</td></tr>'."\n".
858: '<tr><td align="center" valign="top">'.&mt('Role').'<br />'.$roleselector.'</td>'."\n".
859: '<td'.$seccolspan.' align="center" valign="top">'.&mt('Section(s)').'<br />'.$sectionselector.'</td>'."\n".
860: '</tr></table>'.&Apache::lonhtmlcommon::row_closure();
861: }
862: $output .= &Apache::lonhtmlcommon::row_title(&mt('Add another?')).
863: '<input name="persontotal" type="hidden" value="'.$persontotal.'" />'.
864: '<input name="addperson" type="checkbox" value="'.$persontotal.'"'.
865: ' onclick="javascript:nextPage(document.'.$formname.",'".$env{'form.state'}.
866: "'".');" />'.&mt('Add?').&Apache::lonhtmlcommon::row_closure(1).
867: &Apache::lonhtmlcommon::end_pick_box().'</div>';
868: return $output;
869: }
870:
1.1 raeburn 871: sub print_request_status {
872: return;
873: }
874:
875: sub print_request_logs {
876: return;
877: }
878:
879: sub print_review {
880: my ($r,$state,$dom) = @_;
881: return;
882: }
883:
884: sub courseinfo_form {
1.2 raeburn 885: my ($dom,$formname,$crstype) = @_;
886: my $output = '<div>'.&Apache::lonhtmlcommon::start_pick_box().
887: &Apache::lonhtmlcommon::row_title('Course Description').
888: '<input type="text" size="40" name="cdescr" />'.
889: &Apache::lonhtmlcommon::row_closure(1).
890: &Apache::lonhtmlcommon::end_pick_box().'</div>'.
891: '<div>'.&clone_form($dom,$formname,$crstype).'</div>'."\n";
1.1 raeburn 892: return $output;
893: }
894:
895: sub clone_form {
896: my ($dom,$formname,$crstype) = @_;
897: my $type = 'Course';
898: if ($crstype eq 'community') {
899: $type = 'Community';
900: }
901: my $cloneform = &Apache::loncommon::select_dom_form($dom,'clonedomain').
1.2 raeburn 902: &Apache::loncommon::selectcourse_link($formname,'clonecourse','clonedomain','','','',$type);
1.1 raeburn 903: my %lt = &Apache::lonlocal::texthash(
904: 'cid' => 'Course ID',
905: 'dmn' => 'Domain',
906: 'dsh' => 'Date Shift',
907: 'ncd' => 'Do not clone date parameters',
908: 'prd' => 'Clone date parameters as-is',
909: 'shd' => 'Shift date parameters by number of days',
910: );
1.2 raeburn 911: my $output .=
912: &Apache::lonhtmlcommon::start_pick_box().
913: &Apache::lonhtmlcommon::row_title($lt{'cid'}).'<label>'.
914: '<input type="text" size="25" name="clonecourse" value="" onfocus="this.blur();'.
915: 'opencrsbrowser('."'$formname','clonecourse','clonedomain','','','','$type'".');" />'.
916: '</label>'.&Apache::lonhtmlcommon::row_closure(1).'<label>'.
917: &Apache::lonhtmlcommon::row_title($lt{'dmn'}).'</label>'.
918: $cloneform.'</label>'.&Apache::lonhtmlcommon::row_closure().
919: &Apache::lonhtmlcommon::row_title($lt{'dsh'}).'<label>'.
920: '<input type="radio" name="datemode" value="delete" /> '.$lt{'ncd'}.
921: '</label><br /><label>'.
922: '<input type="radio" name="datemode" value="preserve" /> '.$lt{'prd'}.
923: '</label><br /><label>'.
924: '<input type="radio" name="datemode" value="shift" checked="checked" /> '.
925: $lt{'shd'}.'</label>'.
926: '<input type="text" size="5" name="dateshift" value="365" />'.
927: &Apache::lonhtmlcommon::row_closure(1).
928: &Apache::lonhtmlcommon::end_pick_box();
1.1 raeburn 929: return $output;
930: }
931:
932: sub coursecode_form {
1.2 raeburn 933: my ($dom,$context,$codetitles,$cat_titles,$cat_order,$num) = @_;
1.1 raeburn 934: my $output;
1.2 raeburn 935: my %rowtitle = (
936: instcode => 'Course Category',
937: crosslist => 'Cross Listed Course',
938: );
1.1 raeburn 939: if ((ref($codetitles) eq 'ARRAY') && (ref($cat_titles) eq 'HASH') &&
940: (ref($cat_order))) {
1.2 raeburn 941: my ($sel,$instsec,$lcsec);
942: $sel = $context;
943: if ($context eq 'crosslist') {
944: $sel .= '_'.$num;
945: $instsec = &mt('Institutional section').'<br />'.
946: '<input type="text" size="10" name="'.$sel.'_instsec" />';
947: $lcsec = &mt('LON-CAPA section').'<br />'.
948: '<input type="text" size="10" name="'.$sel.'_lcsec" />';
949: }
1.1 raeburn 950: if (@{$codetitles} > 0) {
951: my $lastitem = pop(@{$codetitles});
1.2 raeburn 952: my $lastinput = '<input type="text" size="5" name="'.$sel.'_'. $lastitem.'" />';
1.1 raeburn 953: if (@{$codetitles} > 0) {
1.2 raeburn 954: $output = &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
955: '<table><tr>';
1.1 raeburn 956: if ($context eq 'crosslist') {
1.2 raeburn 957: $output .= '<td>'.&mt('Include?').'<br />'.
958: '<input type="checkbox" name="'.$sel.'" value="1" /></td>';
1.1 raeburn 959: }
960: foreach my $title (@{$codetitles}) {
961: if (ref($cat_order->{$title}) eq 'ARRAY') {
962: if (@{$cat_order->{$title}} > 0) {
963: $output .= '<td align="center">'.$title.'<br />'."\n".
964: '<select name="'.$sel.'_'.$title.'">'."\n".
965: ' <option value="" selected="selected">'.
966: &mt('Select').'</option>'."\n";
967: foreach my $item (@{$cat_order->{$title}}) {
968: my $longitem = $item;
969: if (ref($cat_titles->{$title}) eq 'HASH') {
970: if ($cat_titles->{$title}{$item} ne '') {
971: $longitem = $cat_titles->{$title}{$item};
972: }
973: }
974: $output .= '<option value="'.$item.'">'.$longitem.
975: '</option>'."\n";
976: }
977: }
978: $output .= '</select></td>'."\n";
979: }
980: }
981: if ($context eq 'crosslist') {
982: $output .= '<td align="center">'.$lastitem.'<br />'."\n".
1.2 raeburn 983: $lastinput.'</td><td align="center">'.$instsec.'</td>'.
984: '<td align="center">'.$lcsec.'</td></tr></table>';
1.1 raeburn 985: } else {
986: $output .= '</tr></table>'.
987: &Apache::lonhtmlcommon::row_closure().
988: &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
989: $lastinput;
990: }
991: } else {
992: if ($context eq 'crosslist') {
993: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1.2 raeburn 994: '<table><tr>'.
995: '<td align="center">'.$lastitem.'<br />'.$lastinput.'</td>'.
996: '<td align="center">'.$instsec.'</td><td>'.$lcsec.'</td>'.
997: '</tr></table>';
1.1 raeburn 998: } else {
999: $output .= &Apache::lonhtmlcommon::row_title('Course '.$lastitem).
1000: $lastinput;
1001: }
1002: }
1.2 raeburn 1003: $output .= &Apache::lonhtmlcommon::row_closure(1);
1004: push(@$codetitles,$lastitem);
1005: } elsif ($context eq 'crosslist') {
1006: $output .= &Apache::lonhtmlcommon::row_title($rowtitle{$context}).
1007: '<table><tr><td align="center">'.
1008: '<span class="LC_nobreak">'.&mt('Include?').
1009: '<input type="checkbox" name="'.$sel.'" value="1" /></span>'.
1010: '</td><td align="center">'.&mt('Institutional ID').'<br />'.
1011: '<input type="text" size="10" name="'.$sel.'_instsec" />'.
1012: '</td><td align="center">'.$lcsec.'</td></tr></table>'.
1013: &Apache::lonhtmlcommon::row_closure(1);
1.1 raeburn 1014: }
1015: }
1016: return $output;
1017: }
1018:
1019: sub get_course_dom {
1020: my $codedom = &Apache::lonnet::default_login_domain();
1021: if (($env{'user.domain'} ne '') && ($env{'user.domain'} ne 'public')) {
1022: $codedom = $env{'user.domain'};
1023: if ($env{'request.role.domain'} ne '') {
1024: $codedom = $env{'request.role.domain'};
1025: }
1026: }
1027: if ($env{'form.showdom'} ne '') {
1028: if (&Apache::lonnet::domain($env{'form.showdom'}) ne '') {
1029: $codedom = $env{'form.showdom'};
1030: }
1031: }
1032: return $codedom;
1033: }
1034:
1035: sub display_navbuttons {
1036: my ($r,$formname,$prev,$prevtext,$next,$nexttext) = @_;
1037: $r->print('<div class="LC_navbuttons">');
1038: if ($prev) {
1039: $r->print('
1040: <input type="button" name="previous" value = "'.$prevtext.'"
1041: onclick="javascript:backPage(document.'.$formname.','."'".$prev."'".')"/>
1042: ');
1043: } elsif ($prevtext) {
1044: $r->print('
1045: <input type="button" name="previous" value = "'.$prevtext.'"
1046: onclick="javascript:history.back()"/>
1047: ');
1048: }
1049: if ($next) {
1050: $r->print('
1051: <input type="button" name="next" value="'.$nexttext.'"
1052: onclick="javascript:nextPage(document.'.$formname.','."'".$next."'".')" />');
1053: }
1054: $r->print('</div>');
1055: }
1056:
1057: sub print_request_outcome {
1058: return;
1059: }
1060:
1.2 raeburn 1061: sub retrieve_settings {
1062: my ($dom,$request_id) = @_;
1063: my %reqinfo = &get_request_settings($request_id,$dom);
1064: my %stored;
1065: $stored{'cdescr'} = &unescape($reqinfo{'description'});
1066: $stored{'startaccess'} = $reqinfo{'startaccess'};
1067: $stored{'endaccess'} = $reqinfo{'endaccess'};
1068: if ($stored{'endaccess'} == 0) {
1069: $stored{'no_end_date'} = 1;
1070: }
1071: $stored{'startenroll'} = $reqinfo{'startenroll'};
1072: $stored{'endenroll'} = $reqinfo{'endenroll'};
1073: $stored{'crosslist'} = $reqinfo{'crosslist'};
1074: $stored{'clonecourse'} = $reqinfo{'clonecourse'};
1075: $stored{'clonedomain'} = $reqinfo{'clonedomain'};
1076: $stored{'sections'} = $reqinfo{'sections'};
1077: $stored{'personnel'} = $reqinfo{'personnel'};
1078:
1079: return %stored;
1080: }
1081:
1082: sub get_request_settings {
1083: my ($request_id,$dom);
1084: }
1085:
1.1 raeburn 1086: 1;
1087:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>