--- loncom/interface/lonrequestcourse.pm 2009/08/12 14:24:35 1.11 +++ loncom/interface/lonrequestcourse.pm 2014/01/05 10:55:35 1.75 @@ -1,7 +1,7 @@ # The LearningOnline Network # Request a course # -# $Id: lonrequestcourse.pm,v 1.11 2009/08/12 14:24:35 raeburn Exp $ +# $Id: lonrequestcourse.pm,v 1.75 2014/01/05 10:55:35 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -44,6 +44,66 @@ described at http://www.lon-capa.org. =item handler() +=item get_breadcrumbs() + +=item header() + +=item form_elements() + +=item onload_action() + +=item print_main_menu() + +=item request_administration() + +=item close_popup_form() + +=item get_instcode() + +=item print_request_form() + +=item print_enrollment_menu() + +=item show_invalid_crosslists() + +=item inst_section_selector() + +=item date_setting_table() + +=item print_personnel_menu() + +=item print_request_status() + +=item print_request_logs() + +=item print_review() + +=item dates_from_form() + +=item courseinfo_form() + +=item clone_form() + +=item clone_text() + +=item coursecode_form() + +=item get_course_dom() + +=item display_navbuttons() + +=item print_request_outcome() + +=item check_autolimit() + +=item retrieve_settings() + +=item get_request_settings() + +=item extract_instcode() + +=item generate_date_items() + =back =cut @@ -56,54 +116,89 @@ use Apache::lonnet; use Apache::loncommon; use Apache::lonlocal; use Apache::loncoursequeueadmin; +use Apache::lonuserutils; use LONCAPA qw(:DEFAULT :match); sub handler { my ($r) = @_; + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; if ($r->header_only) { - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; return OK; } - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['action','showdom','cnum','state','crstype','queue','tabs']); &Apache::lonhtmlcommon::clear_breadcrumbs(); my $dom = &get_course_dom(); my $action = $env{'form.action'}; my $state = $env{'form.state'}; - - my %stored; - my $jscript; - if ((defined($state)) && (defined($action))) { - my %elements = &form_elements($dom); - if (($action eq 'view') && ($state ne 'crstype')) { - if (defined($env{'form.request_id'})) { - %stored = &retrieve_settings($dom,$env{'form.request_id'}); - } - } - my $elementsref = {}; - if (ref($elements{$action}) eq 'HASH') { - if (ref($elements{$action}{$state}) eq 'HASH') { - $elementsref = $elements{$action}{$state}; + my (%states,%stored); + my ($jscript,$uname,$udom,$result,$warning,$showcredits,$instcredits,%can_request, + %request_domains,@incdoms); + my %domdefs = &Apache::lonnet::get_domain_defaults($dom); + if ($domdefs{'officialcredits'} || $domdefs{'unofficialcredits'} || $domdefs{'textbookcredits'}) { + $showcredits = 1; + } + + my $canreq = + &Apache::lonnet::check_can_request($dom,\%can_request,\%request_domains); + + foreach my $item (keys(%request_domains)) { + if (ref($request_domains{$item}) eq 'ARRAY') { + foreach my $possdom (@{$request_domains{$item}}) { + unless(grep(/^\Q$possdom\E$/,@incdoms)) { + push(@incdoms,$possdom); + } } } - $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored); } - if ($state eq 'personnel') { - $jscript .= "\n".&Apache::loncommon::userbrowser_javascript(); + if ($canreq) { + if (($env{'form.crstype'} eq 'textbook') || + (scalar(keys(%can_request)) == 1) && ($can_request{'textbook'})) { + my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom); + if ($action eq 'log') { + my $usetabs; + if ((scalar(keys(%can_request)) == 1) && ($can_request{'textbook'})) { + $usetabs = 1; + } elsif ($env{'form.tabs'} eq 'on') { + $usetabs = 1; + } + &Apache::lonhtmlcommon::add_breadcrumb({text=>'Course Request'}); + my $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'); + &print_request_logs($r,$dom,undef,undef,$crumb,$usetabs); + } elsif ($action eq 'process') { + if ($can_request{'textbook'}) { + &process_textbook_request($r,$dom,$action,\%domdefs,\%domconfig,\%can_request); + } else { + &textbook_request_disabled($r,$dom,\%can_request); + } + } else { + if ($can_request{'textbook'}) { + &print_textbook_form($r,$dom,\@incdoms,\%domdefs,$domconfig{'requestcourses'},\%can_request); + } else { + &textbook_request_disabled($r,$dom,\%can_request); + } + } + return OK; + } } - my $loaditems = &onload_action($action,$state); - - my %states; - $states{'view'} = ['pick_request','details','review','process']; - $states{'log'} = ['filter','display']; + $states{'display'} = ['details']; + $states{'view'} = ['pick_request','details','cancel','removal']; + $states{'log'} = ['display']; $states{'new'} = ['courseinfo','enrollment','personnel','review','process']; + if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) { unless ($env{'form.state'} eq 'crstype') { - unshift (@{$states{'new'}},'codepick'); + unshift(@{$states{'new'}},'codepick'); + } + } + + if (($action eq 'new') && (&Apache::loncoursequeueadmin::author_prompt())) { + if (ref($states{$action}) eq 'ARRAY') { + push(@{$states{$action}},'reqauthor'); } } @@ -113,137 +208,379 @@ sub handler { } } + my @invalidcrosslist; my %trail = ( - crstype => 'Course Request Action', + crstype => 'Pick Action', codepick => 'Category', courseinfo => 'Description', - enrollment => 'Enrollment', + enrollment => 'Access Dates', personnel => 'Personnel', review => 'Review', process => 'Result', + reqauthor => 'Authoring Space Result', pick_request => 'Display Summary', + details => 'Request Details', + cancel => 'Cancel Request', + removal => 'Outcome', + display => 'Request Logs', ); - my $page = 0; - my $crumb; - if (defined($action)) { - my $done = 0; - my $i=0; - if (ref($states{$action}) eq 'ARRAY') { - while ($i<@{$states{$action}} && !$done) { - if ($states{$action}[$i] eq $state) { - $page = $i; - $done = 1; - } - $i++; - } - } - for (my $i=0; $i<@{$states{$action}}; $i++) { - if ($state eq $states{$action}[$i]) { - &Apache::lonhtmlcommon::add_breadcrumb( - {text=>"$trail{$state}"}); - $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'); - last; - } else { - if (($state eq 'process') && ($i > 0)) { - &Apache::lonhtmlcommon::add_breadcrumb( - {href=>"javascript:backPage(document.requestcrs,'$states{$action}[0]')", - text=>"$trail{$states{$action}[$i]}"}); + if (($env{'form.crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) { + $trail{'enrollment'} = 'Enrollment'; + } + + my ($page,$crumb,$newinstcode,$codechk,$checkedcode,$description) = + &get_breadcrumbs($dom,$action,\$state,\%states,\%trail); + if ($action eq 'display') { + if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) { + if ($env{'form.cnum'} ne '') { + my $cnum = $env{'form.cnum'}; + my $queue = $env{'form.queue'}; + my $reqkey = $cnum.'_'.$queue; + my $namespace = 'courserequestqueue'; + my $domconfig = &Apache::lonnet::get_domainconfiguser($dom); + my %queued = + &Apache::lonnet::get($namespace,[$reqkey],$dom,$domconfig); + if (ref($queued{$reqkey}) eq 'HASH') { + $uname = $queued{$reqkey}{'ownername'}; + $udom = $queued{$reqkey}{'ownerdom'}; + if (($udom =~ /^$match_domain$/) && ($uname =~ /^$match_username$/)) { + $result = &retrieve_settings($dom,$cnum,$udom,$uname); + } else { + if ($env{'form.crstype'} eq 'community') { + $warning = &mt('Invalid username or domain for community requestor'); + } else { + $warning = &mt('Invalid username or domain for course requestor'); + } + } } else { - &Apache::lonhtmlcommon::add_breadcrumb( - {href=>"javascript:backPage(document.requestcrs,'$states{$action}[$i]')", - text=>"$trail{$states{$action}[$i]}"}); + if ($env{'form.crstype'} eq 'community') { + $warning = &mt('No information was found for this community request.'); + } else { + $warning = &mt('No information was found for this course request.'); + } } + } else { + $warning = &mt('No course request ID provided.'); + } + } else { + if ($env{'form.crstype'} eq 'any') { + $warning = &mt('You do not have rights to view course or community request information.'); + } elsif ($env{'form.crstype'} eq 'community') { + $warning = &mt('You do not have rights to view community request information.'); + } else { + $warning = &mt('You do not have rights to view course request information.'); } } - } else { - &Apache::lonhtmlcommon::add_breadcrumb( - {text=>'Pick Action'}); - $crumb = &Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests'); + } elsif ((defined($state)) && (defined($action))) { + if (($action eq 'view') && ($state eq 'details')) { + if ((defined($env{'form.showdom'})) && (defined($env{'form.cnum'}))) { + my $result = &retrieve_settings($env{'form.showdom'},$env{'form.cnum'}); + } + } elsif ($env{'form.crstype'} eq 'official') { + if (&Apache::lonnet::auto_run('',$dom)) { + if (($action eq 'new') && (($state eq 'enrollment') || + ($state eq 'personnel'))) { + my $checkcrosslist = 0; + for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) { + if ($env{'form.crosslist_'.$i}) { + $checkcrosslist ++; + } + } + if ($checkcrosslist) { + my %codechk; + my (@codetitles,%cat_titles,%cat_order,@code_order,$lastitem); + &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles, + \%cat_titles, + \%cat_order, + \@code_order); + my $numtitles = scalar(@codetitles); + if ($numtitles) { + for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) { + if ($env{'form.crosslist_'.$i}) { + my $codecheck; + my $crosslistcode = ''; + foreach my $item (@code_order) { + $crosslistcode .= $env{'form.crosslist_'.$i.'_'.$item}; + } + if ($crosslistcode ne '') { + ($codechk{$i}, my $rest) = + &Apache::lonnet::auto_validate_instcode('',$dom,$crosslistcode); + } + unless ($codechk{$i} eq 'valid') { + $env{'form.crosslist_'.$i} = ''; + push(@invalidcrosslist,$crosslistcode); + } + } + } + } + } + } + } + } + (my $elements,$instcredits) = &form_elements($dom,$showcredits); + my $elementsref = {}; + if ((ref($elements) eq 'HASH') && (ref($elements->{$action}) eq 'HASH')) { + if (ref($elements->{$action}{$state}) eq 'HASH') { + $elementsref = $elements->{$action}{$state}; + } + } + if (($state eq 'courseinfo') && ($env{'form.clonedom'} eq '')) { + $env{'form.clonedom'} = $dom; + } + if ($state eq 'crstype') { + $jscript = &mainmenu_javascript(); + } else { + $jscript = &Apache::lonhtmlcommon::set_form_elements($elementsref,\%stored); + if ($state eq 'courseinfo') { + $jscript .= &cloning_javascript(); + } + } + } + + if ($state eq 'personnel') { + $jscript .= "\n".&Apache::loncommon::userbrowser_javascript(); } - my %can_request; - my $canreq = &check_can_request($dom,\%can_request); + my $loaditems = &onload_action($action,$state); + if ($action eq 'new') { if ($canreq) { if ($state eq 'crstype') { &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems, - $crumb); + $crumb,\@incdoms); } else { - &request_administration($r,$action,$state,$page,\%states,$dom,$jscript, - $loaditems,$crumb); + &request_administration($r,$action,$state,$page,\%states,$dom, + $jscript,$loaditems,$crumb,$newinstcode, + $codechk,$checkedcode,$description, + $showcredits,$instcredits,\@invalidcrosslist); } } else { - $r->print(&header('Course Requests').$crumb. + $r->print(&header('Course/Community Requests').$crumb. '
'. + &mt('Modify this request').''.(' 'x4). + ''.&mt('Make another request').'
'); + } + if (&Apache::loncoursequeueadmin::author_prompt()) { + &print_author_prompt($r,$env{'form.action'},$env{'form.cnum'},$env{'form.showdom'}, + $env{'form.crstype'},$storeresult); + } elsif ($storeresult eq 'created') { + $r->print(''.&mt('Make another request').'
'); + } + } + } elsif ($state eq 'reqauthor') { + my ($result,@links); + if ($env{'form.requestauthor'}) { + $r->print(&Apache::loncoursequeueadmin::process_reqauthor(\$result)); + if ($result eq 'created') { + my $role = 'au'; + my $spec = "$role./$env{'form.showdom'}/"; + push(@links,&mt('Enter your authoring space with role: [_1]', + ''. + &Apache::lonnet::plaintext($role).'')); + } + } + if (($env{'form.disposition'} eq 'created') && + ($env{'form.cnum'} =~ /^$match_courseid$/) && + ($env{'form.showdom'} =~ /^$match_domain$/)) { + my ($spec,$area,$role,$type); + my $role = 'cc'; + my $spec = "$role./$env{'form.showdom'}/$env{'form.cnum'}"; + my $type = 'Course'; + if ($env{'form.crstype'} eq 'community') { + $type = 'Community'; + } + my $showrole = &Apache::lonnet::plaintext($role,$type); + unshift(@links,&mt('Enter new course with role: [_1]', + ''.$showrole.'')); + } + if (@links > 1) { + $r->print(&mt('New roles will be listed on your [_1]Roles[_2] page.', + '','').' '.&mt('Choose a role:'). + ''.$links[0].'
'); + } + } + my @excluded = &get_excluded_elements($dom,$states,$action,$state,$showcredits); + if ($state eq 'personnel') { + push(@excluded,'persontotal'); + } + if ($state eq 'review') { + if (@disallowed > 0) { + my @items = qw(uname dom lastname firstname emailaddr hidedom role newsec); + my @currsecs = ¤t_lc_sections(); + if (@currsecs) { + push(@items,'sec'); + } + my $count = 0; + for (my $i=0; $i<$env{'form.persontotal'}; $i++) { + unless ($env{'form.person_'.$i.'_uname'} eq '') { + if (grep(/^$i$/,@disallowed)) { + foreach my $item (@items) { + $env{'form.person_'.$i.'_'.$item} = ''; + } + } else { + foreach my $item (@items) { + $env{'form.person_'.$count.'_'.$item} = $env{'form.person_'.$i.'_'.$item}; + } + } + } + $count ++; + } + $env{'form.persontotal'} = $count; + } } + if ($state eq 'enrollment') { + push(@excluded,('sectotal','crosslisttotal')); + } + if (($state eq 'process') || ($state eq 'reqauthor')) { + $r->print(''); + } else { + $r->print(&Apache::lonhtmlcommon::echo_form_input(\@excluded).''); + &display_navbuttons($r,$dom,$formname,$prev,$navtxt{'prev'},$next, + $navtxt{'next'},$state); + } + return; +} + +sub print_author_prompt { + my ($r,$action,$cnum,$showdom,$crstype,$storeresult) = @_; + $r->print(''.
+ &mt('Although assessment items can be created directly inside a course, such items only use part of the assessment capabilities of LON-CAPA.').
+ '
'.
+ &mt('By contrast, items created in authoring space, then imported into a course, can use all of the features of the assessment engine.').'
'.&mt('Request authoring space access now?'). + ' '. + ''. + (' 'x2). + ''. + '
'. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + ''.&mt('Username').' '.$uname_form.' | '."\n".
- ''.&mt('Domain').' '.$udom_form.' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'.&mt('First Name').' '.$form_elems{'first'}.' | '."\n".
- ''.&mt('Last Name').' '.$form_elems{'last'}.' | '."\n".
- ''.&mt('E-mail').' '.$form_elems{email}.' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'.&mt('Role').' '.$roleselector.' | '."\n".
- ''.&mt('Section(s)').' '.$sectionselector.' | '."\n".
+ &Apache::lonhtmlcommon::row_title(&mt('Additional Personnel')).
+ '
'.$usersrchlink.' | '."\n". + ''.
+ &mt('Username').': '.$uname_form.' '.$userchklink.' '."\n". + ''.&mt('Domain').': '.$udom_form.' | '.
+ '|
'.&mt('First Name').' '.$form_elems{'firstname'}.' | '."\n".
+ ''.&mt('Last Name').' '.$form_elems{'lastname'}.' | '."\n".
+ ''.&mt('E-mail').' '.$form_elems{'emailaddr'}.' |
'.&Apache::loncommon::help_open_topic('Course_Roles').' '.&mt('Role').' '.$roleselector.' | '."\n".
+ ''.
+ &Apache::loncommon::help_open_topic('Course_Request_Rolesection').' '.&mt('LON-CAPA Section(s)').' '.$sectionselector.' | '."\n".
'
'.&mt('You may also add users later, once the community has been created, by using the "Manage community users" link, accessible from the "Main Menu".').'
'; + } else { + $output .= ''.&mt('You may also add users later, once the course has been created, by using the "Manage course users" link, accessible from the "Main Menu".').'
'; + } return $output; } -sub print_request_status { - my ($dom) = @_; - my %requests = &Apache::lonnet::dumpstore('courserequests',$env{'user.domain'}, - $env{'user.name'}); - my ($output,$formname,%queue_by_date); - foreach my $key (keys(%requests)) { - if (ref($requests{$key}) eq 'HASH') { - my ($cdom,$cnum) = split('_',$key); - next if ($cdom ne $dom); +sub current_lc_sections { + my @currsecs; + if ($env{'form.sectotal'}) { + for (my $i=0; $i<$env{'form.sectotal'}; $i++) { + if ($env{'form.sec_'.$i}) { + if (defined($env{'form.loncapasec_'.$i})) { + my $lcsec = $env{'form.loncapasec_'.$i}; + unless (grep(/^\Q$lcsec\E$/,@currsecs)) { + push(@currsecs,$lcsec); + } + } + } + } + } + return @currsecs; +} + +sub sorted_request_history { + my ($dom,$action,$curr_req) = @_; + my ($after,$before,$statusfilter,$crstypefilter); + if ($env{'form.status'} ne '') { + $statusfilter = $env{'form.status'}; + } + if ($env{'form.crstype'} ne '') { + $crstypefilter = $env{'form.crstype'}; + } + if (ref($curr_req) eq 'HASH') { + $after = $curr_req->{'requested_after_date'}, + $before = $curr_req->{'requested_before_date'}; + $statusfilter = $curr_req->{'status'}; + $crstypefilter = $curr_req->{'crstype'}; + } + my %statusinfo = &Apache::lonnet::dump('courserequests',$env{'user.domain'}, + $env{'user.name'},'^status:'.$dom); + my %queue_by_date; + my ($types,$typenames) = &Apache::loncommon::course_types(); + foreach my $key (keys(%statusinfo)) { + if ($action eq 'view') { + next unless (($statusinfo{$key} eq 'approval') || ($statusinfo{$key} eq 'pending')); + } else { + next unless (($statusfilter eq 'any') || + ($statusfilter eq $statusinfo{$key})); + } + (undef,my($cdom,$cnum)) = split(':',$key); + next if ($cdom ne $dom); + my $requestkey = $cdom.'_'.$cnum; + if ($requestkey =~ /^($match_domain)_($match_courseid)$/) { + my %history = &Apache::lonnet::restore($requestkey,'courserequests', + $env{'user.domain'},$env{'user.name'}); my $entry; - my $timestamp = $requests{$key}{'timestamp'}; - my $crstype = $requests{$key}{'crstype'}; - my $status = $requests{$key}{'status'}; - next unless (($env{'form.crstype'} eq 'all') || - ($env{'form.crstype'} eq $crstype)); - next unless (($status eq 'approval') || ($status eq 'pending')); - if (ref($requests{$key}{'details'}) eq 'HASH') { - $entry = $key.':'.$crstype.':'.$requests{$key}{'details'}{'cdesc'}; + my $reqtime = $history{'reqtime'}; + my $lastupdate = $history{'timestamp'}; + my $crstype = $history{'crstype'}; + my $disposition = $history{'disposition'}; + my $status = $history{'status'}; + my $uniquecode = $history{'code'}; + if ($action eq 'view') { + next if ((exists($history{'status'})) && ($history{'status'} eq 'created')); + } else { + next if (($reqtime < $after) || ($reqtime > $before)); + } + next unless (($crstypefilter eq 'any') || + ($crstypefilter eq $crstype)); + if ($action eq 'view') { + next unless (($disposition eq 'approval') || + ($disposition eq 'pending')); + } + if (ref($history{'details'}) eq 'HASH') { + $entry = $requestkey.':'.$crstype.':'. + &escape($history{'details'}{'cdescr'}); + if ($action eq 'log') { + $entry .= ':'.$uniquecode.':'.$lastupdate.':'; + if ($statusinfo{$key} ne '') { + $entry .= $statusinfo{$key}; + } elsif ($status ne '') { + $entry .= $status; + } else { + $entry .= $disposition; + } + } if ($crstype eq 'official') { - $entry .= ':'.$requests{$key}{'details'}{'instcode'}; + $entry .= ':'.&escape($history{'details'}{'instcode'}); } } if ($entry ne '') { - if (exists($queue_by_date{$timestamp})) { - if (ref($queue_by_date{$timestamp}) eq 'ARRAY') { - push(@{$queue_by_date{$timestamp}},$entry); + if (exists($queue_by_date{$reqtime})) { + if (ref($queue_by_date{$reqtime}) eq 'ARRAY') { + push(@{$queue_by_date{$reqtime}},$entry); } } else { - @{$queue_by_date{$timestamp}} = ($entry); + @{$queue_by_date{$reqtime}} = ($entry); } } } } - $formname = 'requestcrs'; + return %queue_by_date; +} + +sub print_request_status { + my ($dom,$action) = @_; + my %queue_by_date = &sorted_request_history($dom,$action); my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date)); - $output = ''.&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '
'.&mt('Previous [_1] changes',$curr{'show'}).' | '); + } + if ($more_records) { + $r->print(''.&mt('Next [_1] changes',$curr{'show'}).' | '); + } + $r->print('
'. + &mt('There are no records to display'). + '
'); + } + if ($usetabs) { + $r->print(''); + } + $r->print(''.
+ ''.&mt('Records/page:').' '. + &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + ' | '; + my $startform = + &Apache::lonhtmlcommon::date_setter($formname,'requested_after_date', + $curr->{'requested_after_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + my $endform = + &Apache::lonhtmlcommon::date_setter($formname,'requested_before_date', + $curr->{'requested_before_date'},undef, + undef,undef,undef,undef,undef,undef,$nolink); + $output .= ' | '.&mt('Window during which course/community was requested:').' '. + '
| '.
+ ''; + my ($types,$typenames) = &Apache::loncommon::course_types(); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 1) { + $output .= ' | '.
+ &mt('Course Type:').' | ';
+ }
+ }
+ my ($statuses,$statusnames) = &reqstatus_names($curr->{'crstype'});
+ if (ref($statuses) eq 'ARRAY') {
+ if (@{$statuses} > 1) {
+ $output .= ''.
+ &mt('Request Status:').' | ';
+ }
+ }
+ $output .= '
'. + ''. + '
'. &mt('Institutional section').' | '. ''.&mt('LON-CAPA section').' | '.&mt('LON-CAPA section').' | '; my $xlistinfo; - if ($env{'form.crosslisttotal'}) { - for (my $i=0; $i<$env{'form.crosslisttotal'}; $i++) { - if ($env{'form.crosslist_'.$i}) { - $xlistinfo .= '
---|---|
'; - if (ref($code_order) eq 'ARRAY') { - if (@{$code_order} > 0) { - foreach my $item (@{$code_order}) { - $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item}; - } + my $crosslisttotal = $env{'form.crosslisttotal'}; + if (!$crosslisttotal) { + $crosslisttotal = 1; + } + for (my $i=0; $i<$crosslisttotal; $i++) { + if ($env{'form.crosslist_'.$i}) { + $xlistinfo .= ' | |
'; + if (ref($code_order) eq 'ARRAY') { + if (@{$code_order} > 0) { + foreach my $item (@{$code_order}) { + $xlistinfo .= $env{'form.crosslist_'.$i.'_'.$item}; } } - $xlistinfo .= $env{'form.crosslist_'.$i.'_instsec'}.' | '; - if ($env{'form.crosslist_'.$i.'_lcsec'}) { - $xlistinfo .= $env{'form.crosslist_'.$i.'_lcsec'}; - } else { - $xlistinfo .= &mt('None'); - } - $xlistinfo .= ' | '; + if ($env{'form.crosslist_'.$i.'_lcsec'}) { + $xlistinfo .= $env{'form.crosslist_'.$i.'_lcsec'}; + } else { + $xlistinfo .= &mt('None'); + } + $xlistinfo .= ' | '; } } if ($xlistinfo eq '') { $xlistinfo = '
'.&mt('None').' |
'.&mt('Review the details of the course request before submission.').'
'. - ''. + &mt('Not all requested personnel could be included.').'
'.&mt('Name').' | '. @@ -1202,7 +2978,7 @@ sub print_review { '
---|
'.&mt('Include?').' '. @@ -1373,70 +3223,162 @@ sub coursecode_form { return $output; } +sub sections_form { + my ($dom,$instcode,$num) = @_; + my $rowtitle; + if ($instcode eq '') { + $rowtitle = &mt('Sections'); + } else { + $rowtitle = &mt('Sections of [_1]',$instcode); + } + return &Apache::lonhtmlcommon::row_title($rowtitle). + '
'.$message.' ';
}
+ $storeresult = 'rejected';
} elsif ($disposition eq 'process') {
+ my %domdefs = &Apache::lonnet::get_domain_defaults($dom);
+ my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles,$code);
my $type = 'Course';
if ($crstype eq 'community') {
$type = 'Community';
}
- my ($logmsg,$newusermsg,$addresult,$enrollcount,$output,$keysmsg,%longroles);
- my @roles = &Apache::lonuserutils::roles_by_context('course');
+ my @roles = &Apache::lonuserutils::roles_by_context('course','',$type);
foreach my $role (@roles) {
$longroles{$role}=&Apache::lonnet::plaintext($role,$type);
}
- my %reqdetails = &build_batchcreatehash($details);
- my $cid = &LONCAPA::batchcreatecourse::build_course($dom,$cnum,'request',\%reqdetails,\%longroles,\$logmsg,\$newusermsg,\$addresult,\$enrollcount,\$output,\$keysmsg,$env{'user.domain'},$env{'user.name'},$cnum);
- $disposition = 'created';
- if ($cid eq $cnum) {
+ my ($result,$postprocess) = &Apache::loncoursequeueadmin::course_creation($dom,$cnum,
+ 'autocreate',$details,\$logmsg,\$newusermsg,\$addresult,
+ \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles,
+ \$code,\%customitems);
+ if ($result eq 'created') {
$disposition = 'created';
- $output = &mt('Your course request has been processed and the course has been created.').''.&mt('You will need to logout and log-in again to be able to select a role in the course.'); + $reqstatus = 'created'; + my $role_result = &update_requestors_roles($dom,$cnum,$crstype,$details, + \%longroles); + if ($crstype eq 'community') { + $output = ' '.&mt('Your community request has been processed and the community has been created.'); + } else { + $output = ' '.&mt('Your course request has been processed and the course has been created.');
+ }
+ if (($code) || ((ref($postprocess) eq 'HASH') &&
+ (($postprocess->{'createdweb'}) || ($postprocess->{'createdmsg'})))) {
+ $output .= ¬ification_information($disposition,$env{'user.name'}.':'.$env{'user.domain'},
+ $dom,$cnum,$now,$code,$postprocess);
+ }
+ if ($code) {
+ $reqhash{'code'} = $code;
+ }
+ $output .= ' '.&mt('You may want to review the request details and submit the request again.'); + $output = ''; + if ($crstype eq 'community') { + $output .= &mt('An error occurred when processing your community request.'); + } else { + $output .= &mt('An error occurred when processing your course request.'); + } + $output .= ' '. + &mt('You may want to review the request details and submit the request again.'). + ''; + $creationresult = 'error'; } } else { my $requestid = $cnum.'_'.$disposition; - my $request = { + my $request = { $requestid => { timestamp => $now, crstype => $crstype, ownername => $env{'user.name'}, ownerdom => $env{'user.domain'}, - description => $env{'form.cdesc'}, + description => $env{'form.cdescr'}, }, }; - my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request, - $dom); - if ($putresult eq 'ok') { - my %emails = &Apache::loncommon::getemails(); - my $address; - if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) { - $address = $emails{'permanentemail'}; - if ($address eq '') { - $address = $emails{'notification'}; - } - } - $output = &mt('Your course request has been recorded.').' '; - if ($disposition eq 'approval') { - $output .= &mt('Your course request has been recorded.').' '. - &mt('A message will be sent to your LON-CAPA account when a domain coordinator takes action on your request.').' '. - &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').' '; - if ($address ne '') { - $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).' '; - } - if ($req_notifylist) { - my $fullname = &Apache::loncommon::plainname($env{'user.name'}, - $env{'user.domain'}); - &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,$fullname,$now,$dom,$details); + if ($crstype eq 'official') { + $request->{$requestid}->{'instcode'} = $instcode; + } + my $statuskey = 'status:'.$dom.':'.$cnum; + my %userreqhash = &Apache::lonnet::get('courserequests',[$statuskey], + $env{'user.domain'},$env{'user.name'}); + if ($userreqhash{$statuskey} ne '') { + $modified = 1; + my $uname = &Apache::lonnet::get_domainconfiguser($dom); + my %queuehash = &Apache::lonnet::get('courserequestqueue', + [$cnum.'_approval', + $cnum.'_pending'],$dom,$uname); + if (($queuehash{$cnum.'_approval'} ne '') || + ($queuehash{$cnum.'_pending'} ne '')) { + $queued = 1; + } + } + unless ($queued) { + my $putresult = &Apache::lonnet::newput_dom('courserequestqueue',$request, + $dom); + if ($putresult eq 'ok') { + if ($crstype eq 'community') { + $output .= &mt('Your community request has been recorded.'); + } else { + $output .= &mt('Your course request has been recorded.') } + $output .= ' '. + ¬ification_information($disposition,$req_notifylist, + $dom,$cnum,$now); } else { - $output .= ' '.
-&mt('Your request has been placed in a queue pending administrative action.').' ';
+ $reqstatus = 'domainerror';
+ $reqhash{'disposition'} = $disposition;
+ my $warning = &mt('An error occurred saving your request in the pending requests queue.');
+ $output = ''.$warning.''. -&mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").' '. -&mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.'). - ' '; } + } + } + ($storeresult,my $updateresult) = + &Apache::loncoursequeueadmin::update_coursereq_status(\%reqhash,$dom, + $cnum,$reqstatus,'request',$env{'user.domain'},$env{'user.name'}); + if ($modified && $queued && $storeresult eq 'ok') { + if ($crstype eq 'community') { + $output .= ' '.&mt('Your community request has been updated').' '; } else { - $reqhash{'status'} = 'domainerror'; - $reqhash{'disposition'} = $disposition; - my $warning = &mt('An error occurred saving your request in the pending requests queue.'); - $output = ''.$warning.''; - + $output .= ' '.&mt('Your course request has been updated').' '; + } + $output .= ¬ification_information($disposition,$req_notifylist,$dom,$cnum,$now); + if ($disposition eq 'approval') { + my $fullname = &Apache::loncommon::plainname($env{'user.name'}, + $env{'user.domain'}); + my $postprocess = + &Apache::lonnet::auto_crsreq_update($dom,$cnum,$crstype,'queued',$env{'user.name'}, + $env{'user.domain'},$fullname,$env{'form.cdescr'}); + if ((ref($postprocess) eq 'HASH') && + ((ref($postprocess->{'queuedmsg'}) eq 'HASH') || ($postprocess->{'queuedweb'}))) { + my $recipient = $env{'user.name'}.':'.$env{'user.domain'}; + $output .= ¬ification_information($disposition,$recipient,$dom,$cnum,$now,undef,$postprocess); + } } } - my $storeresult; - if ($requestkey =~ /^($match_domain)_($match_courseid)$/) { - $storeresult = &Apache::lonnet::store_userdata(\%reqhash,$requestkey, - 'courserequests'); - } else { - $storeresult = 'error: invalid requestkey format'; + if ($validationerror ne '') { + $output .= ''.&mt('An error occurred validating your request with institutional data sources: [_1].',$validationerror).' '; } - if ($storeresult ne 'ok') { - $output .= ''.&mt('An error occurred saving a record of the details of your request.').''; - &logthis("Error saving course request - $requestkey for $env{'user.name'}:$env{'user.domain'} - $storeresult"); + if ($updateresult) { + $output .= $updateresult; } } - return $output; + if ($creationresult ne '') { + return ($creationresult,$output); + } else { + return ($storeresult,$output); + } } -sub get_processtype { - my ($dom,$crstype,$inststatuses,$domconfig) = @_; - return unless ((ref($inststatuses) eq 'ARRAY') && (ref($domconfig) eq 'HASH')); - my (%userenv,%settings,$val); - my @options = ('autolimit','validate','approve'); - if ($dom eq $env{'user.domain'}) { - %userenv = - &Apache::lonnet::userenvironment($env{'user.domain'},$env{'user.name'}, - 'requestcourses.'.$crstype,'inststatus'); - if ($userenv{'requestcourses.'.$crstype}) { - $val = $userenv{'requestcourses.'.$crstype}; - @{$inststatuses} = ('_custom_'); - } else { - my ($task,%alltasks); - if (ref($domconfig->{'requestcourses'}) eq 'HASH') { - %settings = %{$domconfig->{'requestcourses'}}; - if (ref($settings{$crstype}) eq 'HASH') { - if (($env{'user.adv'}) && (exists($settings{$crstype}{'_LC_adv'}))) { - $val = $settings{$crstype}{'_LC_adv'}; - @{$inststatuses} = ('_LC_adv_'); +sub update_requestors_roles { + my ($dom,$cnum,$crstype,$details,$longroles) = @_; + my $now = time; + my ($active,$future,$numactive,$numfuture,$output); + my $owner = $env{'user.name'}.':'.$env{'user.domain'}; + if (ref($details) eq 'HASH') { + if (ref($details->{'personnel'}) eq 'HASH') { + my $ccrole = 'cc'; + if ($crstype eq 'community') { + $ccrole = 'co'; + } + unless (ref($details->{'personnel'}{$owner}) eq 'HASH') { + $details->{'personnel'}{$owner} = { + 'roles' => [$ccrole], + $ccrole => { 'usec' => [] }, + }; + } + my @roles; + if (ref($details->{'personnel'}{$owner}{'roles'}) eq 'ARRAY') { + @roles = sort(@{$details->{'personnel'}{$owner}{'roles'}}); + unless (grep(/^\Q$ccrole\E$/,@roles)) { + push(@roles,$ccrole); + } + } else { + @roles = ($ccrole); + } + foreach my $role (@roles) { + my $refresh=$env{'user.refresh.time'}; + if ($refresh eq '') { + $refresh = $env{'user.login.time'}; + } + if ($refresh eq '') { + $refresh = $now; + } + my $start = $refresh-1; + my $end = '0'; + if ($role eq 'st') { + if ($details->{'accessstart'} ne '') { + $start = $details->{'accessstart'}; + } + if ($details->{'accessend'} ne '') { + $end = $details->{'accessend'}; + } + } + my @usecs; + if ($role ne $ccrole) { + if (ref($details->{'personnel'}{$owner}{$role}{'usec'}) eq 'ARRAY') { + @usecs = @{$details->{'personnel'}{$owner}{$role}{'usec'}}; + } + } + if ($role eq 'st') { + if (@usecs > 1) { + my $firstsec = $usecs[0]; + @usecs = ($firstsec); + } + } + if (@usecs == 0) { + push(@usecs,''); + } + foreach my $usec (@usecs) { + my (%userroles,%newrole,%newgroups,$spec,$area); + my $area = '/'.$dom.'/'.$cnum; + my $spec = $role.'.'.$area; + if ($usec ne '') { + $spec .= '/'.$usec; + $area .= '/'.$usec; + } + if ($role =~ /^cr\//) { + &Apache::lonnet::custom_roleprivs(\%newrole,$role,$dom, + $cnum,$spec,$area); } else { - if ($userenv{'inststatus'} ne '') { - @{$inststatuses} = split(',',$userenv{'inststatus'}); - } else { - @{$inststatuses} = ('other'); - } - foreach my $status (@{$inststatuses}) { - if (exists($settings{$crstype}{$status})) { - my $value = $settings{$crstype}{$status}; - next unless ($value); - unless (exists($alltasks{$value})) { - if (ref($alltasks{$value}) eq 'ARRAY') { - unless(grep(/^\Q$status\E$/,@{$alltasks{$value}})) { - push(@{$alltasks{$value}},$status); - } - } else { - @{$alltasks{$value}} = ($status); - } - } + &Apache::lonnet::standard_roleprivs(\%newrole,$role,$dom, + $spec,$cnum,$area); + } + &Apache::lonnet::set_userprivs(\%userroles,\%newrole, + \%newgroups); + $userroles{'user.role.'.$spec} = $start.'.'.$end; + &Apache::lonnet::appenv(\%userroles,[$role,'cm']); + if (($end == 0) || ($end > $now)) { + my $showrole = $role; + if ($role =~ /^cr\//) { + $showrole = &Apache::lonnet::plaintext($role,$crstype); + } elsif (ref($longroles) eq 'HASH') { + if ($longroles->{$role} ne '') { + $showrole = $longroles->{$role}; } } - my $maxlimit = 0; - foreach my $key (sort(keys(%alltasks))) { - if ($key =~ /^autolimit=(\d*)$/) { - if ($1 eq '') { - $val ='autolimit='; - last; - } elsif ($1 > $maxlimit) { - $maxlimit = $1; - } + if ($start <= $now) { + $active .= '
'; + } + if ($future) { + if ($crstype eq 'Community') { + $output .= &mt('The following community [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'','',&Apache::lonlocal::locallocaltime($details->{'accessstart'})) + } else { + $output .= &mt('The following course [quant,_1,role] will become available for selection from your [_2]roles page[_3], once the default student access start date - [_4] - has been reached:',$numfuture,'','',&Apache::lonlocal::locallocaltime($details->{'accessstart'})); + } + $output .= '
'. + &mt('To access your LON-CAPA message, go to the Main Menu and click on "Send and Receive Messages".').' '; + if ($address ne '') { + $output.= &mt('An e-mail will also be sent to: [_1] when this occurs.',$address).' '; + } + if ($req_notifylist) { + my $fullname = &Apache::loncommon::plainname($env{'user.name'}, + $env{'user.domain'}); + my $sender = $env{'user.name'}.':'.$env{'user.domain'}; + &Apache::loncoursequeueadmin::send_selfserve_notification($req_notifylist,"$fullname ($env{'user.name'}:$env{'user.domain'})", + 'undef',$env{'form.cdescr'},$now,'coursereq',$sender); + } + if (ref($postprocess) eq 'HASH') { + if (ref($postprocess->{'queuedmsg'}) eq 'ARRAY') { + if (scalar(@{$postprocess->{'queuedmsg'}}) > 0) { + my $recipient = $env{'user.name'}.':'.$env{'user.domain'}; + my $sender = $recipient; + my $addmsg = []; + foreach my $item (@{$postprocess->{'queuedmsg'}}) { + if (ref($item) eq 'HASH') { + if ($item->{'mt'} ne '') { + push(@{$addmsg},$item); } } } + if (scalar(@{$addmsg}) > 0) { + &Apache::loncoursequeueadmin::send_selfserve_notification($recipient,$addmsg,undef, + $env{'form.cdescr'},$now, + 'queuedreq',$sender); + } } } + if ($postprocess->{'queuedweb'}) { + $output .= $postprocess->{'queuedweb'}; + } } - } else { - %userenv = &Apache::lonnet::userenvironment($env{'user.domain'}, - $env{'user.name'},'reqcrsotherdom.'.$env{'form.crstype'}); - if ($userenv{'reqcrsotherdom'}) { - my @doms = split(',',$userenv{'reqcrsotherdom'}); - my $optregex = join('|',@options); - if (grep(/^\Q$dom\E:($optregex=?\d*)/,@doms)) { - $val = $1; + } elsif ($disposition eq 'pending') { + $output .= ' '.
+&mt('Your request has been placed in a queue pending administrative action.').' ';
+ } elsif ($disposition eq 'created') {
+ if (($code) || ((ref($postprocess) eq 'HASH') &&
+ ((ref($postprocess->{'createdmsg'}) eq 'ARRAY') || ($postprocess->{'createdweb'})))) {
+ my $addmsg = [];
+ my $recipient = $env{'user.name'}.':'.$env{'user.domain'};
+ my $sender = $recipient;
+ if ($code) {
+ push(@{$addmsg},{
+ mt => 'Students can automatically select your course: "[_1]" by entering this code: [_2]',
+ args => [$env{'form.cdescr'},$code],
+ });
+ $output .= ''. +&mt("Usually this means that your institution's information systems do not list you among the instructional personnel for this course.").' '. +&mt('The list of instructional personnel for the course will be automatically checked daily, and once you are listed the request will be processed.'). + ' '.
+ &mt('Students can automatically select your course by entering this code: [_1].',''.$code.'').
+ ' '.
+ &mt('Your request status is: [_1].',$disposition).
+ ' ';
}
- return $val;
+ return $output;
}
sub check_autolimit {
my ($uname,$udom,$dom,$crstype,$limit,$message) = @_;
my %crsroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},
- 'userroles',['active','future'],['cc'],[$dom]);
- my ($types,$typename) = &course_types();
+ 'userroles',['active','future'],['cc','co'],[$dom]);
+ my ($types,$typename) = &Apache::loncommon::course_types();
my %requests = &Apache::lonnet::dumpstore('courserequests',$udom,$uname);
- my %count;
- if (ref($types) eq 'ARRAY') {
- foreach my $type (@{$types}) {
- $count{$type} = 0;
- }
- }
+ my $count = 0;
foreach my $key (keys(%requests)) {
my ($cdom,$cnum) = split('_',$key);
- if (exists($crsroles{$cnum.':'.$cdom.':cc'})) {
- if (ref($requests{$key}) eq 'HASH') {
- my $type = $requests{$key}{'crstype'};
- if ($type =~ /^official|unofficial|community$/) {
- $count{$type} ++;
- }
+ if (ref($requests{$key}) eq 'HASH') {
+ next if ($requests{$key}{'crstype'} ne $crstype);
+ if (($crstype eq 'community') &&
+ (exists($crsroles{$cnum.':'.$cdom.':co'}))) {
+ $count ++;
+ } elsif ((($crstype eq 'official') || ($crstype eq 'unofficial') || ($crstype eq 'textbook')) &&
+ (exists($crsroles{$cnum.':'.$cdom.':cc'}))) {
+ $count ++;
}
}
}
- if ($count{$crstype} < $limit) {
+ if ($count < $limit) {
return 'process';
} else {
if (ref($typename) eq 'HASH') {
- $$message = &mt('Your request has not been processed because you have reached the limit for the number of courses of this type.').''.&mt("Your $typename->{$crstype} limit is [_1].",$limit); + if ($crstype eq 'community') { + $$message = &mt('Your request has not been processed because you have reached the limit for the number of communities.'). + ' '.&mt("Your limit is [_1].",$limit); + } else { + $$message = &mt('Your request has not been processed because you have reached the limit for the number of courses of this type.'). + ' '.&mt("Your $typename->{$crstype} limit is [_1].",$limit); + } } return 'rejected'; } return; } -sub build_batchcreatehash { - my ($details) = @_; - my %batchhash; - if (ref($details) eq 'HASH') { +sub retrieve_settings { + my ($dom,$cnum,$udom,$uname) = @_; + if ($udom eq '' || $uname eq '') { + $udom = $env{'user.domain'}; + $uname = $env{'user.name'}; + } + my ($result,%reqinfo) = &get_request_settings($dom,$cnum,$udom,$uname); + if ($result eq 'ok') { + if (($udom eq $reqinfo{'domain'}) && ($uname eq $reqinfo{'owner'})) { + $env{'form.chome'} = $reqinfo{'coursehome'}; + $env{'form.cdescr'} = $reqinfo{'cdescr'}; + $env{'form.crstype'} = $reqinfo{'crstype'}; + &generate_date_items($reqinfo{'accessstart'},'accessstart'); + &generate_date_items($reqinfo{'accessend'},'accessend'); + if ($reqinfo{'accessend'} == 0) { + $env{'form.no_end_date'} = 1; + } + if (($reqinfo{'crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) { + &generate_date_items($reqinfo{'enrollstart'},'enrollstart'); + &generate_date_items($reqinfo{'enrollend'},'enrollend'); + } + $env{'form.clonecrs'} = $reqinfo{'clonecrs'}; + $env{'form.clonedom'} = $reqinfo{'clonedom'}; + if (($reqinfo{'clonecrs'} ne '') && ($reqinfo{'clonedom'} ne '')) { + $env{'form.cloning'} = 1; + } + $env{'form.datemode'} = $reqinfo{'datemode'}; + $env{'form.dateshift'} = $reqinfo{'dateshift'}; + if ($reqinfo{'crstype'} eq 'official') { + $env{'form.autoadds'} = $reqinfo{'autoadds'}; + $env{'form.autodrops'} = $reqinfo{'autodrops'}; + if ($reqinfo{'instcode'} ne '') { + $env{'form.sectotal'} = $reqinfo{'sectotal'}; + $env{'form.crosslisttotal'} = $reqinfo{'crosslisttotal'}; + $env{'form.instcode'} = $reqinfo{'instcode'}; + my $crscode = { + $cnum => $reqinfo{'instcode'}, + }; + &extract_instcode($dom,'instcode',$crscode,$cnum); + (undef,undef,my $instcredits) = + &Apache::lonnet::auto_validate_instcode(undef,$dom, + $reqinfo{'instcode'}); + if ($instcredits ne $reqinfo{'defaultcredits'}) { + $env{'form.coursecredits'} = $reqinfo{'defaultcredits'}; + } + } + } elsif (($reqinfo{'crstype'} eq 'unofficial') || ($reqinfo{'crstype'} eq 'textbook')) { + $env{'form.coursecredits'} = $reqinfo{'defaultcredits'}; + } + my @currsec; + if (ref($reqinfo{'sections'}) eq 'HASH') { + foreach my $i (sort(keys(%{$reqinfo{'sections'}}))) { + if (ref($reqinfo{'sections'}{$i}) eq 'HASH') { + my $sec = $reqinfo{'sections'}{$i}{'inst'}; + $env{'form.secnum_'.$i} = $sec; + $env{'form.sec_'.$i} = '1'; + if (!grep(/^\Q$sec\E$/,@currsec)) { + push(@currsec,$sec); + } + $env{'form.loncapasec_'.$i} = $reqinfo{'sections'}{$i}{'loncapa'}; + } + } + } + if (ref($reqinfo{'crosslists'}) eq 'HASH') { + foreach my $i (sort(keys(%{$reqinfo{'crosslists'}}))) { + if (ref($reqinfo{'crosslists'}{$i}) eq 'HASH') { + $env{'form.crosslist_'.$i} = '1'; + $env{'form.crosslist_'.$i.'_instsec'} = $reqinfo{'crosslists'}{$i}{'instsec'}; + $env{'form.crosslist_'.$i.'_lcsec'} = $reqinfo{'crosslists'}{$i}{'loncapa'}; + if ($reqinfo{'crosslists'}{$i}{'instcode'} ne '') { + my $key = $cnum.$i; + my $crscode = { + $key => $reqinfo{'crosslists'}{$i}{'instcode'}, + }; + &extract_instcode($dom,'crosslist',$crscode,$key,$i); + } + } + } + } + if (ref($reqinfo{'personnel'}) eq 'HASH') { + my $i = 0; + foreach my $user (sort(keys(%{$reqinfo{'personnel'}}))) { + my ($uname,$udom) = split(':',$user); + if (ref($reqinfo{'personnel'}{$user}) eq 'HASH') { + if (ref($reqinfo{'personnel'}{$user}{'roles'}) eq 'ARRAY') { + foreach my $role (sort(@{$reqinfo{'personnel'}{$user}{'roles'}})) { + $env{'form.person_'.$i.'_role'} = $role; + $env{'form.person_'.$i.'_firstname'} = $reqinfo{'personnel'}{$user}{'firstname'}; + $env{'form.person_'.$i.'_lastname'} = $reqinfo{'personnel'}{$user}{'lastname'}; ; + $env{'form.person_'.$i.'_emailaddr'} = $reqinfo{'personnel'}{$user}{'emailaddr'}; + $env{'form.person_'.$i.'_uname'} = $uname; + $env{'form.person_'.$i.'_dom'} = $udom; + if (ref($reqinfo{'personnel'}{$user}{$role}) eq 'HASH') { + if (ref($reqinfo{'personnel'}{$user}{$role}{'usec'}) eq 'ARRAY') { + my @usecs = @{$reqinfo{'personnel'}{$user}{$role}{'usec'}}; + my @newsecs; + if (@usecs > 0) { + foreach my $sec (@usecs) { + if (grep(/^\Q$sec\E/,@currsec)) { + $env{'form.person_'.$i.'_sec'} = $sec; + } else { + push(@newsecs,$sec); + } + } + } + if (@newsecs > 0) { + $env{'form.person_'.$i.'_newsec'} = join(',',@newsecs); + } + } + } + $i ++; + } + } + } + } + $env{'form.persontotal'} = $i; + } + } + } + return $result; +} +sub get_request_settings { + my ($dom,$cnum,$udom,$uname) = @_; + my $requestkey = $dom.'_'.$cnum; + my ($result,%reqinfo); + if ($requestkey =~ /^($match_domain)_($match_courseid)$/) { + my %history = &Apache::lonnet::restore($requestkey,'courserequests',$udom,$uname); + my $disposition = $history{'disposition'}; + if (($disposition eq 'approval') || ($disposition eq 'pending')) { + if (ref($history{'details'}) eq 'HASH') { + %reqinfo = %{$history{'details'}}; + $result = 'ok'; + } else { + $result = 'nothash'; + } + } else { + $result = 'notqueued'; + } + } else { + $result = 'invalid'; } - return %batchhash; + return ($result,%reqinfo); } -sub retrieve_settings { - my ($dom,$request_id) = @_; - my %reqinfo = &get_request_settings($request_id,$dom); - my %stored; - $stored{'cdescr'} = &unescape($reqinfo{'description'}); - $stored{'startaccess'} = $reqinfo{'startaccess'}; - $stored{'endaccess'} = $reqinfo{'endaccess'}; - if ($stored{'endaccess'} == 0) { - $stored{'no_end_date'} = 1; - } - $stored{'startenroll'} = $reqinfo{'startenroll'}; - $stored{'endenroll'} = $reqinfo{'endenroll'}; - $stored{'crosslist'} = $reqinfo{'crosslist'}; - $stored{'clonecourse'} = $reqinfo{'clonecourse'}; - $stored{'clonedomain'} = $reqinfo{'clonedomain'}; - $stored{'sections'} = $reqinfo{'sections'}; - $stored{'personnel'} = $reqinfo{'personnel'}; +sub extract_instcode { + my ($cdom,$element,$crscode,$crskey,$counter) = @_; + my (%codes,@codetitles,%cat_titles,%cat_order); + if (&Apache::lonnet::auto_instcode_format('requests',$cdom,$crscode,\%codes, + \@codetitles,\%cat_titles, + \%cat_order) eq 'ok') { + if (ref($codes{$crskey}) eq 'HASH') { + if (@codetitles > 0) { + my $sel = $element; + if ($element eq 'crosslist') { + $sel .= '_'.$counter; + } + foreach my $title (@codetitles) { + $env{'form.'.$sel.'_'.$title} = $codes{$crskey}{$title}; + } + } + } + } + return; +} - return %stored; +sub generate_date_items { + my ($currentval,$item) = @_; + if ($currentval =~ /\d+/) { + my ($tzname,$sec,$min,$hour,$mday,$month,$year) = + &Apache::lonhtmlcommon::get_timedates($currentval); + $env{'form.'.$item.'_day'} = $mday; + $env{'form.'.$item.'_month'} = $month+1; + $env{'form.'.$item.'_year'} = $year; + } + return; } -sub get_request_settings { - my ($request_id,$dom); +sub print_textbook_form { + my ($r,$dom,$incdoms,$domdefs,$settings,$can_request) = @_; + my ($bookshash,%ordered); + my $crstype = 'textbook'; +# +# Retrieve list of textbook courses cloneable by user +# + my $numbook; + if (ref($settings) eq 'HASH') { + $bookshash = $settings->{'textbooks'}; + if (ref($bookshash) eq 'HASH') { + foreach my $item (keys(%{$bookshash})) { + my ($clonedom,$clonecrs) = split(/_/,$item); + if (ref($bookshash->{$item}) eq 'HASH') { + my ($clonedom,$clonecrs) = split(/_/,$item); + if (&Apache::loncoursequeueadmin::can_clone_course($env{'user.name'}, + $env{'user.domain'},$clonecrs,$clonedom,$crstype)) { + + my $num = $bookshash->{$item}{'order'}; + $ordered{$num} = $item; + $numbook ++; + } + } + } + } + } + +# +# Check if domain has multiple library servers +# + my ($home_server_pick,$numlib) = + &Apache::loncommon::home_server_form_item($dom,'chome', + 'default','hide'); + if ($numlib > 1) { + $home_server_pick = &mt('Home Server for Course').': '.$home_server_pick.' '; + } + +# +# Retrieve information about courses owned by user, or in which user has an active or future +# Course Coordinator role +# + my $numcurrent; + my %cloneable = &Apache::lonnet::courseiddump($dom,'.',1,'.',$env{'user.name'}.':'.$env{'user.domain'}, + undef,undef,undef,'Course'); + my %ccroles = &Apache::lonnet::get_my_roles($env{'user.name'},$env{'user.domain'},'userroles', + ['active','future'],['cc']); + foreach my $role (keys(%ccroles)) { + my ($cnum,$cdom,$rest) = split(/:/,$role,3); + unless (exists($cloneable{$cdom.'_'.$cnum})) { + my %courseinfo = &Apache::lonnet::coursedescription($cdom.'_'.$cnum,{'one_time' => 1}); + $cloneable{$cdom.'_'.$cnum} = \%courseinfo; + } + } + + my $numcurrent = scalar(keys(%cloneable)); + + my $jscript = &textbook_request_javascript($numbook,$numcurrent); + my %loaditems; + $loaditems{'onload'} = 'javascript:uncheckAllRadio();'; + $r->print(&header('Course Request',$jscript,\%loaditems)); + + if (ref($can_request) eq 'HASH') { + unless ((scalar(keys(%{$can_request})) == 1) && ($can_request->{'textbook'})) { + &Apache::lonhtmlcommon::add_breadcrumb( + { href => '/adm/requestcourse', + text => 'Pick action', + }); + } + } + &Apache::lonhtmlcommon::add_breadcrumb({text=>'Course Request'}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests')); + + &startContentScreen($r,'textbookrequests'); +# +# Show domain selector form, if required. +# + if (@{$incdoms} > 1) { + my $onchange = 'this.form.submit()'; + $r->print(' ');
+ }
+
+#
+# Course request form
+#
+
+#
+# Course Title
+#
+ $r->print(' '.
+ ''.
+ ' ');
+
+#
+# Content source selection, if more than one available
+#
+ if (keys(%cloneable) || keys(%ordered)) {
+ $r->print(''.
+ ' ');
+ }
+
+ my %accesstitles = (
+ 'start' => 'Default start access',
+ 'end' => 'Default end access',
+ );
+ my %help_item = (
+ start => 'Course_Request_Access_Start',
+ end => 'Course_Request_Access_End',
+ );
+ my $starttime = time;
+ my $endtime = time+(6*30*24*60*60); # 6 months from now, approx
+ my $startform = &Apache::lonhtmlcommon::date_setter('requestcourse','accessstart',
+ $starttime,'','','',1,'','','',1);
+ my $endform = &Apache::lonhtmlcommon::date_setter('requestcourse','accessend',
+ $endtime,'','','',1,'','','',1);
+#
+# Set default start and end dates for student access
+#
+ $r->print(''.
+ ' ');
+
+#
+# Display any custom fields for this course type
+#
+ my $fullname = &Apache::loncommon::plainname($env{'user.name'},
+ $env{'user.domain'});
+ my $postprocess = &Apache::lonnet::auto_crsreq_update($dom,undef,$crstype,'review',
+ $env{'user.name'},
+ $env{'user.domain'},$fullname);
+ if (ref($postprocess) eq 'HASH') {
+ if ($postprocess->{'reviewweb'}) {
+ $r->print($postprocess->{'reviewweb'});
+ }
+ }
+
+#
+# Submit button
+#
+ $r->print(''.
+ ''.
+ '');
+
+#
+# End request form
+#
+ $r->print(''.&mt('Create another course').' '); + } + &endContentScreen($r); + $r->print(&Apache::loncommon::end_page()); +} + +sub textbook_request_javascript { + my ($numbook,$numcurrent) = @_; + my %lt = &Apache::lonlocal::texthash( + choose => 'Please select a content option.', + textbook => 'Please select a textbook, or choose a different option.', + existing => 'Please select one of your existing courses to copy, or choose a different option.', + title => 'Please enter a course title.', + ); + return if (!$numbook && !$numcurrent); + return <<"ENDSCRIPT"; +function cloneChoice() { + if (document.requestcourse.cloning) { + var radioLength = document.requestcourse.cloning.length; + if (radioLength == undefined) { + var val = document.requestcourse.cloning.value; + if ((val == 'textbook') || (val == 'existing')) { + var elem = document.getElementById('show'+val); + if (document.requestcourse.cloning.checked) { + elem.style.display = 'block'; + } else { + uncheckRadio(val); + elem.style.display = 'none'; + } + } + } else { + for (var i=0; i
');
+}
+
+sub endContentScreen {
+ my ($r)=@_;
+ $r->print(' Internal Server ErrorThe server encountered an internal error or misconfiguration and was unable to complete your request. Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error. More information about this error may be available in the server error log. |