--- loncom/interface/lonrequestcourse.pm 2013/12/24 19:15:11 1.69 +++ loncom/interface/lonrequestcourse.pm 2014/04/09 10:50:07 1.77 @@ -1,7 +1,7 @@ # The LearningOnline Network # Request a course # -# $Id: lonrequestcourse.pm,v 1.69 2013/12/24 19:15:11 raeburn Exp $ +# $Id: lonrequestcourse.pm,v 1.77 2014/04/09 10:50:07 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -128,18 +128,63 @@ sub handler { } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['action','showdom','cnum','state','crstype','queue']); + ['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 (%states,%stored); - my ($jscript,$uname,$udom,$result,$warning,$showcredits,$instcredits); + 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); + } + } + } + } + + 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; + } + } + $states{'display'} = ['details']; $states{'view'} = ['pick_request','details','cancel','removal']; $states{'log'} = ['display']; @@ -165,7 +210,7 @@ sub handler { my @invalidcrosslist; my %trail = ( - crstype => 'Request Action', + crstype => 'Pick Action', codepick => 'Category', courseinfo => 'Description', enrollment => 'Access Dates', @@ -299,14 +344,11 @@ sub handler { my $loaditems = &onload_action($action,$state); - my (%can_request,%request_domains); - my $canreq = - &Apache::lonnet::check_can_request($dom,\%can_request,\%request_domains); if ($action eq 'new') { if ($canreq) { if ($state eq 'crstype') { &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems, - $crumb,\%request_domains); + $crumb,\@incdoms); } else { &request_administration($r,$action,$state,$page,\%states,$dom, $jscript,$loaditems,$crumb,$newinstcode, @@ -321,7 +363,7 @@ sub handler { } } elsif ($action eq 'view') { if ($state eq 'crstype') { - &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,$crumb,\%request_domains); + &print_main_menu($r,\%can_request,\%states,$dom,$jscript,$loaditems,$crumb,\@incdoms); } else { &request_administration($r,$action,$state,$page,\%states,$dom,$jscript, $loaditems,$crumb,'','','','',$showcredits); @@ -340,7 +382,7 @@ sub handler { } } elsif ($action eq 'log') { if ($state eq 'crstype') { - &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\%request_domains); + &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\@incdoms); } else { $jscript .= <{'official'}) || ($can_request->{'unofficial'}) || $can_request->{'textbook'}) { if ($can_request->{'community'}) { @@ -791,37 +833,34 @@ END $pagetitle = 'Community Requests'; $pageinfo = &mt('Request creation of a new course, or review your pending requests.'); $domaintitle = &mt('Community Domain'); - } else { + } elsif ((ref($incdoms) eq 'ARRAY') && ((@{$incdoms} > 1) || + ((@{$incdoms} == 1) && ($incdoms->[0] ne $dom)))) { $pagetitle = 'Course/Community Requests'; $pageinfo = &mt('You do not have rights to request creation of courses in this domain; please choose a different domain.'); $domaintitle = &mt('Course/Community Domain'); - } - } - my @incdoms; - if (ref($request_domains) eq 'HASH') { - 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); - } - } - } + } else { + $pagetitle = 'Course/Community Requests'; + $pageinfo = &mt('You do not have rights to request creation of courses or communities.'); + $earlyout = 1; } } $r->print(&header($pagetitle,$js.$jscript,$loaditems).$crumb. - '

'.$pageinfo.'

'. - '
'. + '

'.$pageinfo.'

