--- loncom/interface/lonnavmaps.pm 2011/12/25 19:39:08 1.476 +++ loncom/interface/lonnavmaps.pm 2012/06/19 10:11:35 1.487 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Navigate Maps Handler # -# $Id: lonnavmaps.pm,v 1.476 2011/12/25 19:39:08 raeburn Exp $ +# $Id: lonnavmaps.pm,v 1.487 2012/06/19 10:11:35 foxr Exp $ # # Copyright Michigan State University Board of Trustees @@ -225,7 +225,7 @@ automatically. =over 4 -=item * B: default: constructs one from %env A reference to a fresh ::iterator to use from the navmaps. The rendering will reflect the options passed to the iterator, so you can @@ -484,10 +484,11 @@ use POSIX qw (floor strftime); use Time::HiRes qw( gettimeofday tv_interval ); use LONCAPA; use DateTime(); +use HTML::Entities; # For debugging -# use Data::Dumper; +use Data::Dumper; # symbolic constants @@ -896,6 +897,7 @@ sub part_status_summary { return 4; } sub render_resource { my ($resource, $part, $params) = @_; + my $editmapLink; my $nonLinkedText = ''; # stuff after resource title not in link my $link = $params->{"resourceLink"}; @@ -977,6 +979,14 @@ sub render_resource { $linkopen = ""; $linkclose = ""; } + if ((&Apache::lonnet::allowed('mdc',$env{'request.course.id'})) && + ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/)) { + my $icon = &Apache::loncommon::lonhttpdurl('/res/adm/pages').'/editmap.png'; + $editmapLink=' '. + ''. + ''.&mt('Edit Content').''. + ''; + } } if ($resource->randomout()) { @@ -1010,8 +1020,10 @@ sub render_resource { # Is this the current resource? if (!$params->{'displayedHereMarker'} && $resource->symb() eq $params->{'here'} ) { - $curMarkerBegin = ''; - $curMarkerEnd = ''; + unless ($resource->is_map()) { + $curMarkerBegin = ''; + $curMarkerEnd = ''; + } $params->{'displayedHereMarker'} = 1; } @@ -1030,7 +1042,7 @@ sub render_resource { if (!$params->{'resource_nolink'} && !$resource->is_sequence() && !$resource->is_empty_sequence) { $result .= "$curMarkerBegin$title$partLabel$curMarkerEnd$nonLinkedText"; } else { - $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$nonLinkedText"; + $result .= "$curMarkerBegin$linkopen$title$partLabel$curMarkerEnd$editmapLink$nonLinkedText"; } return $result; @@ -1044,6 +1056,7 @@ sub render_communication_status { my $linkopen = ""; my $linkclose = ""; my $location=&Apache::loncommon::lonhttpdurl("/adm/lonMisc"); + if ($resource->hasDiscussion()) { $discussionHTML = $linkopen . ''.&mt('New Discussion').'' . @@ -1132,14 +1145,6 @@ sub render_long_status { $result .= getDescription($resource, $part); if ($color) {$result .= ""; } } - if ($resource->is_map()) { - if (&Apache::lonnet::allowed('mdc')) { - if ($resource->symb=~/\_\_\_[^\_]+\_\_\_uploaded/) { - $result.=" ". - "".&mt("Edit Content").' '; - } - } - } if ($resource->is_map() && &advancedUser() && $resource->randompick()) { $result .= &mt('(randomly select [_1])', $resource->randompick()); } @@ -1394,7 +1399,6 @@ sub render { } } - # (re-)Locate the jump point, if any # Note this does not take filtering or hidden into account... need # to be fixed? @@ -1462,8 +1466,10 @@ sub render { $link .= '&register='.$env{'form.register'}; } if ($args->{'caller'} eq 'navmapsdisplay') { - &add_linkitem($args->{'linkitems'},'changefolder', - "location.href='$link'",$text); + unless ($args->{'notools'}) { + &add_linkitem($args->{'linkitems'},'changefolder', + "location.href='$link'",$text); + } } else { $result.= ''.&mt($text).''; } @@ -1471,14 +1477,15 @@ sub render { } # 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', 'document.clearbubbles.submit()', 'Mark all posts read'); my $time=time; + my $querystr = &HTML::Entities::encode($ENV{'QUERY_STRING'},'<>&"'); $result .= (< - + END if ($env{'form.register'}) { @@ -1503,15 +1510,16 @@ END } } $result.=''; - if (&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','direct');", - 'Content Editor'); - } + } + 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'); } } @@ -1648,7 +1656,6 @@ END $curRes = shift(@resources); } else { $curRes = $it->next($closeAllPages); - } if (!$curRes) { last; } @@ -1820,6 +1827,8 @@ END } } } + + $result.=&Apache::loncommon::end_data_table(); # Print out the part that jumps to #curloc if it exists # delay needed because the browser is processing the jump before @@ -1836,8 +1845,6 @@ if (location.href.indexOf('#curloc')==-1 "); } - $result.=&Apache::loncommon::end_data_table(); - if ($r) { $r->print($result); $result = ""; @@ -1855,25 +1862,28 @@ sub add_linkitem { sub show_linkitems_toolbar { my ($args,$condition) = @_; - my $result = - ''. - ''. - ''; + my $result; if (ref($args) eq 'HASH') { if (ref($args->{'linkitems'}) eq 'HASH') { + my $numlinks = scalar(keys(%{$args->{'linkitems'}})); + if ($numlinks > 1) { + $result = ''. + ''. + ''; + } + $result .= ''."\n"; + ''; + if (($numlinks==1) && (exists($args->{'linkitems'}{'edittoplevel'}))) { + $result .= ''; + } } if ($args->{'sort_html'}) { $result .= ''. ''; } } - $result .= '
'. - &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen',undef,'RAT'). - ' '.&mt('Tools:').''. + &Apache::loncommon::help_open_menu('Navigation Screen','Navigation_Screen', + undef,'RAT'). + ' '.&mt('Tools:').''."\n". + '
    '; my @linkorder = ('firsthomework','everything','uncompleted', 'changefolder','clearbubbles','edittoplevel'); - $result .='
