--- loncom/interface/lonviewclasslist.pm 2006/08/25 03:26:05 1.7 +++ loncom/interface/lonviewclasslist.pm 2015/03/17 00:08:48 1.17 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Handler to display the classlist # -# $Id: lonviewclasslist.pm,v 1.7 2006/08/25 03:26:05 raeburn Exp $ +# $Id: lonviewclasslist.pm,v 1.17 2015/03/17 00:08:48 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -34,6 +34,7 @@ use strict; use Apache::loncoursedata(); use Apache::loncommon(); use Apache::lonhtmlcommon(); +use Apache::courseprefs(); use Apache::Constants qw(:common :http REDIRECT); use Apache::lonlocal; use Apache::lonnet; @@ -60,14 +61,8 @@ sub handler { $r->send_http_header; return OK; } -# &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, -# ['action','state']); - &Apache::lonhtmlcommon::clear_breadcrumbs(); - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/viewclasslist", - text=>"View Classlist", - faq=>9,bug=>'Instructor Interface',}); - # Needs to be in a course + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['register','forceedit','action','symb','todocs']); if (! ($env{'request.course.fn'})) { $env{'user.error.msg'}= "/adm/viewclasslist:not in course role"; @@ -76,23 +71,124 @@ sub handler { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; # - my $start_page = &Apache::loncommon::start_page('Classlist'); - my $breadcrumbs= &Apache::lonhtmlcommon::breadcrumbs(undef, - 'Enrollment Manager'); + my $start_page; + if ($env{'form.register'}) { + $start_page = &Apache::loncommon::start_page('Classlist',undef, + {'force_register' => $env{'form.register'}}); + } else { + my $brcrum = [{'href' => 'adm/viewclasslist', + 'text' => 'View Classlist'},]; + $start_page = &Apache::loncommon::start_page('Classlist',undef, + {'bread_crumbs' => $brcrum}); + } $r->print(<print(&html_classlist()); - } else { - $r->print('

'. - &mt("You are not authorized to view the classlist for your course."). - '

'); + + # Get classlist view settings + my %viewsettings = &retrieve_view_settings(); + my $crstype = &Apache::loncommon::course_type(); + + if (($env{'form.forceedit'}) || ($env{'form.action'} eq 'setconfig')) { + if (&Apache::lonnet::allowed('opa',$env{'request.course.id'})) { + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my $rosterprefs = &roster_prefs($crstype); + my $allitems = {}; + if ($env{'form.action'} eq 'setconfig') { + my %values=&Apache::lonnet::dump('environment',$cdom,$cnum); + if (keys(%values) > 0) { + my ($numchanged,%changes,%disallowed); + my $prefs = { + classlists => $rosterprefs, + }; + $changes{'classlists'} = {}; + &Apache::courseprefs::process_changes($cdom,'classlists',\%values, + $rosterprefs, + $changes{'classlists'}, + $allitems,\%disallowed,$crstype); + my $message; + if (keys(%{$changes{'classlists'}}) > 0) { + my $actions = ['classlists']; + $message = + &Apache::courseprefs::store_changes($cdom,$cnum,$actions, + $actions,$prefs,\%values, + \%changes,$crstype); + } else { + if ($crstype eq 'Community') { + $message = &mt('No changes made to community settings.'); + } else { + $message = &mt('No changes made to course settings.'); + } + } + $r->print(&Apache::loncommon::confirmwrapper($message)); + } else { + $r->print('
'. + &mt('Unable to retrieve current settings.').'
'. + &mt('No changes saved.'). + '
'); + } + } else { + my $current = {}; + my @settings = ('student_classlist_view','student_classlist_opt_in', + 'student_classlist_portfiles'); + foreach my $setting (@settings) { + $current->{$setting} = $env{"course.$env{'request.course.id'}.$setting"}; + } + my ($output,$rowtotal) = + &Apache::courseprefs::print_config_box($r,$cdom,'display', + 'viewableroster', + $rosterprefs,$current, + $allitems,$crstype); + if ($output) { + $r->print('
'."\n". + ''."\n". + ''."\n". + ''."\n"); + if ($env{'form.symb'}) { + $r->print(''."\n"); + } + if ($env{'form.symb'}) { + $r->print(''."\n"); + } + $r->print('
'. + $output. + '