'); + if ($earlyout) { + $r->print(&Apache::loncommon::end_page()); + return; + } + $r->print('
'. &Apache::lonhtmlcommon::start_pick_box(). &Apache::lonhtmlcommon::row_title($domaintitle). '
'. - &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,\@incdoms)); + &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,$incdoms)); if (!$onchange) { $r->print(' '); } unless ((ref($can_request) eq 'HASH') && (keys(%{$can_request}) > 0)) { - $r->print(&Apache::lonhtmlcommon::row_closure(1)."\n". + $r->print('
'.&Apache::lonhtmlcommon::row_closure(1)."\n". &Apache::lonhtmlcommon::end_pick_box().'
'."\n". &Apache::loncommon::end_page()); return; @@ -1468,6 +1507,15 @@ sub print_request_form { } $r->print(&print_review($dom,\@codetitles,\%cat_titles,\%cat_order,\@code_order,'','',\@disallowed,\%disallowmsg,$instcredits). ''); + my $fullname = &Apache::loncommon::plainname($env{'user.name'}, + $env{'user.domain'}); + my $postprocess = &Apache::lonnet::auto_crsreq_update($dom,$cnum,$crstype,'review',$env{'user.name'}, + $env{'user.domain'},$fullname,$env{'form.cdescr'}); + if (ref($postprocess) eq 'HASH') { + if ($postprocess->{'reviewweb'}) { + $r->print($postprocess->{'reviewweb'}); + } + } if ($crstype eq 'community') { $navtxt{'next'} = &mt('Submit community request'); } else { @@ -1488,25 +1536,8 @@ sub print_request_form { ''.&mt('Make another request').'

'); } if (&Apache::loncoursequeueadmin::author_prompt()) { - $r->print('

'.&mt('Access to authoring space').'

'. - '

'. - &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). - ''. - '

'. - ''. - ''. - ''. - ''. - ''. - ''. - ''. - '
'); + &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').'

'); } @@ -1518,7 +1549,7 @@ sub print_request_form { if ($result eq 'created') { my $role = 'au'; my $spec = "$role./$env{'form.showdom'}/"; - push(@links,&mt('Enter your authoring space with role: [_1]', + push(@links,&mt('Enter your Authoring Space with role: [_1]', ''. &Apache::lonnet::plaintext($role).'')); } @@ -1591,6 +1622,29 @@ sub print_request_form { return; } +sub print_author_prompt { + my ($r,$action,$cnum,$showdom,$crstype,$storeresult) = @_; + $r->print('

'.&mt('Access to Authoring Space').'

'. + '

'. + &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). + ''. + '

'. + ''. + ''. + ''. + ''. + ''. + ''. + ''. + '
'); +} + sub get_usertype { my ($persondom,$personname,$curr_rules,$got_rules) = @_; my ($rules,$ruleorder) = @@ -2105,6 +2159,7 @@ sub sorted_request_history { 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 { @@ -2120,7 +2175,7 @@ sub sorted_request_history { $entry = $requestkey.':'.$crstype.':'. &escape($history{'details'}{'cdescr'}); if ($action eq 'log') { - $entry .= ':'.$lastupdate.':'; + $entry .= ':'.$uniquecode.':'.$lastupdate.':'; if ($statusinfo{$key} ne '') { $entry .= $statusinfo{$key}; } elsif ($status ne '') { @@ -2333,7 +2388,7 @@ ENDJS } sub print_request_logs { - my ($r,$dom,$jscript,$loaditems,$crumb) = @_; + my ($r,$dom,$jscript,$loaditems,$crumb,$usetabs) = @_; my $title; if ($env{'form.crstype'} eq 'community') { $title = 'Community Request Logs'; @@ -2343,6 +2398,9 @@ sub print_request_logs { $title = 'Course Request Logs'; } $r->print(&header($title,$jscript,$loaditems).$crumb); + if ($usetabs) { + &startContentScreen($r,'textbooklogs'); + } my $formname = 'requestcrs'; $r->print('
'."\n". ''."\n". @@ -2387,6 +2445,28 @@ sub print_request_logs { if (($curr{'crstype'} eq 'official') || ($curr{'crstype'} eq 'any')) { $tablehdr .= ''.&mt('Institutional Code').''; } + my $showuniquecode; + my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom); + if (($curr{'status'} eq 'any') || ($curr{'status'} eq 'created')) { + if (ref($domconfig{'requestcourses'}) eq 'HASH') { + if (ref($domconfig{'requestcourses'}{'uniquecode'}) eq 'HASH') { + if ($curr{'crstype'} eq 'any') { + my @types = qw(official unofficial community textbook); + foreach my $type (@types) { + if ($domconfig{'requestcourses'}{'uniquecode'}{$type}) { + $showuniquecode = 1; + last; + } + } + } elsif ($domconfig{'requestcourses'}{'uniquecode'}{$curr{'crstype'}}) { + $showuniquecode = 1; + } + } + } + } + if ($showuniquecode) { + $tablehdr .= ''.&mt('Unique Code').''; + } if ($curr{'status'} eq 'any') { $tablehdr .= ''.&mt('Status').''; } elsif ($curr{'status'} eq 'created') { @@ -2424,7 +2504,7 @@ sub print_request_logs { my $showtime = &Apache::lonlocal::locallocaltime($item); if (ref($queue_by_date{$item}) eq 'ARRAY') { foreach my $request (sort(@{$queue_by_date{$item}})) { - my ($key,$crstype,$desc,$timestamp,$status,$instcode) = split(':',$request); + my ($key,$crstype,$desc,$uniquecode,$timestamp,$status,$instcode) = split(':',$request); my ($cdom,$cnum) = split('_',$key); my $output = &Apache::loncommon::start_data_table_row(). ''.$count.''. @@ -2450,6 +2530,13 @@ sub print_request_logs { } $output .= ''.$showinstcode.''; } + if ($showuniquecode) { + if ($status eq 'created') { + $output .= ''.$uniquecode.''; + } else { + $output .= ''.&mt('Not applicable').''; + } + } if ($curr{'status'} eq 'any') { my $statusname = &mt('Unknown status'); if (ref($statusnames) eq 'HASH') { @@ -2510,8 +2597,14 @@ ENDSCRIPT &mt('There are no records to display'). '

