--- loncom/interface/lonrequestcourse.pm 2010/03/08 13:42:18 1.46 +++ loncom/interface/lonrequestcourse.pm 2010/03/31 18:58:34 1.51 @@ -1,7 +1,7 @@ # The LearningOnline Network # Request a course # -# $Id: lonrequestcourse.pm,v 1.46 2010/03/08 13:42:18 wenzelju Exp $ +# $Id: lonrequestcourse.pm,v 1.51 2010/03/31 18:58:34 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -128,7 +128,7 @@ sub handler { } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['action','showdom','cnum','state','crstype']); + ['action','showdom','cnum','state','crstype','queue']); &Apache::lonhtmlcommon::clear_breadcrumbs(); my $dom = &get_course_dom(); my $action = $env{'form.action'}; @@ -138,7 +138,7 @@ sub handler { $states{'display'} = ['details']; $states{'view'} = ['pick_request','details','cancel','removal']; - $states{'log'} = ['filter','display']; + $states{'log'} = ['display']; $states{'new'} = ['courseinfo','enrollment','personnel','review','process']; if (($action eq 'new') && ($env{'form.crstype'} eq 'official')) { @@ -166,6 +166,7 @@ sub handler { details => 'Request Details', cancel => 'Cancel Request', removal => 'Outcome', + display => 'Request Logs', ); if (($env{'form.crstype'} eq 'official') && (&Apache::lonnet::auto_run('',$dom))) { @@ -178,7 +179,8 @@ sub handler { if (($dom eq $env{'request.role.domain'}) && (&Apache::lonnet::allowed('ccc',$dom))) { if ($env{'form.cnum'} ne '') { my $cnum = $env{'form.cnum'}; - my $reqkey = $cnum.'_approval'; + my $queue = $env{'form.queue'}; + my $reqkey = $cnum.'_'.$queue; my $namespace = 'courserequestqueue'; my $domconfig = &Apache::lonnet::get_domainconfiguser($dom); my %queued = @@ -316,7 +318,7 @@ sub handler { } elsif ($action eq 'display') { if ($warning ne '') { my $args = { only_body => 1 }; - $r->print(&header('Course/Community Requests','','',$args).$crumb. + $r->print(&header('Course/Community Requests','','' ,'',$args).$crumb. '<h3>'.&mt('Course/Community Request Details').'</h3>'. '<div class="LC_warning">'.$warning.'</div>'. &close_popup_form()); @@ -325,7 +327,24 @@ sub handler { $loaditems,$crumb,'','','','','',$uname,$udom); } } elsif ($action eq 'log') { - &print_request_logs($jscript,$loaditems,$crumb); + if ($state eq 'crstype') { + &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\%request_domains); + } else { + $jscript .= <<ENDJS; + +function backPage(formname,prevstate) { + formname.state.value = prevstate; + formname.submit(); +} + +function setPage(formname) { + formname.page.value = '1'; + return; +} + +ENDJS + &print_request_logs($r,$dom,$jscript,$loaditems,$crumb); + } } else { &print_main_menu($r,\%can_request,\%states,$dom,$jscript,'',$crumb,\%request_domains); } @@ -681,7 +700,7 @@ END official => 'You are not permitted to request creation of an official course in this domain.', unofficial => 'You are not permitted to request creation of an unofficial course in this domain.', community => 'You are not permitted to request creation of a community this domain.', - all => 'You must choose a specific course type when making a new course request.\\nAll types is not allowed.', + all => 'You must choose a specific course type when making a new course request.\\n\"All types\" is not allowed.', ); $js .= <<END; if (crschoice == 'official') { @@ -894,7 +913,7 @@ END $title = &mt('Pending course/community requests'); } $r->print('<h3>'.$title.'</h3><div>'."\n".$form."\n". - &print_request_status($dom).'</form></div>'); + &print_request_status($dom,$action).'</form></div>'); } elsif ($state eq 'details') { my (@codetitles,%cat_titles,%cat_order,@code_order,$instcode,$code_chk); my $origcnum = $env{'form.cnum'}; @@ -1016,8 +1035,6 @@ END &print_review($dom,\@codetitles,\%cat_titles,\%cat_order, \@code_order,$uname,$udom)."\n".'</div>'. &close_popup_form()); - } elsif ($action eq 'log') { - $r->print(&coursereq_log('View request log',$jscript,$loaditems).$crumb); } $r->print(&Apache::loncommon::end_page()); return; @@ -1364,7 +1381,11 @@ sub print_request_form { if ($env{'form.origcnum'} =~ /^($match_courseid)$/) { $cnum = $env{'form.origcnum'}; } else { - $cnum = &Apache::lonnet::generate_coursenum($dom); + my $gentype = 'Course'; + if ($crstype eq 'community') { + $gentype = 'Community'; + } + $cnum = &Apache::lonnet::generate_coursenum($dom,$gentype); } &Apache::lonnet::auto_possible_instcodes($dom,\@codetitles,\%cat_titles, \%cat_order,\@code_order); @@ -1840,51 +1861,93 @@ sub current_lc_sections { return @currsecs; } -sub print_request_status { - my ($dom) = @_; +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 ($output,$formname,%queue_by_date); + my %queue_by_date; my ($types,$typenames) = &Apache::loncommon::course_types(); foreach my $key (keys(%statusinfo)) { - if (($statusinfo{$key} eq 'approval') || ($statusinfo{$key} eq 'pending')) { - (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 = $history{'reqtime'}; - my $crstype = $history{'crstype'}; - my $disposition = $history{'disposition'}; + 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 $reqtime = $history{'reqtime'}; + my $lastupdate = $history{'timestamp'}; + my $crstype = $history{'crstype'}; + my $disposition = $history{'disposition'}; + my $status = $history{'status'}; + if ($action eq 'view') { next if ((exists($history{'status'})) && ($history{'status'} eq 'created')); - next unless (($env{'form.crstype'} eq 'any') || - ($env{'form.crstype'} eq $crstype)); + } 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 ($crstype eq 'official') { - $entry .= ':'.&escape($history{'details'}{'instcode'}); + } + if (ref($history{'details'}) eq 'HASH') { + $entry = $requestkey.':'.$crstype.':'. + &escape($history{'details'}{'cdescr'}); + if ($action eq 'log') { + $entry .= ':'.$lastupdate.':'; + if ($statusinfo{$key} ne '') { + $entry .= $statusinfo{$key}; + } elsif ($status ne '') { + $entry .= $status; + } else { + $entry .= $disposition; } } - if ($entry ne '') { - if (exists($queue_by_date{$timestamp})) { - if (ref($queue_by_date{$timestamp}) eq 'ARRAY') { - push(@{$queue_by_date{$timestamp}},$entry); - } - } else { - @{$queue_by_date{$timestamp}} = ($entry); + if ($crstype eq 'official') { + $entry .= ':'.&escape($history{'details'}{'instcode'}); + } + } + if ($entry ne '') { + if (exists($queue_by_date{$reqtime})) { + if (ref($queue_by_date{$reqtime}) eq 'ARRAY') { + push(@{$queue_by_date{$reqtime}},$entry); } + } else { + @{$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 = '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n". + my $formname = 'requestcrs'; + my ($types,$typenames) = &Apache::loncommon::course_types(); + my $output = '<input type="hidden" name="action" value="'.$env{'form.action'}.'" />'."\n". '<input type="hidden" name="state" value="'.$env{'form.state'}.'" />'."\n". '<input type="hidden" name="crstype" value="'.$env{'form.crstype'}.'" />'."\n". @@ -2064,10 +2127,291 @@ ENDJS } sub print_request_logs { - my ($jscript,$loaditems,$crumb) = @_; + my ($r,$dom,$jscript,$loaditems,$crumb) = @_; + my $title; + if ($env{'form.crstype'} eq 'community') { + $title = 'Community Request Logs'; + } elsif ($env{'form.crstype'} eq 'any') { + $title = 'Course/Community Request Logs'; + } else { + $title = 'Course Request Logs'; + } + $r->print(&header($title,$jscript,$loaditems).$crumb); + my $formname = 'requestcrs'; + $r->print('<form action="/adm/requestcourse" method="post" name="'.$formname.'" onsubmit="javascript:setPage(this);">'."\n". + '<input type="hidden" name="action" value="log" />'."\n". + '<input type="hidden" name="state" value="display" />'."\n"); + # set defaults + my $now = time(); + my $defstart = $now - (7*24*3600); #7 days ago + my %defaults = ( + page => '1', + show => '10', + crstype => 'any', + status => 'any', + requested_before_date => $now, + requested_after_date => $defstart, + ); + my ($types,$typenames) = &Apache::loncommon::course_types(); + my $more_records = 0; + my %curr; + foreach my $item ('show','page','crstype','status') { + $curr{$item} = $env{'form.'.$item}; + } + $curr{'requested_after_date'} = &Apache::lonhtmlcommon::get_date_from_form('requested_after_date'); + $curr{'requested_before_date'} = &Apache::lonhtmlcommon::get_date_from_form('requested_before_date'); + foreach my $key (keys(%defaults)) { + if ($curr{$key} eq '') { + $curr{$key} = $defaults{$key}; + } + } + my ($statuses,$statusnames) = &reqstatus_names($curr{'crstype'}); + $r->print('<input type="hidden" name="page" value="'.$curr{'page'}.'" />'. + &requestlog_display_filter($formname,\%curr)); + my %queue_by_date = &sorted_request_history($dom,$env{'form.action'},\%curr); + my @sortedtimes = sort {$a <=> $b} (keys(%queue_by_date)); + my $showntablehdr = 0; + my $tablehdr = &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + '<th> </th><th>'.&mt('Request Date').'</th>'. + '<th>'.&mt('Description').'</th>'; + if ($curr{'crstype'} eq 'any') { + $tablehdr .= '<th>'.&mt('Course Type').'</th>'; + } + if (($curr{'crstype'} eq 'official') || ($curr{'crstype'} eq 'any')) { + $tablehdr .= '<th>'.&mt('Institutional Code').'</th>'; + } + if ($curr{'status'} eq 'any') { + $tablehdr .= '<th>'.&mt('Status').'</th>'; + } elsif ($curr{'status'} eq 'created') { + $tablehdr .= '<th>'.&mt('Creation Date').'</th>'; + } elsif ($curr{'status'} eq 'cancelled') { + $tablehdr .= '<th>'.&mt('Cancellation Date').'</th>'; + } elsif ($curr{'status'} eq 'rejected') { + $tablehdr .= '<th>'.&mt('Rejection Date').'</th>'; + } + $tablehdr .= &Apache::loncommon::end_data_table_header_row(); + my ($minshown,$maxshown); + $minshown = 1; + my $count = 0; + if ($curr{'show'} ne &mt('all')) { + $maxshown = $curr{'page'} * $curr{'show'}; + if ($curr{'page'} > 1) { + $minshown = 1 + ($curr{'page'} - 1) * $curr{'show'}; + } + } + my $norecords; + if (@sortedtimes > 0) { + foreach my $item (@sortedtimes) { + if ($curr{'show'} ne &mt('all')) { + if ($count >= $curr{'page'} * $curr{'show'}) { + $more_records = 1; + last; + } + } + $count ++; + next if ($count < $minshown); + if (!$showntablehdr) { + $r->print($tablehdr); + $showntablehdr = 1; + } + 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 ($cdom,$cnum) = split('_',$key); + my $output = &Apache::loncommon::start_data_table_row(). + '<td>'.$count.'</td>'. + '<td>'.$showtime.'</td>'. + '<td>'.&unescape($desc).'</td>'; + if ($curr{'crstype'} eq 'any') { + my $typename; + if (ref($typenames) eq 'HASH') { + $typename = &mt($typenames->{$crstype}); + } + if ($typename eq '') { + $typename = &mt('Unknown type'); + } + $output .= '<td>'.$typename.'</td>'; + } + if (($curr{'crstype'} eq 'any') || + ($curr{'crstype'} eq 'official')) { + my $showinstcode; + if ($crstype eq 'official') { + $showinstcode = &unescape($instcode); + } else { + $showinstcode = &mt('Not applicable'); + } + $output .= '<td>'.$showinstcode.'</td>'; + } + if ($curr{'status'} eq 'any') { + my $statusname = &mt('Unknown status'); + if (ref($statusnames) eq 'HASH') { + if ($statusnames->{$status} ne '') { + $statusname = $statusnames->{$status}; + } + } + if (($status eq 'created') || ($status eq 'cancelled') || + ($status eq 'rejected')) { + $statusname .= ' '.&Apache::lonlocal::locallocaltime($timestamp); + } + $output .= '<td>'.$statusname.'</td>'; + } elsif (($status eq 'created') || ($status eq 'cancelled') || + ($status eq 'rejected')) { + $output .= '<td>'.&Apache::lonlocal::locallocaltime($timestamp).'</td>'; + } + $output .= &Apache::loncommon::end_data_table_row(); + $r->print($output); + } + } + } + if ($showntablehdr) { + $r->print(&Apache::loncommon::end_data_table()); + if (($curr{'page'} > 1) || ($more_records)) { + $r->print('<table><tr>'); + if ($curr{'page'} > 1) { + $r->print('<td><a href="javascript:chgPage('."'previous'".');">'.&mt('Previous [_1] changes',$curr{'show'}).'</a></td>'); + } + if ($more_records) { + $r->print('<td><a href="javascript:chgPage('."'next'".');">'.&mt('Next [_1] changes',$curr{'show'}).'</a></td>'); + } + $r->print('</tr></table>'); + $r->print(<<"ENDSCRIPT"); +<script type="text/javascript"> +// <![CDATA[ +function chgPage(caller) { + if (caller == 'previous') { + document.$formname.page.value --; + } + if (caller == 'next') { + document.$formname.page.value ++; + } + document.$formname.submit(); + return; +} +// ]]> +</script> +ENDSCRIPT + } + } else { + $norecords = 1; + } + } else { + $norecords = 1; + } + if ($norecords) { + $r->print('<p class="LC_info">'. + &mt('There are no records to display'). + '</p>'); + } + $r->print('</form>'. + &Apache::loncommon::end_page()); return; } +sub reqstatus_names { + my ($crstype) = @_; + my @statuses = qw(created approval pending rejected cancelled); + my %statusnames = + &Apache::lonlocal::texthash ( + created => 'Created', + approval => 'Queued pending approval', + pending => 'Queued pending validation', + rejected => 'Request rejected', + cancelled => 'Request cancelled', + ); + if (($crstype eq 'official') || ($crstype eq 'unofficial')) { + $statusnames{'created'} = &mt('Course created'); + } elsif ($crstype eq 'community') { + $statusnames{'created'} = &mt('Community created'); + } + return (\@statuses,\%statusnames); +} + +sub requestlog_display_filter { + my ($formname,$curr) = @_; + my $nolink = 1; + my $output = '<table><tr><td valign="top">'. + '<span class="LC_nobreak"><b>'.&mt('Records/page:').'</b></span><br />'. + &Apache::lonmeta::selectbox('show',$curr->{'show'},undef, + (&mt('all'),5,10,20,50,100,1000,10000)). + '</td><td> </td>'; + 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 .= '<td valign="top"><b>'.&mt('Window during which course/community was requested:').'</b><br />'. + '<table><tr><td>'.&mt('After:'). + '</td><td>'.$startform.'</td></tr>'. + '<tr><td>'.&mt('Before:').'</td>'. + '<td>'.$endform.'</td></tr></table>'. + '</td>'. + '<td> </td>'; + my ($types,$typenames) = &Apache::loncommon::course_types(); + if (ref($types) eq 'ARRAY') { + if (@{$types} > 1) { + $output .= '<td valign="top"><b>'. + &mt('Course Type:').'</b><br /><select name="crstype">'; + my $selstr = ''; + if ($curr->{'crstype'} eq 'any') { + $selstr = ' selected="selected"'; + } + $output .= '<option value="any"'.$selstr.'>'.&mt('All types').'</option>'."\n"; + foreach my $crstype (@{$types}) { + my $selstr = ''; + if ($curr->{'crstype'} eq $crstype) { + $selstr = ' selected="selected"'; + } + my $typename = $crstype; + if (ref($typenames) eq 'HASH') { + if ($typenames->{$crstype} ne '') { + $typename = $typenames->{$crstype}; + } + } + $output .= '<option value="'.$crstype.'"'.$selstr.'>'.$typename.'</option>'."\n"; + } + $output .= '</select></td>'; + } + } + my ($statuses,$statusnames) = &reqstatus_names($curr->{'crstype'}); + if (ref($statuses) eq 'ARRAY') { + if (@{$statuses} > 1) { + $output .= '<td valign="top"><b>'. + &mt('Request Status:').'</b><br /><select name="status">'; + my $selstr = ''; + if ($curr->{'status'} eq 'any') { + $selstr = ' selected="selected"'; + } + $output .= '<option value="any"'.$selstr.'>'.&mt('Any status').'</option>'."\n"; + foreach my $status (@{$statuses}) { + my $selstr = ''; + if ($curr->{'status'} eq $status) { + $selstr = ' selected="selected"'; + } + my $statusname = $status; + if (ref($statusnames) eq 'HASH') { + if ($statusnames->{$status} ne '') { + $statusname = $statusnames->{$status}; + } + } + $output .= '<option value="'.$status.'"'.$selstr.'>'.$statusname.'</option>'."\n"; + } + $output .= '</select></td>'; + } + } + $output .= '</tr></table>'; + + # Update Display button + $output .= '<p>'. + '<input type="submit" value="'.&mt('Update Display').'" />'. + '</p><hr />'; + return $output; +} + sub print_review { my ($dom,$codetitles,$cat_titles,$cat_order,$code_order,$uname,$udom, $disallowed,$disallowmsg) = @_; @@ -2424,7 +2768,7 @@ ENDJS '<label><input type="radio" name="cloning" value="1" '. 'onclick="javascript:toggleCloning()" />'. &mt('Yes').(' 'x2).'</label><label>'. - '<input type="radio" name="cloning" value="0" '. + '<input type="radio" name="cloning" value="0" checked="checked" '. 'onclick="javascript:toggleCloning()" />'.&mt('No').'</label>'. '</h3>'. &Apache::lonhtmlcommon::row_closure(1). @@ -2954,6 +3298,9 @@ sub print_request_outcome { description => $env{'form.cdescr'}, }, }; + 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'});