'. + ''. + '
'); + } else { + $r->print('
'); + if ($crstype eq 'Community') { + $r->print(&mt('No member-viewable community roster settings available.')); + } else { + $r->print(&mt('No student-viewable course roster settings available.')); + } + $r->print('
'); + } + } + } else { + $r->print('
'); + if ($crstype eq 'Community') { + $r->print(&mt('You do not have rights to modify member-viewable community roster settings.')); + } else { + $r->print(&mt('You do not have rights to modify student-viewable course roster settings.')); + } + $r->print('
'); + } + } else { + + # Print classlist + if (keys(%viewsettings) > 0) { + $r->print(&html_classlist($r,$crstype,\%viewsettings)); + } else { + $r->print('
'); + if ($crstype eq 'Community') { + $r->print(&mt("Display of a member-viewable community roster is not currently enabled.")); + } else { + $r->print(&mt("Display of a student-viewable course roster is not currently enabled.")); + } + $r->print('
'); + } } # # Finish up @@ -100,56 +196,194 @@ ENDHEADER return OK; } -sub allowed_to_view_classlist { - return 0 if (! exists($env{'request.course.id'})); - my $cid = $env{'request.course.id'}; - my $viewpermission = 'course.'.$cid.'.student_classlist_view'; - if (exists($env{$viewpermission}) && - $env{$viewpermission} =~ /^(all|section)$/) { - return $env{$viewpermission}; +sub retrieve_view_settings { + my %viewsettings; + if (exists($env{'request.course.id'})) { + my $cid = $env{'request.course.id'}; + my $viewpermission = 'course.'.$cid.'.student_classlist_view'; + my $student_opt_in = 'course.'.$cid.'.student_classlist_opt_in'; + my $portfiles_link = 'course.'.$cid.'.student_classlist_portfiles'; + if (exists($env{$viewpermission}) && + $env{$viewpermission} =~ /^(all|section)$/) { + $viewsettings{'permission'} = $env{$viewpermission}; + if ($viewsettings{'permission'} =~ /^section$/i) { + $viewsettings{'limit_to_section'} = 1; + } else { + $viewsettings{'limit_to_section'} = 0; + } + $viewsettings{'student_opt_in'} = $env{$student_opt_in}; + $viewsettings{'portfiles_link'} = $env{$portfiles_link}; + } + } + return %viewsettings; +} + +sub roster_prefs { + my ($crstype) = @_; + my %lt; + if ($crstype eq 'Community') { + %lt = &Apache::lonlocal::texthash ( + svrs => 'Member-viewable roster settings', + stuv => 'Member-viewable membership list options', + stul => 'Member agreement needed to be listed', + ); } else { - return 0; + %lt = &Apache::lonlocal::texthash( + svrs => 'Student-viewable roster settings', + stuv => 'Student-viewable classlist options', + stul => 'Student agreement needed to be listed', + ); } + $lt{'incl'} = &mt('Include link to accessible portfolio files'); + + return + { text => $lt{'svrs'}, + header => [ {col1 => 'Setting', + col2 => $lt{'stuv'}}], + ordered => ['student_classlist_view', + 'student_classlist_opt_in', + 'student_classlist_portfiles'], + itemtext => { + student_classlist_view => $lt{'stuv'}, + student_classlist_opt_in => $lt{'stul'}, + student_classlist_portfiles => $lt{'incl'}, + }, + }; } sub html_classlist { - my $limit_to_section = (&allowed_to_view_classlist()=~ /^section$/i); - my $Str; - if ($limit_to_section) { + my ($r,$crstype,$viewsettings) = @_; + my ($Str,$title,$secdisplay,$cid,$cdom,$cnum,$listtype,%publicroster); + my $fullroster = &Apache::loncoursedata::get_classlist(); + my $classlist; + + my $singular = 'student'; + my $plural = 'students'; + my $titleplural = 'Students'; + my $heading = &mt('Student-viewable course roster'); + + if ($crstype eq 'Community') { + $singular = 'member'; + $plural = 'members'; + $titleplural = 'Members'; + $heading = &mt('Member-viewable community roster'); + } + + if ($env{'form.action'} eq 'setenv') { + $Str .= &process_student_prefs($crstype); + } + + $Str .= '

'.$heading.'

'; + + $cid = $env{'request.course.id'}; + $cdom = $env{'course.'.$cid.'.domain'}; + $cnum = $env{'course.'.$cid.'.num'}; + + my $title; + if ($viewsettings->{'limit_to_section'}) { if ($env{'request.course.sec'} eq '') { - $Str .= '

'. - &mt('Students with no section').'

'; + $title = &mt($titleplural.' with no section'); + $listtype = 'without a section'; } else { - $Str.='

'. - &mt('Students in section "[_1]"', - $env{'request.course.sec'}). - '