'); } - $r->print('
'. - &Apache::loncommon::end_page()); + if ($usetabs) { + $r->print(''); + } + $r->print(''); + if ($usetabs) { + &endContentScreen($r); + } + $r->print(&Apache::loncommon::end_page()); return; } @@ -3244,7 +3337,8 @@ sub display_navbuttons { sub print_request_outcome { my ($dom,$codetitles,$code_order,$instcredits) = @_; my ($output,$cnum,$now,$req_notifylist,$crstype,$enrollstart,$enrollend, - %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig); + %sections,%crosslistings,%personnel,@baduname,@missingdom,%domconfig, + $uniquecode); my $sectotal = $env{'form.sectotal'}; my $crosslisttotal = 0; $cnum = $env{'form.cnum'}; @@ -3252,15 +3346,17 @@ sub print_request_outcome { $output = &mt('Invalid LON-CAPA course number for the new course')."\n"; return $output; } - - %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom); + $crstype = $env{'form.crstype'}; + my %domconfig = &Apache::lonnet::get_dom('configuration',['requestcourses'],$dom); if (ref($domconfig{'requestcourses'}) eq 'HASH') { if (ref($domconfig{'requestcourses'}{'notify'}) eq 'HASH') { $req_notifylist = $domconfig{'requestcourses'}{'notify'}{'approval'}; } + if (ref($domconfig{'requestcourses'}{'uniquecode'}) eq 'HASH') { + $uniquecode = $domconfig{'requestcourses'}{'uniquecode'}{$crstype}; + } } $now = time; - $crstype = $env{'form.crstype'}; my $ccrole = 'cc'; if ($crstype eq 'community') { $ccrole = 'co'; @@ -3467,6 +3563,7 @@ sub print_request_outcome { crstype => $env{'form.crstype'}, instcode => $instcode, defaultcredits => $credits, + uniquecode => $uniquecode, clonedom => $clonedom, clonecrs => $clonecrs, datemode => $env{'form.datemode'}, @@ -3483,11 +3580,18 @@ sub print_request_outcome { accessend => $accessend, personnel => \%personnel, }; - my (@inststatuses,$storeresult,$creationresult); + my ($result,$output) = &process_request($dom,$cnum,$crstype,$now,$details,$instcode, + $req_notifylist,\@instsections,\%domconfig); + return ($result,$output); +} + +sub process_request { + my ($dom,$cnum,$crstype,$now,$details,$instcode,$req_notifylist,$instsections,$domconfig) = @_; + my (@inststatuses,$storeresult,$creationresult,$output); my $val = &Apache::loncoursequeueadmin::get_processtype('course',$env{'user.name'}, $env{'user.domain'},$env{'user.adv'}, - $dom,$crstype,\@inststatuses,\%domconfig); + $dom,$crstype,\@inststatuses,$domconfig); if ($val eq '') { if ($crstype eq 'official') { $output = &mt('You are not permitted to request creation of official courses.'); @@ -3522,8 +3626,10 @@ sub print_request_outcome { $inststatuslist = join(',',@inststatuses); } my $instseclist; - if (@instsections > 0) { - $instseclist = join(',',@instsections); + if (ref($instsections) eq 'ARRAY') { + if (@{$instsections} > 0) { + $instseclist = join(',',@{$instsections}); + } } $validationchk = &Apache::lonnet::auto_courserequest_validation($dom, @@ -3545,7 +3651,32 @@ sub print_request_outcome { } $reqhash{'disposition'} = $disposition; $reqstatus = $disposition; - my ($modified,$queued); + my ($modified,$queued,$coursedesc,%customitems); + unless ($disposition eq 'rejected') { + if (ref($details) eq 'HASH') { + $coursedesc = $details->{'cdescr'}; + } + my $fullname = &Apache::loncommon::plainname($env{'user.name'}, + $env{'user.domain'}); + my $inprocess = &Apache::lonnet::auto_crsreq_update($dom,$cnum,$crstype,'process',$env{'user.name'}, + $env{'user.domain'},$fullname,$coursedesc); + if (ref($inprocess) eq 'HASH') { + if (ref($inprocess->{'formitems'}) eq 'HASH') { + foreach my $key (keys(%{$inprocess->{'formitems'}})) { + if ($inprocess->{'formitems'}->{$key} eq 'multiple') { + if (exists($env{'form.'.$key})) { + @{$customitems{$key}} = &Apache::loncommon::get_env_multiple($env{'form.'.$key}); + } + } else { + if (exists($env{'form.'.$key})) { + $customitems{$key} = $env{'form.'.$key}; + $reqhash{'custom'}{$key} = $customitems{$key}; + } + } + } + } + } + } if ($disposition eq 'rejected') { if ($crstype eq 'community') { $output = &mt('Your community request was rejected.'); @@ -3558,7 +3689,7 @@ sub print_request_outcome { $storeresult = 'rejected'; } elsif ($disposition eq 'process') { my %domdefs = &Apache::lonnet::get_domain_defaults($dom); - my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles); + my ($logmsg,$newusermsg,$addresult,$enrollcount,$response,$keysmsg,%longroles,$code); my $type = 'Course'; if ($crstype eq 'community') { $type = 'Community'; @@ -3567,9 +3698,10 @@ sub print_request_outcome { foreach my $role (@roles) { $longroles{$role}=&Apache::lonnet::plaintext($role,$type); } - my $result = &Apache::loncoursequeueadmin::course_creation($dom,$cnum, - 'autocreate',$details,\$logmsg,\$newusermsg,\$addresult, - \$enrollcount,\$response,\$keysmsg,\%domdefs,\%longroles); + 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'; $reqstatus = 'created'; @@ -3580,6 +3712,14 @@ sub print_request_outcome { } 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 .= '
'.$role_result.'