'."\n". - ''."\n". - '
    '; foreach my $link (@linkorder) { - my $link_id = 'LC_content_toolbar_'.$link; 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'; @@ -1892,18 +1902,23 @@ sub show_linkitems_toolbar { } } $result .= '
'. - '
'. + &mt('Content Editor').'   '.$args->{'sort_html'}.'
'; + if ($result) { + $result = "$result
"; + } return $result; } - 1; @@ -2010,7 +2025,7 @@ sub new { # assume there are course hashes for the specific requested user@domamin: # - if ( ($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) { + if (($self->{USERNAME} eq $env{'user.name'}) && ($self->{DOMAIN} eq $env{'user.domain'})) { # tie the nav hash @@ -2036,8 +2051,6 @@ sub new { $self->change_user($self->{USERNAME}, $self->{DOMAIN}); } - my $d = Data::Dumper->new([$self]); - return $self; } @@ -2089,7 +2102,6 @@ sub change_user { } $self->{PARM_HASH} = \%parm_hash; - @@ -2135,6 +2147,8 @@ sub generate_course_user_opt { return; } + + sub generate_email_discuss_status { my $self = shift; my $symb = shift; @@ -2548,10 +2562,12 @@ sub parmval { return $result->[0]; } + sub parmval_real { my $self = shift; my ($what,$symb,$recurse) = @_; + # Make sure the {USER_OPT} and {COURSE_OPT} hashes are populated $self->generate_course_user_opt(); @@ -2580,18 +2596,23 @@ sub parmval_real { my $mapparm=$mapname.'___(all).'.$what; my $usercourseprefix=$cid; + + my $grplevel=$usercourseprefix.'.['.$cgroup.'].'.$what; my $grplevelr=$usercourseprefix.'.['.$cgroup.'].'.$symbparm; my $grplevelm=$usercourseprefix.'.['.$cgroup.'].'.$mapparm; + my $seclevel= $usercourseprefix.'.['.$csec.'].'.$what; my $seclevelr=$usercourseprefix.'.['.$csec.'].'.$symbparm; my $seclevelm=$usercourseprefix.'.['.$csec.'].'.$mapparm; + my $courselevel= $usercourseprefix.'.'.$what; my $courselevelr=$usercourseprefix.'.'.$symbparm; my $courselevelm=$usercourseprefix.'.'.$mapparm; + my $useropt = $self->{USER_OPT}; my $courseopt = $self->{COURSE_OPT}; my $parmhash = $self->{PARM_HASH}; @@ -2658,6 +2679,217 @@ sub parmval_real { if (defined($pack_def)) { return [$pack_def,'resource']; } 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 @@ -3083,7 +3315,6 @@ sub new { my $firstResource = $resource->map_start(); my $finishResource = $resource->map_finish(); my $result; - my $rdump = Data::Dumper->new([$result]); $result = Apache::lonnavmaps::iterator->new($self->{NAV_MAP}, $firstResource, $finishResource, $self->{FILTER}, $self->{ALREADY_SEEN}, @@ -3110,8 +3341,6 @@ sub new { $self->{ALREADY_SEEN}->{$self->{FIRST_RESOURCE}->{ID}} = 1; bless ($self); - my $selfDump = Data::Dumper->new([$self]); - return $self; } @@ -3127,7 +3356,6 @@ sub next { if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0}) { $self->{HAVE_RETURNED_0} = 1; my $nextTopLevel = $self->{NAV_MAP}->getById('0.0'); - return $self->{NAV_MAP}->getById('0.0'); } if ($self->{RETURN_0} && !$self->{HAVE_RETURNED_0_BEGIN_MAP}) { @@ -3153,7 +3381,6 @@ sub next { if (defined($self->{FORCE_NEXT})) { my $tmp = $self->{FORCE_NEXT}; $self->{FORCE_NEXT} = undef; - return $tmp; } @@ -3275,8 +3502,6 @@ sub next { return $self->next($closeAllPages); } - my $hereResource = $self->{HERE}; - return $self->{HERE}; } @@ -3443,7 +3668,6 @@ sub next { my $nextUnfiltered; if ($self->{DIRECTION} == FORWARD()) { $nextUnfiltered = $self->{HERE}->getNext(); - } else { $nextUnfiltered = $self->{HERE}->getPrevious(); } @@ -3598,6 +3822,8 @@ sub new { $self->{NAV_MAP}->{RESOURCE_CACHE}->{$self->{ID}} = $self; $self->{RESOURCE_ERROR} = 0; + $self->{DUEDATE_CACHE} = undef; + # A hash that can be used by two-pass algorithms to store data # about this resource in. Not used by the resource object # directly. @@ -4065,11 +4291,13 @@ their code.) =over 4 + =item * B returns true if the current date is such that the specified resource part is printable. + =item * B Returns true if all parts in the resource are printable making the @@ -4128,23 +4356,41 @@ Get the weight for the problem. =cut + + + sub printable { my ($self, $part) = @_; - # Get the print open/close dates for the resource. + &Apache::lonnet::logthis($self->symb()); - my $start = $self->parmval("prinstartdate", $part); - my $end = $self->parmval("printenddate", $part); # The following cases apply: - # - No dates set: Printable. + # - 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; @@ -4236,6 +4482,9 @@ sub checkedin { sub duedate { (my $self, my $part) = @_; + if (defined ($self->{DUEDATE_CACHE}->{$part})) { + return $self->{DUEDATE_CACHE}->{$part}; + } my $date; my @interval=$self->parmval("interval", $part); my $due_date=$self->parmval("duedate", $part); @@ -4252,6 +4501,7 @@ sub duedate { } else { $date = $due_date; } + $self->{DUEDATE_CACHE}->{$part} = $date; return $date; } sub handgrade {