'; + $title = &mt($titleplural.' in section "[_1]"', + $env{'request.course.sec'}); + $listtype = 'in the section'; + $secdisplay = " ($env{'request.course.sec'}) "; } + } else { + $title = &mt($titleplural.' in any section'); + $listtype = 'in the course'; } - # - my $classlist = &Apache::loncoursedata::get_classlist(); - # + + if ($viewsettings->{'student_opt_in'}) { + if ($env{'request.role'} =~ /^st/) { + $Str .= &print_roster_form($crstype); + } + %publicroster = &Apache::lonnet::dump('publicroster',$cdom,$cnum); + } + + $Str .= '

'.$title.'

'; + + my $fullcount = 0; + my $publiccount = 0; + my $displaycount = 0; + my $sectionidx = &Apache::loncoursedata::CL_SECTION(); + my $statusidx = &Apache::loncoursedata::CL_STATUS(); + + foreach my $student (keys(%{$fullroster})) { + my $section = $fullroster->{$student}->[$sectionidx]; + my $status = $fullroster->{$student}->[$statusidx]; + next if (lc($status) ne 'active'); + if ($viewsettings->{'limit_to_section'}) { + next if ($section ne $env{'request.course.sec'}); + } + $fullcount ++; + if ($viewsettings->{'student_opt_in'}) { + if ($publicroster{$student}) { + $classlist->{$student} = $fullroster->{$student}; + $publiccount ++; + } + } else { + $classlist->{$student} = $fullroster->{$student}; + } + } + if ($viewsettings->{'student_opt_in'}) { + $displaycount = $publiccount; + if ($fullcount > $publiccount) { + if ($publiccount) { + $Str .= &mt('Only '.$plural.' who have opted to be listed in the roster ([_1] out of [_2] '.$plural.') are shown.',$publiccount,$fullcount).'
'; + } else { + if ($fullcount == 1) { + $Str .= &mt('The single '.$singular.' '.$listtype.'[_1] has opted not to be listed in the roster.',$secdisplay); + } else { + $Str .= &mt('None of the [_1] '.$plural.' '.$listtype.'[_2] have opted to be listed in the roster.',$fullcount,$secdisplay); + } + return $Str; + } + } else { + if ($fullcount > 1) { + $Str .= &mt('All [_1] '.$plural.' '.$listtype.'[_2] have opted to be listed in the roster.',$fullcount,$secdisplay); + } elsif ($fullcount == 1) { + $Str .= &mt('The single '.$singular.' '.$listtype.'[_1] has opted to be listed in the roster.',$secdisplay); + } + } + } else { + $displaycount = $fullcount; + if ($fullcount > 1) { + $Str .= &mt('All [_1] '.$plural.' '.$listtype.'[_2] are listed in the roster.',$fullcount,$secdisplay); + } elsif ($fullcount == 1) { + $Str .= &mt('There is only a single '.$singular.' '.$listtype.'[_1]',$secdisplay); + } + } + undef($fullroster); + + if (!$displaycount) { + $Str .= &mt('There are currently no '.$plural.' to display.'); + return $Str; + } + # Set up a couple variables. my $usernameidx = &Apache::loncoursedata::CL_SNAME(); my $domainidx = &Apache::loncoursedata::CL_SDOM(); my $fullnameidx = &Apache::loncoursedata::CL_FULLNAME(); - my $sectionidx = &Apache::loncoursedata::CL_SECTION(); - my $statusidx = &Apache::loncoursedata::CL_STATUS(); - # + # Sort the students my $sortby = $fullnameidx; my @Sorted_Students = sort { lc($classlist->{$a}->[$sortby]) cmp lc($classlist->{$b}->[$sortby]) } (keys(%$classlist)); - $Str .= ''.$/. - ''. + $Str .= '
'.&Apache::loncommon::start_data_table()."\n". + &Apache::loncommon::start_data_table_header_row()."\n". ''. # for the count - ''. + ''. ''; - if (! $limit_to_section) { + if (! $viewsettings->{'limit_to_section'}) { $Str .= ''; } - $Str .=''.$/; + if ($viewsettings->{'portfiles_link'}) { + $Str .= ''; + } + $Str .= &Apache::loncommon::end_data_table_header_row(); my $count ++; foreach my $student (@Sorted_Students) { my $username = $classlist->{$student}->[$usernameidx]; @@ -159,14 +393,10 @@ sub html_classlist { $fullname = &mt('Name not given'); } my $section = $classlist->{$student}->[$sectionidx]; - my $status = $classlist->{$student}->[$statusidx]; - next if (lc($status) ne 'active'); - if ($limit_to_section) { - if ($section ne $env{'request.course.sec'}) { - next; - } + if ($section eq '') { + $section = &mt('none'); } - $Str .= ''. + $Str .= &Apache::loncommon::start_data_table_row()."\n". ''. ''; - if (! $limit_to_section) { + $username.':'.$domain,$username,$domain).''; + if (! $viewsettings->{'limit_to_section'}) { $Str .= ''; } - $Str .= ''.$/; + if ($viewsettings->{'portfiles_link'}) { + my $filecounts = &Apache::lonaboutme::portfolio_files($r,'showlink',undef,undef,$domain,$username,$fullname); + my $link; + if (ref($filecounts) eq 'HASH') { + $link = &mt('[quant,_1,file,files,No files]',$filecounts->{'both'}); + if ($filecounts->{'both'} > 0) { + $link = ''.$link.''; + } + } else { + $link = ''.&mt("Error retrieving file information.").''; + } + $Str .= ''; + } + $Str .= &Apache::loncommon::end_data_table_row()."\n"; } - $Str .= '
'.&mt('Student').''.&mt('Name').''.&mt('Username').''.&mt('Section').'
'.&mt('Available Portfolio files').'
'.$count++.''.&Apache::loncommon::aboutmewrapper($fullname, $username, @@ -174,16 +404,123 @@ sub html_classlist { ''.(' 'x2). &Apache::loncommon::messagewrapper (' '. - $username.'@'.$domain,$username,$domain).''.$section.'
'.$link.'
'; + $Str .= &Apache::loncommon::end_data_table(); return $Str; } +sub print_roster_form { + my ($crstype) = @_; + my $cid = $env{'request.course.id'}; + my $showinroster = $env{'environment.internal.'.$cid.'.showinroster'}; + my ($showoff,$showon); + if ($showinroster) { + $showon = ' checked="checked" '; + $showoff = ' '; + } else { + $showoff = ' checked="checked" '; + $showon = ' '; + } + my $singular = 'student'; + if ($crstype eq 'Community') { + $singular = 'member'; + } + my $output = + '
' + .'
'.&mt('Your roster setting').''; + if ($showinroster) { + $output .= &mt("You are currently listed in the $singular-viewable roster."); + } else { + $output .= &mt("You are currently [_1]not[_2] listed in the $singular-viewable roster.",'',''); + } + $output .= '
'.&mt('Include yourself in the roster?').'  '. + '
'. + '  