'; $creationresult = 'created'; } else { @@ -3596,7 +3736,7 @@ sub print_request_outcome { } } else { my $requestid = $cnum.'_'.$disposition; - my $request = { + my $request = { $requestid => { timestamp => $now, crstype => $crstype, @@ -3633,7 +3773,7 @@ sub print_request_outcome { } $output .= '
'. ¬ification_information($disposition,$req_notifylist, - $cnum,$now); + $dom,$cnum,$now); } else { $reqstatus = 'domainerror'; $reqhash{'disposition'} = $disposition; @@ -3651,7 +3791,18 @@ sub print_request_outcome { } else { $output .= '

'.&mt('Your course request has been updated').'

'; } - $output .= ¬ification_information($disposition,$req_notifylist,$cnum,$now); + $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'}))) { + ¬ification_information($disposition,undef,$dom,$cnum,$now,undef,$postprocess); + } + } } if ($validationerror ne '') { $output .= '

'.&mt('An error occurred validating your request with institutional data sources: [_1].',$validationerror).'

'; @@ -3803,7 +3954,7 @@ sub update_requestors_roles { } sub notification_information { - my ($disposition,$req_notifylist,$cnum,$now) = @_; + my ($disposition,$req_notifylist,$dom,$cnum,$now,$code,$postprocess) = @_; my %emails = &Apache::loncommon::getemails(); my $address; if (($emails{'permanentemail'} ne '') || ($emails{'notification'} ne '')) { @@ -3821,9 +3972,34 @@ sub notification_information { } if ($req_notifylist) { my $fullname = &Apache::loncommon::plainname($env{'user.name'}, - $env{'user.domain'}); + $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'})",$cnum,$env{'form.cdescr'},$now,'coursereq',$sender); + &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, + 'queuedcrsreq',$sender); + } + } + } + if ($postprocess->{'queuedweb'}) { + $output .= $postprocess->{'queuedweb'}; + } } } elsif ($disposition eq 'pending') { $output .= '
'. @@ -3831,6 +4007,49 @@ sub notification_information { &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.'). '
'; + } 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('Students can automatically select your course by entering this code: [_1].',''.$code.''). + '
'. + &mt('A message has been sent to your LON-CAPA account with this information.'); + if ($address ne '') { + $output.= '
'.&mt('An e-mail has also been sent to: [_1] with this code.',$address); + } + $output .= '

