version 1.452, 2010/12/02 15:40:02
|
version 1.498, 2014/01/19 21:12:35
|
Line 164 If true, the resource's folder will not
|
Line 164 If true, the resource's folder will not
|
it. Default is false. True implies printCloseAll is false, since you |
it. Default is false. True implies printCloseAll is false, since you |
can't close or open folders when this is on anyhow. |
can't close or open folders when this is on anyhow. |
|
|
|
=item * B<map_no_edit_link>: |
|
|
|
If true, the title of the folder or page will not be followed by an |
|
icon/link to direct editing of a folder or composite page, originally |
|
added via the Course Editor. |
|
|
=back |
=back |
|
|
=item * B<Apache::lonnavmaps::communication_status>: |
=item * B<Apache::lonnavmaps::communication_status>: |
Line 464 returns 4
|
Line 470 returns 4
|
|
|
=item add_linkitem() |
=item add_linkitem() |
|
|
=item show_linkitems() |
=item show_linkitems_toolbar() |
|
|
=back |
=back |
|
|
Line 478 use Apache::loncommon();
|
Line 484 use Apache::loncommon();
|
use Apache::lonenc(); |
use Apache::lonenc(); |
use Apache::lonlocal; |
use Apache::lonlocal; |
use Apache::lonnet; |
use Apache::lonnet; |
|
use Apache::lonmap; |
|
|
use POSIX qw (floor strftime); |
use POSIX qw (floor strftime); |
use Time::HiRes qw( gettimeofday tv_interval ); |
use Time::HiRes qw( gettimeofday tv_interval ); |
use LONCAPA; |
use LONCAPA; |
use DateTime(); |
use DateTime(); |
|
use HTML::Entities; |
|
|
|
# For debugging |
|
|
|
use Data::Dumper; |
|
|
|
|
# symbolic constants |
# symbolic constants |
sub SYMB { return 1; } |
sub SYMB { return 1; } |
Line 509 my %statusIconMap =
|
Line 522 my %statusIconMap =
|
my %iconAltTags = #texthash does not work here |
my %iconAltTags = #texthash does not work here |
( 'navmap.correct.gif' => 'Correct', |
( 'navmap.correct.gif' => 'Correct', |
'navmap.wrong.gif' => 'Incorrect', |
'navmap.wrong.gif' => 'Incorrect', |
'navmap.open.gif' => 'Open', |
'navmap.open.gif' => 'Is Open', |
'navmap.partial.gif' => 'Partially Correct', |
'navmap.partial.gif' => 'Partially Correct', |
'navmap.ellipsis.gif' => 'Attempted', |
'navmap.ellipsis.gif' => 'Attempted', |
); |
); |
Line 536 my %colormap =
|
Line 549 my %colormap =
|
# is not yet done and due in less than 24 hours |
# is not yet done and due in less than 24 hours |
my $hurryUpColor = "#FF0000"; |
my $hurryUpColor = "#FF0000"; |
|
|
my $future_slots_checked = 0; |
|
my $future_slots = 0; |
|
|
|
sub addToFilter { |
sub addToFilter { |
my $hashIn = shift; |
my $hashIn = shift; |
my $addition = shift; |
my $addition = shift; |
Line 609 sub getDescription {
|
Line 619 sub getDescription {
|
return &mt("Having technical difficulties; please check status later"); |
return &mt("Having technical difficulties; please check status later"); |
} |
} |
if ($status == $res->NOTHING_SET) { |
if ($status == $res->NOTHING_SET) { |
return &mt("Not currently assigned."); |
return &Apache::lonhtmlcommon::direct_parm_link(&mt('Not currently assigned'),$res->symb(),'opendate',$part); |
} |
} |
if ($status == $res->OPEN_LATER) { |
if ($status == $res->OPEN_LATER) { |
return &mt("Open ") .timeToHumanString($open,'start'); |
return &mt("Open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($open,'start'),$res->symb(),'opendate',$part)); |
} |
} |
if ($res->simpleStatus($part) == $res->OPEN) { |
if ($res->simpleStatus($part) == $res->OPEN) { |
unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { |
unless (&Apache::lonnet::allowed('mgr',$env{'request.course.id'})) { |
Line 629 sub getDescription {
|
Line 639 sub getDescription {
|
return &mt('Reserved - next open [_1]', |
return &mt('Reserved - next open [_1]', |
timeToHumanString($slot_time,'start')); |
timeToHumanString($slot_time,'start')); |
} elsif ($slot_status == $res->RESERVABLE) { |
} elsif ($slot_status == $res->RESERVABLE) { |
return &mt('Reservable ending [_1]', |
return &mt('Reservable, reservations close [_1]', |
timeToHumanString($slot_time,'end')); |
timeToHumanString($slot_time,'end')); |
} elsif ($slot_status == $res->RESERVABLE_LATER) { |
} elsif ($slot_status == $res->RESERVABLE_LATER) { |
return &mt('Reservable starting [_1]', |
return &mt('Reservable, reservations open [_1]', |
timeToHumanString($slot_time,'start')); |
timeToHumanString($slot_time,'start')); |
} elsif ($slot_status == $res->NOT_IN_A_SLOT) { |
} elsif ($slot_status == $res->NOT_IN_A_SLOT) { |
return &mt('Reserve a time/place to work'); |
return &mt('Reserve a time/place to work'); |
Line 646 sub getDescription {
|
Line 656 sub getDescription {
|
if ($status == $res->OPEN) { |
if ($status == $res->OPEN) { |
if ($due) { |
if ($due) { |
if ($res->is_practice()) { |
if ($res->is_practice()) { |
return &mt("Closes ")." " .timeToHumanString($due,'start'); |
return &mt("Closes [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'duedate',$part)); |
} else { |
} else { |
return &mt("Due")." " .timeToHumanString($due,'end'); |
return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)); |
} |
} |
} else { |
} else { |
return &mt("Open, no due date"); |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Open, no due date"),$res->symb(),'duedate',$part); |
} |
} |
} |
} |
if ($status == $res->PAST_DUE_ANSWER_LATER) { |
if ($status == $res->PAST_DUE_ANSWER_LATER) { |
return &mt("Answer open")." " .timeToHumanString($answer,'start'); |
return &mt("Answer open [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($answer,'start'),$res->symb(),'answerdate',$part)); |
} |
} |
if ($status == $res->PAST_DUE_NO_ANSWER) { |
if ($status == $res->PAST_DUE_NO_ANSWER) { |
if ($res->is_practice()) { |
if ($res->is_practice()) { |
return &mt("Closed")." " . timeToHumanString($due,'start'); |
return &mt("Closed [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'start'),$res->symb(),'answerdate,duedate',$part)); |
} else { |
} else { |
return &mt("Was due")." " . timeToHumanString($due,'end'); |
return &mt("Was due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'answerdate,duedate',$part)); |
} |
} |
} |
} |
if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) |
if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) |
&& $res->handgrade($part) ne 'yes') { |
&& $res->handgrade($part) ne 'yes') { |
return &mt("Answer available"); |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("Answer available"),$res->symb(),'answerdate,duedate',$part); |
} |
} |
if ($status == $res->EXCUSED) { |
if ($status == $res->EXCUSED) { |
return &mt("Excused by instructor"); |
return &mt("Excused by instructor"); |
Line 688 sub getDescription {
|
Line 698 sub getDescription {
|
my $maxtries = $res->maxtries($part); |
my $maxtries = $res->maxtries($part); |
my $triesString = ""; |
my $triesString = ""; |
if ($tries && $maxtries) { |
if ($tries && $maxtries) { |
$triesString = '<font size="-1"><i>('.&mt('[_1] of [quant,_2,try,tries] used',$tries,$maxtries).')</i></font>'; |
$triesString = '<span class="LC_fontsize_medium"><i>('.&mt('[_1] of [quant,_2,try,tries] used',$tries,$maxtries).')</i></span>'; |
if ($maxtries > 1 && $maxtries - $tries == 1) { |
if ($maxtries > 1 && $maxtries - $tries == 1) { |
$triesString = "<b>$triesString</b>"; |
$triesString = "<b>$triesString</b>"; |
} |
} |
} |
} |
if ($due) { |
if ($due) { |
return &mt("Due")." " . timeToHumanString($due,'end') . |
return &mt("Due [_1]",&Apache::lonhtmlcommon::direct_parm_link(&timeToHumanString($due,'end'),$res->symb(),'duedate',$part)) . |
" $triesString"; |
" $triesString"; |
} else { |
} else { |
return &mt("No due date")." $triesString"; |
return &Apache::lonhtmlcommon::direct_parm_link(&mt("No due date"),$res->symb(),'duedate',$part)." $triesString"; |
} |
} |
} |
} |
if ($status == $res->ANSWER_SUBMITTED) { |
if ($status == $res->ANSWER_SUBMITTED) { |
Line 779 sub timeToHumanString {
|
Line 789 sub timeToHumanString {
|
|
|
# Less than an hour |
# Less than an hour |
if ( $delta < $hour ) { |
if ( $delta < $hour ) { |
# If so, use minutes |
# If so, use minutes; or minutes, seconds (if format requires) |
my $minutes = floor($delta / 60); |
my $minutes = floor($delta / 60); |
|
if (($format ne '') && ($format =~ /\%(T|S)/)) { |
|
my $display; |
|
if ($minutes == 1) { |
|
$display = "${prefix}1 minute"; |
|
} else { |
|
$display = "$prefix$minutes minutes"; |
|
} |
|
my $seconds = $delta % $minute; |
|
if ($seconds == 0) { |
|
$display .= $tense; |
|
} elsif ($seconds == 1) { |
|
$display .= ", 1 second$tense"; |
|
} else { |
|
$display .= ", $seconds seconds$tense"; |
|
} |
|
return $display; |
|
} |
if ($minutes == 1) { return "${prefix}1 minute$tense"; } |
if ($minutes == 1) { return "${prefix}1 minute$tense"; } |
return "$prefix$minutes minutes$tense"; |
return "$prefix$minutes minutes$tense"; |
} |
} |
|
|
# Is it less than 24 hours away? If so, |
# Is it less than 24 hours away? If so, |
# display hours + minutes |
# display hours + minutes, (and + seconds, if format specified it) |
if ( $delta < $hour * 24) { |
if ( $delta < $hour * 24) { |
my $hours = floor($delta / $hour); |
my $hours = floor($delta / $hour); |
my $minutes = floor(($delta % $hour) / $minute); |
my $minutes = floor(($delta % $hour) / $minute); |
Line 801 sub timeToHumanString {
|
Line 828 sub timeToHumanString {
|
if ($minutes == 0) { |
if ($minutes == 0) { |
$minuteString = ""; |
$minuteString = ""; |
} |
} |
|
if (($format ne '') && ($format =~ /\%(T|S)/)) { |
|
my $display = "$prefix$hourString$minuteString"; |
|
my $seconds = $delta-(($hours * $hour)+($minutes * $minute)); |
|
if ($seconds == 0) { |
|
$display .= $tense; |
|
} elsif ($seconds == 1) { |
|
$display .= ", 1 second$tense"; |
|
} else { |
|
$display .= ", $seconds seconds$tense"; |
|
} |
|
return $display; |
|
} |
return "$prefix$hourString$minuteString$tense"; |
return "$prefix$hourString$minuteString$tense"; |
} |
} |
|
|
|
# Date/time is more than 24 hours away |
|
|
my $dt = DateTime->from_epoch(epoch => $time) |
my $dt = DateTime->from_epoch(epoch => $time) |
->set_time_zone(&Apache::lonlocal::gettimezone()); |
->set_time_zone(&Apache::lonlocal::gettimezone()); |
|
|
# If there's a caller supplied format, use it. |
# If there's a caller supplied format, use it, unless it only displays |
|
# H:M:S or H:M. |
|
|
if ($format ne '') { |
if (($format ne '') && ($format ne '%T') && ($format ne '%R')) { |
my $timeStr = $dt->strftime($format); |
my $timeStr = $dt->strftime($format); |
return $timeStr.' ('.$dt->time_zone_short_name().')'; |
return $timeStr.' ('.$dt->time_zone_short_name().')'; |
} |
} |
Line 861 sub part_status_summary { return 4; }
|
Line 903 sub part_status_summary { return 4; }
|
sub render_resource { |
sub render_resource { |
my ($resource, $part, $params) = @_; |
my ($resource, $part, $params) = @_; |
|
|
|
my $editmapLink; |
my $nonLinkedText = ''; # stuff after resource title not in link |
my $nonLinkedText = ''; # stuff after resource title not in link |
|
|
my $link = $params->{"resourceLink"}; |
my $link = $params->{"resourceLink"}; |
Line 942 sub render_resource {
|
Line 985 sub render_resource {
|
$linkopen = ""; |
$linkopen = ""; |
$linkclose = ""; |
$linkclose = ""; |
} |
} |
|
if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) && |
|
($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) { |
|
if (!$params->{'map_no_edit_link'}) { |
|
my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png'; |
|
$editmapLink=' '. |
|
'<a href="/adm/coursedocs?command=directnav&symb='.&escape($resource->symb()).'">'. |
|
'<img src="'.$icon.'" alt="'.&mt('Edit Content').'" title="'.&mt('Edit Content').'" />'. |
|
'</a>'; |
|
} |
|
} |
} |
} |
|
|
if ($resource->randomout()) { |
if ($resource->randomout()) { |
$nonLinkedText .= ' <i>('.&mt('hidden').')</i> '; |
$nonLinkedText .= ' <span class="LC_warning">('.&mt('hidden').')</span> '; |
} |
} |
if (!$resource->condval()) { |
if (!$resource->condval()) { |
$nonLinkedText .= ' <i>('.&mt('conditionally hidden').')</i> '; |
$nonLinkedText .= ' <span class="LC_info">('.&mt('conditionally hidden').')</span> '; |
} |
} |
if (($resource->is_practice()) && ($resource->is_raw_problem())) { |
if (($resource->is_practice()) && ($resource->is_raw_problem())) { |
$nonLinkedText .=' <font color="green"><b>'.&mt('not graded').'</b></font>'; |
$nonLinkedText .=' <span class="LC_info"><b>'.&mt('not graded').'</b></span>'; |
} |
} |
|
|
# We're done preparing and finally ready to start the rendering |
# We're done preparing and finally ready to start the rendering |
Line 975 sub render_resource {
|
Line 1028 sub render_resource {
|
# Is this the current resource? |
# Is this the current resource? |
if (!$params->{'displayedHereMarker'} && |
if (!$params->{'displayedHereMarker'} && |
$resource->symb() eq $params->{'here'} ) { |
$resource->symb() eq $params->{'here'} ) { |
$curMarkerBegin = '<em>'; |
unless ($resource->is_map()) { |
$curMarkerEnd = '</em>'; |
$curMarkerBegin = '<span class="LC_current_nav_location">'; |
|
$curMarkerEnd = '</span>'; |
|
} |
$params->{'displayedHereMarker'} = 1; |
$params->{'displayedHereMarker'} = 1; |
} |
} |
|
|
Line 993 sub render_resource {
|
Line 1048 sub render_resource {
|
} |
} |
|
|
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { |
if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { |
$result .= "$curMarkerBegin<a href=\"$link\">$title$partLabel</a>$curMarkerEnd$nonLinkedText</td>"; |
$result .= "$curMarkerBegin<a href=\"$link\">$title$partLabel</a>$curMarkerEnd$editmapLink$nonLinkedText</td>"; |
} else { |
} else { |
$result .= "$curMarkerBegin$linkopen$title$partLabel</a>$curMarkerEnd$nonLinkedText</td>"; |
$result .= "$curMarkerBegin$linkopen$title$partLabel</a>$curMarkerEnd$editmapLink$nonLinkedText</td>"; |
} |
} |
|
|
return $result; |
return $result; |
Line 1009 sub render_communication_status {
|
Line 1064 sub render_communication_status {
|
my $linkopen = "<a href=\"$link\">"; |
my $linkopen = "<a href=\"$link\">"; |
my $linkclose = "</a>"; |
my $linkclose = "</a>"; |
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); |
|
|
if ($resource->hasDiscussion()) { |
if ($resource->hasDiscussion()) { |
$discussionHTML = $linkopen . |
$discussionHTML = $linkopen . |
'<img alt="'.&mt('New Discussion').'" src="'.$location.'/chat.gif" title="'.&mt('New Discussion').'"/>' . |
'<img alt="'.&mt('New Discussion').'" src="'.$location.'/chat.gif" title="'.&mt('New Discussion').'"/>' . |
Line 1081 sub render_long_status {
|
Line 1137 sub render_long_status {
|
$params->{'multipart'} && $part eq "0"; |
$params->{'multipart'} && $part eq "0"; |
|
|
my $color; |
my $color; |
|
my $info = ''; |
if ($resource->is_problem() || $resource->is_practice()) { |
if ($resource->is_problem() || $resource->is_practice()) { |
$color = $colormap{$resource->status}; |
$color = $colormap{$resource->status}; |
|
|
if (dueInLessThan24Hours($resource, $part) || |
if (dueInLessThan24Hours($resource, $part) || |
lastTry($resource, $part)) { |
lastTry($resource, $part)) { |
$color = $hurryUpColor; |
$color = $hurryUpColor; |
|
$info = ' title="'.&mt('Due in less than 24 hours!').'"'; |
} |
} |
} |
} |
|
|
if (($resource->kind() eq "res" && |
if ($resource->kind() eq "res" && |
($resource->is_problem() || $resource->is_practice()) && |
$resource->is_raw_problem() && |
!$firstDisplayed) && |
!$firstDisplayed) { |
$resource->is_raw_problem()) { |
if ($color) {$result .= '<span style="color:'.$color.'"'.$info.'><b>'; } |
if ($color) {$result .= "<font color=\"$color\"><b>"; } |
|
$result .= getDescription($resource, $part); |
$result .= getDescription($resource, $part); |
if ($color) {$result .= "</b></font>"; } |
if ($color) {$result .= "</b></span>"; } |
} |
} |
if ($resource->is_map() && &advancedUser() && $resource->randompick()) { |
if ($resource->is_map() && &advancedUser() && $resource->randompick()) { |
$result .= &mt('(randomly select [_1])', $resource->randompick()); |
$result .= &mt('(randomly select [_1])', $resource->randompick()); |
Line 1178 sub render_parts_summary_status {
|
Line 1235 sub render_parts_summary_status {
|
} |
} |
$return.= $td . $totalParts . ' parts: '; |
$return.= $td . $totalParts . ' parts: '; |
foreach my $status (@statuses) { |
foreach my $status (@statuses) { |
if ($overallstatus{$status}) { |
if ($overallstatus{$status}) { |
$return.="<font color='" . $statusColors{$status} . |
$return.='<span style="color:' . $statusColors{$status} |
"'>" . $overallstatus{$status} . ' ' |
. '">' . $overallstatus{$status} . ' ' |
. $statusStrings{$status} . "</font>"; |
. $statusStrings{$status} . '</span>'; |
} |
} |
} |
} |
$return.= $endtd; |
$return.= $endtd; |
return $return; |
return $return; |
Line 1419 sub render {
|
Line 1476 sub render {
|
$link .= '&register='.$env{'form.register'}; |
$link .= '&register='.$env{'form.register'}; |
} |
} |
if ($args->{'caller'} eq 'navmapsdisplay') { |
if ($args->{'caller'} eq 'navmapsdisplay') { |
&add_linkitem($args->{'linkitems'},'changefolder', |
unless ($args->{'notools'}) { |
"location.href='$link'",$text); |
&add_linkitem($args->{'linkitems'},'changefolder', |
|
"location.href='$link'",$text); |
|
} |
} else { |
} else { |
$result.= '<a href="'.$link.'">'.&mt($text).'</a>'; |
$result.= '<a href="'.$link.'">'.&mt($text).'</a>'; |
} |
} |
Line 1428 sub render {
|
Line 1487 sub render {
|
} |
} |
|
|
# Check for any unread discussions in all resources. |
# Check for any unread discussions in all resources. |
if ($args->{'caller'} eq 'navmapsdisplay') { |
if (($args->{'caller'} eq 'navmapsdisplay') && (!$args->{'notools'})) { |
&add_linkitem($args->{'linkitems'},'clearbubbles', |
&add_linkitem($args->{'linkitems'},'clearbubbles', |
'document.clearbubbles.submit()', |
'document.clearbubbles.submit()', |
'Mark all posts read'); |
'Mark all posts read'); |
my $time=time; |
my $time=time; |
|
my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"'); |
$result .= (<<END); |
$result .= (<<END); |
<form name="clearbubbles" method="post" action="/adm/feedback"> |
<form name="clearbubbles" method="post" action="/adm/feedback"> |
<input type="hidden" name="navurl" value="$ENV{'QUERY_STRING'}" /> |
<input type="hidden" name="navurl" value="$querystr" /> |
<input type="hidden" name="navtime" value="$time" /> |
<input type="hidden" name="navtime" value="$time" /> |
END |
END |
if ($env{'form.register'}) { |
if ($env{'form.register'}) { |
Line 1461 END
|
Line 1521 END
|
} |
} |
$result.='</form>'; |
$result.='</form>'; |
} |
} |
|
if (($args->{'caller'} eq 'navmapsdisplay') && |
|
(&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { |
|
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
|
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; |
|
if ($env{'course.'.$env{'request.course.id'}.'.url'} eq |
|
"uploaded/$cdom/$cnum/default.sequence") { |
|
&add_linkitem($args->{'linkitems'},'edittoplevel', |
|
"javascript:gocmd('/adm/coursedocs','editdocs');", |
|
'Content Editor'); |
|
} |
|
} |
|
|
if ($args->{'caller'} eq 'navmapsdisplay') { |
if ($args->{'caller'} eq 'navmapsdisplay') { |
$result .= '<table><tr><td>'. |
$result .= &show_linkitems_toolbar($args,$condition); |
&Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT').'</td>'; |
|
$result .= '<td> </td>'; |
|
$result.='<td class="LC_middle">'.&mt('Tools:').'</td>'; |
|
$result.=&show_linkitems_toolbar($args->{'linkitems'}); |
|
if ($args->{'sort_html'}) { |
|
$result.='<td> </td><td> </td><td> </td>'. |
|
'<td align="right">'.$args->{'sort_html'}.'</td></tr>'; |
|
} |
|
$result .= '</table>'; |
|
} elsif ($args->{'sort_html'}) { |
} elsif ($args->{'sort_html'}) { |
$result.=$args->{'sort_html'}; |
$result.=$args->{'sort_html'}; |
} |
} |
Line 1775 END
|
Line 1837 END
|
} |
} |
} |
} |
} |
} |
|
|
|
$result.=&Apache::loncommon::end_data_table(); |
|
|
# Print out the part that jumps to #curloc if it exists |
# Print out the part that jumps to #curloc if it exists |
# delay needed because the browser is processing the jump before |
# delay needed because the browser is processing the jump before |
Line 1791 if (location.href.indexOf('#curloc')==-1
|
Line 1855 if (location.href.indexOf('#curloc')==-1
|
"); |
"); |
} |
} |
|
|
$result.=&Apache::loncommon::end_data_table(); |
|
|
|
if ($r) { |
if ($r) { |
$r->print($result); |
$r->print($result); |
$result = ""; |
$result = ""; |
Line 1809 sub add_linkitem {
|
Line 1871 sub add_linkitem {
|
} |
} |
|
|
sub show_linkitems_toolbar { |
sub show_linkitems_toolbar { |
my ($linkitems,$condition)=@_; |
my ($args,$condition) = @_; |
my @linkorder = ('firsthomework','everything','uncompleted', |
my $result; |
'changefolder','clearbubbles'); |
if (ref($args) eq 'HASH') { |
my $result .='<td align="left">'."\n". |
if (ref($args->{'linkitems'}) eq 'HASH') { |
'<span class="LC_nobreak">'."\n". |
my $numlinks = scalar(keys(%{$args->{'linkitems'}})); |
'<ul id="LC_toolbar">'; |
if ($numlinks > 1) { |
foreach my $link (@linkorder) { |
$result = '<td>'. |
my $link_id = 'LC_content_toolbar_'.$link; |
&Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen', |
if (defined($linkitems->{$link})) { |
undef,'RAT'). |
if ($linkitems->{$link}{'text'} ne '') { |
'</td>'. |
$linkitems->{$link}{'cmd'}=~s/"/'/g; |
'<td> </td>'. |
if ($linkitems->{$link}{'cmd'}) { |
'<td class="LC_middle">'.&mt('Tools:').'</td>'; |
if ($link eq 'changefolder') { |
} |
if ($condition) { |
$result .= '<td align="left">'."\n". |
$link_id='LC_content_toolbar_changefolder_toggled'; |
'<ul id="LC_toolbar">'; |
} else { |
my @linkorder = ('firsthomework','everything','uncompleted', |
$link_id='LC_content_toolbar_changefolder'; |
'changefolder','clearbubbles','edittoplevel'); |
|
foreach my $link (@linkorder) { |
|
if (ref($args->{'linkitems'}{$link}) eq 'HASH') { |
|
if ($args->{'linkitems'}{$link}{'text'} ne '') { |
|
$args->{'linkitems'}{$link}{'cmd'}=~s/"/'/g; |
|
if ($args->{'linkitems'}{$link}{'cmd'}) { |
|
my $link_id = 'LC_content_toolbar_'.$link; |
|
if ($link eq 'changefolder') { |
|
if ($condition) { |
|
$link_id='LC_content_toolbar_changefolder_toggled'; |
|
} else { |
|
$link_id='LC_content_toolbar_changefolder'; |
|
} |
|
} |
|
$result .= '<li><a href="#" '. |
|
'onclick="'.$args->{'linkitems'}{$link}{'cmd'}.'" '. |
|
'id="'.$link_id.'" '. |
|
'class="LC_toolbarItem" '. |
|
'title="'.$args->{'linkitems'}{$link}{'text'}.'">'. |
|
'</a></li>'."\n"; |
} |
} |
} |
} |
$result .= '<li><a href="#" '. |
|
'onclick="'.$linkitems->{$link}{'cmd'}.'" '. |
|
'id="'.$link_id.'" '. |
|
'class="LC_toolbarItem" '. |
|
'title="'.$linkitems->{$link}{'text'}.'">'. |
|
'</a></li>'."\n"; |
|
} |
} |
} |
} |
|
$result .= '</ul>'. |
|
'</td>'; |
|
if (($numlinks==1) && (exists($args->{'linkitems'}{'edittoplevel'}))) { |
|
$result .= '<td><a href="'.$args->{'linkitems'}{'edittoplevel'}{'cmd'}.'">'. |
|
&mt('Content Editor').'</a></td>'; |
|
} |
} |
} |
|
if ($args->{'sort_html'}) { |
|
$result .= '<td> </td><td> </td><td> </td>'. |
|
'<td align="right">'.$args->{'sort_html'}.'</td>'; |
|
} |
|
} |
|
if ($result) { |
|
$result = "<table><tr>$result</tr></table>"; |
} |
} |
$result .= '</ul>'. |
|
'</span></td>'."\n"; |
|
return $result; |
return $result; |
} |
} |
|
|
|
|
1; |
1; |
|
|
|
|
Line 1930 sub new {
|
Line 2015 sub new {
|
my $proto = shift; |
my $proto = shift; |
my $class = ref($proto) || $proto; |
my $class = ref($proto) || $proto; |
my $self = {}; |
my $self = {}; |
|
bless($self); # So we can call change_user if neceesary |
|
|
|
$self->{USERNAME} = shift || $env{'user.name'}; |
|
$self->{DOMAIN} = shift || $env{'user.domain'}; |
|
$self->{CODE} = shift; |
|
$self->{NOHIDE} = shift; |
|
|
|
|
|
|
# Resource cache stores navmap resources as we reference them. We generate |
# Resource cache stores navmap resources as we reference them. We generate |
# them on-demand so we don't pay for creating resources unless we use them. |
# them on-demand so we don't pay for creating resources unless we use them. |
Line 1939 sub new {
|
Line 2032 sub new {
|
# failed |
# failed |
$self->{NETWORK_FAILURE} = 0; |
$self->{NETWORK_FAILURE} = 0; |
|
|
# tie the nav hash |
# We can only tie the nav hash as done below if the username/domain |
|
# match the env one. Otherwise change_user does everything we need...since we can't |
|
# assume there are course hashes for the specific requested user@domamin: |
|
# |
|
|
my %navmaphash; |
if (($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'}) && !$self->{CODE}) { |
my %parmhash; |
|
my $courseFn = $env{"request.course.fn"}; |
# tie the nav hash |
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
|
&GDBM_READER(), 0640))) { |
my %navmaphash; |
return undef; |
my %parmhash; |
|
my $courseFn = $env{"request.course.fn"}; |
|
if (!(tie(%navmaphash, 'GDBM_File', "${courseFn}.db", |
|
&GDBM_READER(), 0640))) { |
|
return undef; |
|
} |
|
|
|
if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", |
|
&GDBM_READER(), 0640))) |
|
{ |
|
untie %{$self->{PARM_HASH}}; |
|
return undef; |
|
} |
|
|
|
$self->{NAV_HASH} = \%navmaphash; |
|
$self->{PARM_HASH} = \%parmhash; |
|
$self->{PARM_CACHE} = {}; |
|
} else { |
|
$self->change_user($self->{USERNAME}, $self->{DOMAIN}, $self->{CODE}, $self->{NOHIDE}); |
} |
} |
|
|
|
return $self; |
|
} |
|
|
|
# |
|
# In some instances it is useful to be able to dynamically change the |
|
# username/domain associated with a navmap (e.g. to navigate for someone |
|
# else besides the current user...if sufficiently privileged. |
|
# Parameters: |
|
# user - New user. |
|
# domain- Domain the user belongs to. |
|
# code - Anonymous CODE in use. |
|
# Implicit inputs: |
|
# |
|
sub change_user { |
|
my $self = shift; |
|
$self->{USERNAME} = shift; |
|
$self->{DOMAIN} = shift; |
|
$self->{CODE} = shift; |
|
$self->{NOHIDE} = shift; |
|
|
|
# If the hashes are already tied make sure to break that bond: |
|
|
|
untie %{$self->{NAV_HASH}}; |
|
untie %{$self->{PARM_HASH}}; |
|
|
|
# The assumption is that we have to |
|
# use lonmap here to re-read the hash and from it reconstruct |
|
# new big and parameter hashes. An implicit assumption at this time |
|
# is that the course file is probably not created locally yet |
|
# an that we will therefore just read without tying. |
|
|
|
my ($cdom, $cnum) = split(/\_/, $env{'request.course.id'}); |
|
|
|
my %big_hash; |
|
&Apache::lonmap::loadmap($cnum, $cdom, $self->{USERNAME}, $self->{DOMAIN}, $self->{CODE}, $self->{NOHIDE}, \%big_hash); |
|
$self->{NAV_HASH} = \%big_hash; |
|
|
|
|
|
|
|
# Now clear the parm cache and reconstruct the parm hash fromt he big_hash |
|
# param.xxxx keys. |
|
|
|
$self->{PARM_CACHE} = {}; |
|
|
if (!(tie(%parmhash, 'GDBM_File', "${courseFn}_parms.db", |
my %parm_hash = {}; |
&GDBM_READER(), 0640))) |
foreach my $key (keys %big_hash) { |
{ |
if ($key =~ /^param\./) { |
untie %{$self->{PARM_HASH}}; |
my $param_key = $key; |
return undef; |
$param_key =~ s/^param\.//; |
|
$parm_hash{$param_key} = $big_hash{$key}; |
|
} |
} |
} |
|
|
$self->{NAV_HASH} = \%navmaphash; |
$self->{PARM_HASH} = \%parm_hash; |
$self->{PARM_HASH} = \%parmhash; |
|
$self->{PARM_CACHE} = {}; |
|
|
|
bless($self); |
|
|
|
return $self; |
} |
} |
|
|
|
sub generate_course_user_opt { |
sub generate_course_user_opt { |
my $self = shift; |
my $self = shift; |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
if ($self->{COURSE_USER_OPT_GENERATED}) { return; } |
|
|
my $uname=$env{'user.name'}; |
my $uname=$self->{USERNAME}; |
my $udom=$env{'user.domain'}; |
my $udom=$self->{DOMAIN}; |
|
|
my $cid=$env{'request.course.id'}; |
my $cid=$env{'request.course.id'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
Line 2004 sub generate_course_user_opt {
|
Line 2162 sub generate_course_user_opt {
|
return; |
return; |
} |
} |
|
|
|
|
|
|
sub generate_email_discuss_status { |
sub generate_email_discuss_status { |
my $self = shift; |
my $self = shift; |
my $symb = shift; |
my $symb = shift; |
Line 2013 sub generate_email_discuss_status {
|
Line 2173 sub generate_email_discuss_status {
|
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
|
|
my %emailstatus = &Apache::lonnet::dump('email_status'); |
my %emailstatus = &Apache::lonnet::dump('email_status',$self->{DOMAIN},$self->{USERNAME}); |
my $logoutTime = $emailstatus{'logout'}; |
my $logoutTime = $emailstatus{'logout'}; |
my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}}; |
my $courseLeaveTime = $emailstatus{'logout_'.$env{'request.course.id'}}; |
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? |
$self->{LAST_CHECK} = (($courseLeaveTime > $logoutTime) ? |
Line 2021 sub generate_email_discuss_status {
|
Line 2181 sub generate_email_discuss_status {
|
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
my %discussiontime = &Apache::lonnet::dump('discussiontimes', |
$cdom, $cnum); |
$cdom, $cnum); |
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', |
my %lastread = &Apache::lonnet::dump('nohist_'.$cid.'_discuss', |
$env{'user.domain'},$env{'user.name'},'lastread'); |
$self->{DOMAIN},$self->{USERNAME},'lastread'); |
my %lastreadtime = (); |
my %lastreadtime = (); |
foreach my $key (keys %lastread) { |
foreach my $key (keys %lastread) { |
my $shortkey = $key; |
my $shortkey = $key; |
Line 2031 sub generate_email_discuss_status {
|
Line 2191 sub generate_email_discuss_status {
|
|
|
my %feedback=(); |
my %feedback=(); |
my %error=(); |
my %error=(); |
my @keys = &Apache::lonnet::getkeys('nohist_email',$env{'user.domain'}, |
my @keys = &Apache::lonnet::getkeys('nohist_email',$self->{DOMAIN}, |
$env{'user.name'}); |
$self->{USERNAME}); |
|
|
foreach my $msgid (@keys) { |
foreach my $msgid (@keys) { |
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { |
if ((!$emailstatus{$msgid}) || ($emailstatus{$msgid} eq 'new')) { |
Line 2080 sub get_user_data {
|
Line 2240 sub get_user_data {
|
|
|
# Retrieve performance data on problems |
# Retrieve performance data on problems |
my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, |
my %student_data = Apache::lonnet::currentdump($env{'request.course.id'}, |
$env{'user.domain'}, |
$self->{DOMAIN}, |
$env{'user.name'}); |
$self->{USERNAME}); |
$self->{STUDENT_DATA} = \%student_data; |
$self->{STUDENT_DATA} = \%student_data; |
|
|
$self->{RETRIEVED_USER_DATA} = 1; |
$self->{RETRIEVED_USER_DATA} = 1; |
Line 2395 sub parmval {
|
Line 2555 sub parmval {
|
my $self = shift; |
my $self = shift; |
my ($what,$symb,$recurse)=@_; |
my ($what,$symb,$recurse)=@_; |
my $hashkey = $what."|||".$symb; |
my $hashkey = $what."|||".$symb; |
|
my $cache = $self->{PARM_CACHE}; |
if (defined($self->{PARM_CACHE}->{$hashkey})) { |
if (defined($self->{PARM_CACHE}->{$hashkey})) { |
if (ref($self->{PARM_CACHE}->{$hashkey}) eq 'ARRAY') { |
if (ref($self->{PARM_CACHE}->{$hashkey}) eq 'ARRAY') { |
if (defined($self->{PARM_CACHE}->{$hashkey}->[0])) { |
if (defined($self->{PARM_CACHE}->{$hashkey}->[0])) { |
Line 2417 sub parmval {
|
Line 2577 sub parmval {
|
return $result->[0]; |
return $result->[0]; |
} |
} |
|
|
|
|
sub parmval_real { |
sub parmval_real { |
my $self = shift; |
my $self = shift; |
my ($what,$symb,$recurse) = @_; |
my ($what,$symb,$recurse) = @_; |
|
|
|
|
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
# Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated |
$self->generate_course_user_opt(); |
$self->generate_course_user_opt(); |
|
|
Line 2432 sub parmval_real {
|
Line 2594 sub parmval_real {
|
@cgrps = sort(@cgrps); |
@cgrps = sort(@cgrps); |
$cgroup = $cgrps[0]; |
$cgroup = $cgrps[0]; |
} |
} |
my $uname=$env{'user.name'}; |
my $uname=$self->{USERNAME}; |
my $udom=$env{'user.domain'}; |
my $udom=$self->{DOMAIN}; |
|
|
unless ($symb) { return ['']; } |
unless ($symb) { return ['']; } |
my $result=''; |
my $result=''; |
Line 2449 sub parmval_real {
|
Line 2611 sub parmval_real {
|
my $mapparm=$mapname.'___(all).'.$what; |
my $mapparm=$mapname.'___(all).'.$what; |
my $usercourseprefix=$cid; |
my $usercourseprefix=$cid; |
|
|
|
|
|
|
my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what; |
my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what; |
my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm; |
my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm; |
my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm; |
my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm; |
|
|
|
|
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; |
my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm; |
my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm; |
|
|
|
|
my $courselevel= $usercourseprefix.'.'.$what; |
my $courselevel= $usercourseprefix.'.'.$what; |
my $courselevelr=$usercourseprefix.'.'.$symbparm; |
my $courselevelr=$usercourseprefix.'.'.$symbparm; |
my $courselevelm=$usercourseprefix.'.'.$mapparm; |
my $courselevelm=$usercourseprefix.'.'.$mapparm; |
|
|
|
|
my $useropt = $self->{USER_OPT}; |
my $useropt = $self->{USER_OPT}; |
my $courseopt = $self->{COURSE_OPT}; |
my $courseopt = $self->{COURSE_OPT}; |
my $parmhash = $self->{PARM_HASH}; |
my $parmhash = $self->{PARM_HASH}; |
Line 2527 sub parmval_real {
|
Line 2694 sub parmval_real {
|
if (defined($pack_def)) { return [$pack_def,'resource']; } |
if (defined($pack_def)) { return [$pack_def,'resource']; } |
return ['']; |
return ['']; |
} |
} |
|
# |
|
# Determines the open/close dates for printing a map that |
|
# encloses a resource. |
|
# |
|
sub map_printdates { |
|
my ($self, $res, $part) = @_; |
|
|
|
|
|
|
|
|
|
|
|
my $opendate = $self->get_mapparam($res->symb(), "$part.printstartdate"); |
|
my $closedate= $self->get_mapparam($res->symb(), "$part.printenddate"); |
|
|
|
|
|
return ($opendate, $closedate); |
|
} |
|
|
|
sub get_mapparam { |
|
my ($self, $symb, $what) = @_; |
|
|
|
# Ensure the course option hash is populated: |
|
|
|
$self->generate_course_user_opt(); |
|
|
|
# Get the course id and section if there is one. |
|
|
|
my $cid=$env{'request.course.id'}; |
|
my $csec=$env{'request.course.sec'}; |
|
my $cgroup=''; |
|
my @cgrps=split(/:/,$env{'request.course.groups'}); |
|
if (@cgrps > 0) { |
|
@cgrps = sort(@cgrps); |
|
$cgroup = $cgrps[0]; |
|
} |
|
my $uname=$self->{USERNAME}; |
|
my $udom=$self->{DOMAIN}; |
|
|
|
unless ($symb) { return ['']; } |
|
my $result=''; |
|
|
|
|
|
# Figure out which map we are in. |
|
|
|
my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb); |
|
$mapname = &Apache::lonnet::deversion($mapname); |
|
|
|
|
|
my $rwhat=$what; |
|
$what=~s/^parameter\_//; |
|
$what=~s/\_/\./; |
|
|
|
# Build the hash keys for the lookup: |
|
|
|
my $symbparm=$symb.'.'.$what; |
|
my $mapparm=$mapname.'___(all).'.$what; |
|
my $usercourseprefix=$cid; |
|
|
|
|
|
my $grplevel = "$usercourseprefix.[$cgroup].$mapparm"; |
|
my $seclevel = "$usercourseprefix.[$csec].$mapparm"; |
|
my $courselevel = "$usercourseprefix.$mapparm"; |
|
|
|
|
|
# Get handy references to the hashes we need in $self: |
|
|
|
my $useropt = $self->{USER_OPT}; |
|
my $courseopt = $self->{COURSE_OPT}; |
|
my $parmhash = $self->{PARM_HASH}; |
|
|
|
# Check per user |
|
|
|
|
|
|
|
if ($uname and defined($useropt)) { |
|
if (defined($$useropt{$courselevel})) { |
|
return $$useropt{$courselevel}; |
|
} |
|
} |
|
|
|
# Check course -- group |
|
|
|
|
|
|
|
if ($cgroup ne '' and defined ($courseopt)) { |
|
if (defined($$courseopt{$grplevel})) { |
|
return $$courseopt{$grplevel}; |
|
} |
|
} |
|
|
|
# Check course -- section |
|
|
|
|
|
|
|
|
|
|
|
if ($csec and defined($courseopt)) { |
|
if (defined($$courseopt{$seclevel})) { |
|
return $$courseopt{$seclevel}; |
|
} |
|
} |
|
# Check the map parameters themselves: |
|
|
|
my $thisparm = $$parmhash{$symbparm}; |
|
if (defined($thisparm)) { |
|
return $thisparm; |
|
} |
|
|
|
|
|
# Additional course parameters: |
|
|
|
if (defined($courseopt)) { |
|
if (defined($$courseopt{$courselevel})) { |
|
return $$courseopt{$courselevel}; |
|
} |
|
} |
|
return undef; # Unefined if we got here. |
|
} |
|
|
|
sub course_printdates { |
|
my ($self, $symb, $part) = @_; |
|
|
|
|
|
my $opendate = $self->getcourseparam($symb, $part . '.printstartdate'); |
|
my $closedate = $self->getcourseparam($symb, $part . '.printenddate'); |
|
return ($opendate, $closedate); |
|
|
|
} |
|
|
|
sub getcourseparam { |
|
my ($self, $symb, $what) = @_; |
|
|
|
$self->generate_course_user_opt(); # If necessary populate the hashes. |
|
|
|
my $uname = $self->{USERNAME}; |
|
my $udom = $self->{DOMAIN}; |
|
|
|
# Course, section, group ids come from the env: |
|
|
|
my $cid = $env{'request.course.id'}; |
|
my $csec = $env{'request.course.sec'}; |
|
my $cgroup = ''; # Assume no group |
|
|
|
my @cgroups = split(/:/, $env{'request.course.groups'}); |
|
if(@cgroups > 0) { |
|
@cgroups = sort(@cgroups); |
|
$cgroup = $cgroups[0]; # There is a course group. |
|
} |
|
my ($mapname,$id,$fn)=&Apache::lonnet::decode_symb($symb); |
|
$mapname = &Apache::lonnet::deversion($mapname); |
|
|
|
# |
|
# Make the various lookup keys: |
|
# |
|
|
|
$what=~s/^parameter\_//; |
|
$what=~s/\_/\./; |
|
|
|
|
|
my $symbparm = $symb . '.' . $what; |
|
my $mapparm=$mapname.'___(all).'.$what; |
|
|
|
# Local refs to the hashes we're going to look at: |
|
|
|
my $useropt = $self->{USER_OPT}; |
|
my $courseopt = $self->{COURSE_OPT}; |
|
|
|
# |
|
# We want the course level stuff from the way |
|
# parmval_real operates |
|
# TODO: Fator some of this stuff out of |
|
# both parmval_real and here |
|
# |
|
my $courselevel = $cid . '.' . $what; |
|
my $grplevel = $cid . '.[' . $cgroup . ']' . $what; |
|
my $seclevel = $cid . '.[' . $csec . ']' . $what; |
|
|
|
|
|
# Try for the user's course level option: |
|
|
|
if ($uname and defined($useropt)) { |
|
if (defined($$useropt{$courselevel})) { |
|
return $$useropt{$courselevel}; |
|
} |
|
} |
|
# Try for the group's course level option: |
|
|
|
if ($uname ne '' and defined($courseopt)) { |
|
if (defined($$courseopt{$grplevel})) { |
|
return $$courseopt{$grplevel}; |
|
} |
|
} |
|
|
|
# Try for section level parameters: |
|
|
|
if ($csec and defined($courseopt)) { |
|
if (defined($$courseopt{$seclevel})) { |
|
return $$courseopt{$seclevel}; |
|
} |
|
} |
|
# Try for 'additional' course parameterse: |
|
|
|
if (defined($courseopt)) { |
|
if (defined($$courseopt{$courselevel})) { |
|
return $$courseopt{$courselevel}; |
|
} |
|
} |
|
return undef; |
|
|
|
} |
|
|
|
|
=pod |
=pod |
|
|
Line 2835 sub new {
|
Line 3213 sub new {
|
weaken($self->{NAV_MAP} = shift); |
weaken($self->{NAV_MAP} = shift); |
return undef unless ($self->{NAV_MAP}); |
return undef unless ($self->{NAV_MAP}); |
|
|
|
$self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; |
|
$self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; |
|
|
# Handle the parameters |
# Handle the parameters |
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
$self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); |
$self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); |
Line 2948 sub new {
|
Line 3329 sub new {
|
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { |
if ($resourceCount == 1 && $resource->is_sequence() && !$self->{FORCE_TOP}) { |
my $firstResource = $resource->map_start(); |
my $firstResource = $resource->map_start(); |
my $finishResource = $resource->map_finish(); |
my $finishResource = $resource->map_finish(); |
return |
my $result; |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$result = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$finishResource, $self->{FILTER}, |
$finishResource, $self->{FILTER}, |
$self->{ALREADY_SEEN}, |
$self->{ALREADY_SEEN}, |
$self->{CONDITION}, |
$self->{CONDITION}, |
$self->{FORCE_TOP}); |
$self->{FORCE_TOP}); |
|
return $result; |
|
|
|
|
} |
} |
|
|
Line 2973 sub new {
|
Line 3356 sub new {
|
$self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; |
$self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; |
|
|
bless ($self); |
bless ($self); |
|
|
return $self; |
return $self; |
} |
} |
|
|
Line 2988 sub next {
|
Line 3370 sub next {
|
# do so. |
# do so. |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { |
$self->{HAVE_RETURNED_0} = 1; |
$self->{HAVE_RETURNED_0} = 1; |
|
my $nextTopLevel = $self->{NAV_MAP}->getById('0.0'); |
return $self->{NAV_MAP}->getById('0.0'); |
return $self->{NAV_MAP}->getById('0.0'); |
} |
} |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { |
if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { |
Line 3007 sub next {
|
Line 3390 sub next {
|
if ($self->{RECURSIVE_DEPTH} == 0) { |
if ($self->{RECURSIVE_DEPTH} == 0) { |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
$self->{RECURSIVE_ITERATOR_FLAG} = 0; |
} |
} |
|
|
return $next; |
return $next; |
} |
} |
|
|
Line 3083 sub next {
|
Line 3465 sub next {
|
# So we need to look at all the resources we can get to from here, |
# So we need to look at all the resources we can get to from here, |
# categorize them if we haven't seen them, remember if we have a new |
# categorize them if we haven't seen them, remember if we have a new |
my $nextUnfiltered = $here->getNext(); |
my $nextUnfiltered = $here->getNext(); |
|
|
|
|
my $maxDepthAdded = -1; |
my $maxDepthAdded = -1; |
|
|
for (@$nextUnfiltered) { |
for (@$nextUnfiltered) { |
Line 3116 sub next {
|
Line 3500 sub next {
|
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
$self->{RECURSIVE_ITERATOR_FLAG} = 1; |
my $firstResource = $self->{HERE}->map_start(); |
my $firstResource = $self->{HERE}->map_start(); |
my $finishResource = $self->{HERE}->map_finish(); |
my $finishResource = $self->{HERE}->map_finish(); |
|
|
$self->{RECURSIVE_ITERATOR} = |
$self->{RECURSIVE_ITERATOR} = |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, |
$finishResource, $self->{FILTER}, |
$finishResource, $self->{FILTER}, |
Line 3208 sub new {
|
Line 3591 sub new {
|
weaken($self->{NAV_MAP} = shift); |
weaken($self->{NAV_MAP} = shift); |
return undef unless ($self->{NAV_MAP}); |
return undef unless ($self->{NAV_MAP}); |
|
|
|
$self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; |
|
$self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; |
|
|
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
$self->{FIRST_RESOURCE} = shift || $self->{NAV_MAP}->firstResource(); |
$self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); |
$self->{FINISH_RESOURCE} = shift || $self->{NAV_MAP}->finishResource(); |
|
|
Line 3444 sub new {
|
Line 3830 sub new {
|
weaken($self->{NAV_MAP} = shift); |
weaken($self->{NAV_MAP} = shift); |
$self->{ID} = shift; |
$self->{ID} = shift; |
|
|
|
$self->{USERNAME} = $self->{NAV_MAP}->{USERNAME}; |
|
$self->{DOMAIN} = $self->{NAV_MAP}->{DOMAIN}; |
|
|
# Store this new resource in the parent nav map's cache. |
# Store this new resource in the parent nav map's cache. |
$self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; |
$self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; |
$self->{RESOURCE_ERROR} = 0; |
$self->{RESOURCE_ERROR} = 0; |
|
|
|
$self->{DUEDATE_CACHE} = undef; |
|
|
# A hash that can be used by two-pass algorithms to store data |
# A hash that can be used by two-pass algorithms to store data |
# about this resource in. Not used by the resource object |
# about this resource in. Not used by the resource object |
# directly. |
# directly. |
Line 3707 sub is_practice {
|
Line 4098 sub is_practice {
|
sub is_problem { |
sub is_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { |
if ($src =~ /$LONCAPA::assess_re/) { |
return !($self->is_practice()); |
return !($self->is_practice()); |
} |
} |
return 0; |
return 0; |
Line 3730 my %incomplete_hash =
|
Line 4121 my %incomplete_hash =
|
sub is_incomplete { |
sub is_incomplete { |
my $self = shift; |
my $self = shift; |
if ($self->is_problem()) { |
if ($self->is_problem()) { |
&Apache::lonnet::logthis('is problem'); |
|
foreach my $part (@{$self->parts()}) { |
foreach my $part (@{$self->parts()}) { |
&Apache::lonnet::logthis("$part status ".$self->status($part)); |
|
if (exists($incomplete_hash{$self->status($part)})) { |
if (exists($incomplete_hash{$self->status($part)})) { |
return 1; |
return 1; |
} |
} |
Line 3744 sub is_incomplete {
|
Line 4133 sub is_incomplete {
|
sub is_raw_problem { |
sub is_raw_problem { |
my $self=shift; |
my $self=shift; |
my $src = $self->src(); |
my $src = $self->src(); |
if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) { |
if ($src =~ /$LONCAPA::assess_re/) { |
return 1; |
return 1; |
} |
} |
return 0; |
return 0; |
Line 3846 resource of the map.
|
Line 4235 resource of the map.
|
|
|
Returns a string with the type of the map in it. |
Returns a string with the type of the map in it. |
|
|
=item *B<map_hierarchy>: |
=item * B<map_hierarchy>: |
|
|
Returns a string with a comma-separated ordered list of map_pc IDs |
Returns a string with a comma-separated ordered list of map_pc IDs |
for the hierarchy of maps containing a map, with the top level |
for the hierarchy of maps containing a map, with the top level |
Line 3917 their code.)
|
Line 4306 their code.)
|
|
|
=over 4 |
=over 4 |
|
|
=item * B<acc>: |
|
|
=item * B<printable> |
|
|
|
returns true if the current date is such that the |
|
specified resource part is printable. |
|
|
|
|
|
=item * B<resprintable> |
|
|
|
Returns true if all parts in the resource are printable making the |
|
entire resource printable. |
|
|
|
=item * B<acc> |
|
|
Get the Client IP/Name Access Control information. |
Get the Client IP/Name Access Control information. |
|
|
Line 3970 Get the weight for the problem.
|
Line 4371 Get the weight for the problem.
|
|
|
=cut |
=cut |
|
|
|
|
|
|
|
|
|
sub printable { |
|
|
|
my ($self, $part) = @_; |
|
|
|
# The following cases apply: |
|
# - If a start date is not set, it is replaced by the open date. |
|
# - Ditto for start/open replaced by content open. |
|
# - If neither start nor printdates are set the part is printable. |
|
# - Start date set but no end date: Printable if now >= start date. |
|
# - End date set but no start date: Printable if now <= end date. |
|
# - both defined: printable if start <= now <= end |
|
# |
|
|
|
# Get the print open/close dates for the resource. |
|
|
|
my $start = $self->parmval("printstartdate", $part); |
|
my $end = $self->parmval("printenddate", $part); |
|
|
|
if (!$start) { |
|
$start = $self->parmval("opendate", $part); |
|
} |
|
if (!$start) { |
|
$start = $self->parmval("contentopen", $part); |
|
} |
|
|
|
|
|
my $now = time(); |
|
|
|
|
|
my $startok = 1; |
|
my $endok = 1; |
|
|
|
if ((defined $start) && ($start ne '')) { |
|
$startok = $start <= $now; |
|
} |
|
if ((defined $end) && ($end != '')) { |
|
$endok = $end >= $now; |
|
} |
|
return $startok && $endok; |
|
} |
|
|
|
sub resprintable { |
|
my $self = shift; |
|
|
|
# get parts...or realize there are no parts. |
|
|
|
my $partsref = $self->parts(); |
|
my @parts = @$partsref; |
|
|
|
if (!@parts) { |
|
return $self->printable(0); |
|
} else { |
|
foreach my $part (@parts) { |
|
if (!$self->printable($part)) { |
|
return 0; |
|
} |
|
} |
|
return 1; |
|
} |
|
} |
|
|
sub acc { |
sub acc { |
(my $self, my $part) = @_; |
(my $self, my $part) = @_; |
my $acc = $self->parmval("acc", $part); |
my $acc = $self->parmval("acc", $part); |
Line 4022 sub checkedin {
|
Line 4487 sub checkedin {
|
} |
} |
} |
} |
# this should work exactly like the copy in lonhomework.pm |
# this should work exactly like the copy in lonhomework.pm |
|
# Why is there a copy in lonhomework? Why not centralized? |
|
# |
|
# TODO: Centralize duedate. |
|
# |
|
|
sub duedate { |
sub duedate { |
(my $self, my $part) = @_; |
(my $self, my $part) = @_; |
|
if (defined ($self->{DUEDATE_CACHE}->{$part})) { |
|
return $self->{DUEDATE_CACHE}->{$part}; |
|
} |
my $date; |
my $date; |
my @interval=$self->parmval("interval", $part); |
my @interval=$self->parmval("interval", $part); |
my $due_date=$self->parmval("duedate", $part); |
my $due_date=$self->parmval("duedate", $part); |
Line 4040 sub duedate {
|
Line 4513 sub duedate {
|
} else { |
} else { |
$date = $due_date; |
$date = $due_date; |
} |
} |
|
$self->{DUEDATE_CACHE}->{$part} = $date; |
return $date; |
return $date; |
} |
} |
sub handgrade { |
sub handgrade { |
Line 4101 sub weight {
|
Line 4575 sub weight {
|
my $self = shift; my $part = shift; |
my $self = shift; my $part = shift; |
if (!defined($part)) { $part = '0'; } |
if (!defined($part)) { $part = '0'; } |
my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', |
my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', |
$self->symb(), $env{'user.domain'}, |
$self->symb(), $self->{DOMAIN}, |
$env{'user.name'}, |
$self->{USERNAME}, |
$env{'request.course.sec'}); |
$env{'request.course.sec'}); |
return $weight; |
return $weight; |
} |
} |
Line 4130 sub getReturnHash {
|
Line 4604 sub getReturnHash {
|
my $self = shift; |
my $self = shift; |
|
|
if (!defined($self->{RETURN_HASH})) { |
if (!defined($self->{RETURN_HASH})) { |
my %tmpHash = &Apache::lonnet::restore($self->symb()); |
my %tmpHash = &Apache::lonnet::restore($self->symb(),undef,$self->{DOMAIN},$self->{USERNAME}); |
$self->{RETURN_HASH} = \%tmpHash; |
$self->{RETURN_HASH} = \%tmpHash; |
} |
} |
} |
} |
Line 4891 sub status {
|
Line 5365 sub status {
|
} |
} |
|
|
# Otherwise, it's untried and open |
# Otherwise, it's untried and open |
return OPEN; |
return OPEN; |
} |
} |
|
|
sub check_for_slot { |
sub check_for_slot { |
my $self = shift; |
my $self = shift; |
my $part = shift; |
my $part = shift; |
|
my $symb = $self->symb(); |
my ($use_slots,$available,$availablestudent) = $self->slot_control($part); |
my ($use_slots,$available,$availablestudent) = $self->slot_control($part); |
if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) { |
if (($use_slots ne '') && ($use_slots !~ /^\s*no\s*$/i)) { |
my @slots = (split(/:/,$availablestudent),split(/:/,$available)); |
my @slots = (split(/:/,$availablestudent),split(/:/,$available)); |
Line 4904 sub check_for_slot {
|
Line 5379 sub check_for_slot {
|
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cdom=$env{'course.'.$cid.'.domain'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $cnum=$env{'course.'.$cid.'.num'}; |
my $now = time; |
my $now = time; |
|
my $num_usable_slots = 0; |
if (@slots > 0) { |
if (@slots > 0) { |
my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum); |
my %slots=&Apache::lonnet::get('slots',[@slots],$cdom,$cnum); |
if (&Apache::lonnet::error(%slots)) { |
if (&Apache::lonnet::error(%slots)) { |
return (UNKNOWN); |
return (UNKNOWN); |
} |
} |
my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots); |
my @sorted_slots = &Apache::loncommon::sorted_slots(\@slots,\%slots,'starttime'); |
my ($checkedin,$checkedinslot); |
my ($checkedin,$checkedinslot); |
foreach my $slot_name (@sorted_slots) { |
foreach my $slot_name (@sorted_slots) { |
next if (!defined($slots{$slot_name}) || |
next if (!defined($slots{$slot_name}) || !ref($slots{$slot_name})); |
!ref($slots{$slot_name})); |
|
my $end = $slots{$slot_name}->{'endtime'}; |
my $end = $slots{$slot_name}->{'endtime'}; |
my $start = $slots{$slot_name}->{'starttime'}; |
my $start = $slots{$slot_name}->{'starttime'}; |
my $ip = $slots{$slot_name}->{'ip'}; |
my $ip = $slots{$slot_name}->{'ip'}; |
if ($self->simpleStatus() == OPEN) { |
if ($self->simpleStatus() == OPEN) { |
my $startreserve = $slots{$slot_name}->{'startreserve'}; |
|
my @proctors; |
|
if ($slots{$slot_name}->{'proctor'} ne '') { |
|
@proctors = split(',',$slots{$slot_name}->{'proctor'}); |
|
} |
|
if ($end > $now) { |
if ($end > $now) { |
($checkedin,$checkedinslot) = $self->checkedin(); |
if ($start > $now) { |
if ($startreserve < $now) { |
return (RESERVED_LATER,$start,$slot_name); |
if ($start > $now) { |
} else { |
return (RESERVED_LATER,$start,$slot_name); |
if ($ip ne '') { |
} else { |
if (!&Apache::loncommon::check_ip_acc($ip)) { |
if ($ip ne '') { |
return (RESERVED_LOCATION,$ip,$slot_name); |
if (!&Apache::loncommon::check_ip_acc($ip)) { |
|
return (RESERVED_LOCATION,$ip,$slot_name); |
|
} |
|
} |
|
if (@proctors > 0) { |
|
unless ((grep(/^\Q$checkedin\E/,@proctors)) && |
|
($checkedinslot eq $slot_name)) { |
|
return (NEEDS_CHECKIN,undef,$slot_name); |
|
} |
|
} |
} |
return (RESERVED,$end,$slot_name); |
|
} |
} |
} else { |
my @proctors; |
if ($start > $now) { |
if ($slots{$slot_name}->{'proctor'} ne '') { |
return (RESERVABLE,$startreserve,$slot_name); |
@proctors = split(',',$slots{$slot_name}->{'proctor'}); |
} |
} |
|
if (@proctors > 0) { |
|
($checkedin,$checkedinslot) = $self->checkedin(); |
|
unless ((grep(/^\Q$checkedin\E/,@proctors)) && |
|
($checkedinslot eq $slot_name)) { |
|
return (NEEDS_CHECKIN,undef,$slot_name); |
|
} |
|
} |
|
return (RESERVED,$end,$slot_name); |
} |
} |
} |
} |
|
} elsif ($end > $now) { |
|
$num_usable_slots ++; |
} |
} |
} |
} |
my ($is_correct,$got_grade); |
my ($is_correct,$got_grade); |
Line 4955 sub check_for_slot {
|
Line 5425 sub check_for_slot {
|
my $taskstatus = $self->taskstatus(); |
my $taskstatus = $self->taskstatus(); |
$is_correct = (($taskstatus eq 'pass') || |
$is_correct = (($taskstatus eq 'pass') || |
($self->solved() =~ /^correct_/)); |
($self->solved() =~ /^correct_/)); |
$got_grade = ($self->solved() =~ /^(?:pass|fail)$/); |
$got_grade = ($taskstatus =~ /^(?:pass|fail)$/); |
} else { |
} else { |
$got_grade = 1; |
$got_grade = 1; |
$is_correct = ($self->solved() =~ /^correct_/); |
$is_correct = ($self->solved() =~ /^correct_/); |
Line 4968 sub check_for_slot {
|
Line 5438 sub check_for_slot {
|
return (CORRECT); |
return (CORRECT); |
} |
} |
} |
} |
return(NOT_IN_A_SLOT); |
if ($num_usable_slots) { |
} else { |
|
if (!$future_slots_checked) { |
|
$future_slots = &get_future_slots($cdom,$cnum,$now); |
|
$future_slots_checked = 1; |
|
} |
|
if ($future_slots) { |
|
return(NOT_IN_A_SLOT); |
return(NOT_IN_A_SLOT); |
} |
} |
return(NOTRESERVABLE); |
|
} |
} |
} |
my $reservable = &Apache::lonnet::get_reservable_slots($cnum,$cdom,$env{'user.name'}, |
return; |
$env{'user.domain'}); |
} |
if (ref($reservable) eq 'HASH') { |
|
if ((ref($reservable->{'now_order'}) eq 'ARRAY') && (ref($reservable->{'now'}) eq 'HASH')) { |
sub get_future_slots { |
foreach my $slot (reverse (@{$reservable->{'now_order'}})) { |
my ($cdom,$cnum,$now) = @_; |
if (($reservable->{'now'}{$slot}{'symb'} eq '') || |
my %slots=&Apache::lonnet::dump('slots',$cdom,$cnum); |
($reservable->{'now'}{$slot}{'symb'} eq $symb)) { |
my $future_slots = 0; |
return(RESERVABLE,$reservable->{'now'}{$slot}{'endreserve'}); |
foreach my $slot (keys(%slots)) { |
} |
if (($slots{$slot}->{'starttime'} > $now) && |
} |
($slots{$slot}->{'endtime'} > $now)) { |
} |
$future_slots ++; |
if ((ref($reservable->{'future_order'}) eq 'ARRAY') && (ref($reservable->{'future'}) eq 'HASH')) { |
|
foreach my $slot (@{$reservable->{'future_order'}}) { |
|
if (($reservable->{'future'}{$slot}{'symb'} eq '') || |
|
($reservable->{'future'}{$slot}{'symb'} eq $symb)) { |
|
return(RESERVABLE_LATER,$reservable->{'future'}{$slot}{'startreserve'}); |
|
} |
|
} |
|
} |
} |
} |
|
return(NOTRESERVABLE); |
} |
} |
return $future_slots; |
return; |
} |
} |
|
|
sub CLOSED { return 23; } |
sub CLOSED { return 23; } |