'. + ''. + ''. + '

'; + return $output; +} + +sub process_student_prefs { + my ($crstype) = @_; + my $cid = $env{'request.course.id'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $cnum = $env{'course.'.$cid.'.num'}; + my $uname = $env{'user.name'}; + my $udom = $env{'user.domain'}; + my $student = $uname.':'.$udom; + my %pubroster = &Apache::lonnet::get('publicroster',[$student],$cdom,$cnum); + my $visibility = &mt('off'); + my $showinroster = $env{'form.showinroster'}; + if ($showinroster) { + $visibility = &mt('on'); + } + my $sturoster = 0; + if ($pubroster{$student}) { + $sturoster = 1; + } + + my $singular = 'student'; + if ($crstype eq 'Community') { + $singular = 'member'; + } + my $output; + if ($sturoster ne $showinroster) { + my %changeHash = ( + 'environment.internal.'.$cid.'.showinroster' => $showinroster, + ); + my $putresult = &Apache::lonnet::put('environment', + \%changeHash,$udom,$uname); + if ($putresult eq 'ok') { + &Apache::lonnet::appenv(\%changeHash); + my $result = &Apache::lonnet::put('publicroster',{$student => $showinroster,},$cdom,$cnum); + if ($result eq 'ok') { + $output .= + &Apache::lonhtmlcommon::confirm_success( + &mt("Display of your name in the $singular-viewable roster set to [_1].",''.$visibility.'')); + } else { + $output .= + &Apache::lonhtmlcommon::confirm_success( + &mt('Error occurred saving display setting.'),1); + } + } else { + $output .= + &Apache::lonhtmlcommon::confirm_success( + &mt('Error occurred saving display setting.'),1); + } + } else { + $output .= + &Apache::lonhtmlcommon::confirm_success( + &mt("Display of your name in the $singular-viewable roster unchanged (set to [_1]).",''.$visibility.'')); + } + $output = &Apache::loncommon::confirmwrapper($output); + return $output; +} + + + + ################################################################### ###################################################################