'; + } + if (ref($postprocess) eq 'HASH') { + if (ref($postprocess->{'createdmsg'}) eq 'ARRAY') { + foreach my $item (@{$postprocess->{'createdmsg'}}) { + if (ref($item) eq 'HASH') { + if ($item->{'mt'} ne '') { + push(@{$addmsg},$item); + } + } + } + } + if ($postprocess->{'createdweb'}) { + $output .= $postprocess->{'createdweb'} + } + } + if (scalar(@{$addmsg}) > 0) { + my $type = 'createdcrsreq'; + if ($code) { + $type = 'uniquecode'; + } + &Apache::loncoursequeueadmin::send_selfserve_notification($recipient,$addmsg,$dom.'_'.$cnum,$env{'form.cdescr'}, + $now,$type,$sender); + } + } } else { $output .= '
'. &mt('Your request status is: [_1].',$disposition). @@ -4054,5 +4273,546 @@ sub generate_date_items { return; } +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('
'. + '
'.&mt('Domain').''. + &Apache::loncommon::select_dom_form($dom,'showdom','',1,$onchange,$incdoms). + '
'); + } + +# +# Course request form +# + +# +# Course Title +# + $r->print('
'. + '
'. + '
'. + ''.&mt('Course Information').''. + ''.&mt('Title').': '. + '
'. + $home_server_pick.'
'. + '
'); + +# +# Content source selection, if more than one available +# + if (keys(%cloneable) || keys(%ordered)) { + $r->print('
'. + '
'.&mt('Course Content').''); + if (keys(%ordered)) { + $r->print(''.(' 'x2).' '); + } + if (keys(%cloneable)) { + $r->print(''.(' 'x2).' '); + } + $r->print(''); + } else { + $r->print(''); + } + +# +# Table of cloneable textbook courses +# + if (keys(%ordered)) { + $r->print(''); + } + +# +# Table of user's current courses (owner and/or course coordinator) +# + if (keys(%cloneable)) { + my %lt = &clone_text(); + $r->print(''); + } +# +# End of content selector +# + 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('
'. + '
'.&mt('Student Access Dates').''. + &Apache::loncommon::help_open_topic($help_item{'start'}). + ' '.&mt($accesstitles{'start'}).$startform.'
'. + &Apache::loncommon::help_open_topic($help_item{'end'}). + ' '.&mt($accesstitles{'end'}).$endform.'
'); + +# +# 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('
'); + &endContentScreen($r). + $r->print(&Apache::loncommon::end_page()); + return; +} + +sub process_textbook_request { + my ($r,$dom,$action,$domdefs,$domconfig,$can_request) = @_; + my ($uniquecode,$req_notifylist); + my $crstype = 'textbook'; + if (ref($domconfig) eq 'HASH') { + if (ref($domconfig->{'requestcourses'}) eq 'HASH') { + if (ref($domconfig->{'requestcourses'}{'notify'}) eq 'HASH') { + $req_notifylist = $domconfig->{'requestcourses'}{'notify'}{'approval'}; + } + if (ref($domconfig->{'requestcourses'}{'uniquecode'}) eq 'HASH') { + $uniquecode = $domconfig->{'requestcourses'}{'uniquecode'}{$crstype}; + } + } + } + my $crstype = 'textbook'; + my $now = time; + my $reqtype = $env{'form.cloning'}; + my (@inststatuses,$storeresult,$creationresult); + my $cnum = &Apache::lonnet::generate_coursenum($dom,'Course'); + my ($clonefrom,$clonedom,$clonecrs); + if ($reqtype eq 'textbook') { + $clonefrom = $env{'form.book'}; + } elsif ($reqtype eq 'existing') { + $clonefrom = $env{'form.owned'}; + } + my ($accessstart,$accessend) = &dates_from_form('accessstart','accessend'); + if ($clonefrom) { + ($clonedom,$clonecrs) = split(/_/,$clonefrom); + if (&Apache::lonnet::homeserver($clonecrs,$clonedom) ne 'no_host') { + my $canclone = + &Apache::loncoursequeueadmin::can_clone_course($env{'user.name'}, + $env{'user.domain'},$clonecrs,$clonedom,$crstype); + unless ($canclone) { + undef($clonecrs); + undef($clonedom); + } + } else { + undef($clonecrs); + undef($clonedom); + } + } + $r->print(&header('Course Creation')); + + 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( + { href => '/adm/requestcourse', + text => "Create Course", + } + ); + &Apache::lonhtmlcommon::add_breadcrumb({text=>'Request Processed'}); + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Course Requests','Course_Requests')); + &startContentScreen($r,'textbookrequests'); + + my $details = { + owner => $env{'user.name'}, + domain => $env{'user.domain'}, + cdom => $dom, + cnum => $cnum, + coursehome => $env{'form.chome'}, + cdescr => $env{'form.cdescr'}, + crstype => $crstype, + uniquecode => $uniquecode, + clonedom => $clonedom, + clonecrs => $clonecrs, + accessstart => $accessstart, + accessend => $accessend, + personnel => {}, + }; + if ($reqtype eq 'existing') { + $details->{datemode} = $env{'form.datemode'}; + $details->{dateshift} = $env{'form.dateshift'}; + } + my ($result,$output) = &process_request($dom,$cnum,$crstype,$now,$details,'',$req_notifylist,[],$domconfig); + $r->print($output); + if (&Apache::loncoursequeueadmin::author_prompt()) { + &print_author_prompt($r,$action,$cnum,$dom,$crstype,$result); + } elsif ($result eq 'created') { + $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 0) { + uncheckRadio('textbook'); + } + if (numcurrent > 0) { + uncheckRadio('existing'); + } + return; +} + +function validTextbookReq() { + if (document.requestcourse.cloning) { + var cloneChoice = 0; + var radioLength = document.requestcourse.cloning.length; + if (radioLength == undefined) { + if (document.requestcourse.cloning.checked == false) { + alert("$lt{'choose'}"); + return false; + } else { + cloneChoice = document.requestcourse.cloning.value; + } + } else { + for (var i=0; iprint("\n".''."\n"); + $r->print('
'); +} + +sub endContentScreen { + my ($r)=@_; + $r->print('
'); +} + 1;