[LON-CAPA-cvs] cvs: loncom /interface lonuserutils.pm lonwhatsnew.pm /lonnet/perl lonnet.pm

raeburn raeburn at source.lon-capa.org
Sat Aug 18 20:18:42 EDT 2012


raeburn		Sun Aug 19 00:18:42 2012 EDT

  Modified files:              
    /loncom/interface	lonwhatsnew.pm lonuserutils.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - Keep track of last course "login". 
    - Display of last "login" by user/role/section added to What's New screen 
      and also to "List Users" screen. ("login" is selection of course role).
    - DC selecting adhoc role in a course (in which he/she has no existing
      role, and use of role switcher within course do *not* cause update 
      of last log-in for that user/role/section.
  
  
-------------- next part --------------
Index: loncom/interface/lonwhatsnew.pm
diff -u loncom/interface/lonwhatsnew.pm:1.105 loncom/interface/lonwhatsnew.pm:1.106
--- loncom/interface/lonwhatsnew.pm:1.105	Fri Mar 16 21:16:38 2012
+++ loncom/interface/lonwhatsnew.pm	Sun Aug 19 00:18:16 2012
@@ -1,5 +1,5 @@
 #
-# $Id: lonwhatsnew.pm,v 1.105 2012/03/16 21:16:38 www Exp $
+# $Id: lonwhatsnew.pm,v 1.106 2012/08/19 00:18:16 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -72,6 +72,7 @@
 			    ['mdc','versionchanges',0],
                             ['vcl','newroles',1],
                             ['vcl','oldroles',1],
+                            ['whn','crslogin',1],
 			    ) {
 	my ($perm,$key,$check_section) = @{ $perm_check };
 	my $scope = $env{'request.course.id'};
@@ -143,6 +144,13 @@
         $r->print(&Apache::lonhtmlcommon::breadcrumbs
             ("What's New?",#'Course_Action_Items_Intervals'
              ));
+    } elsif ($command eq 'chgcrslogininterval' && $checkallowed{'crslogin'}) {
+        &Apache::lonhtmlcommon::add_breadcrumb
+            ({href=>'/adm/whatsnew?command=chgcrslogininterval&refpage='.$refpage,
+              text=>"Change interval"});
+        $r->print(&Apache::lonhtmlcommon::breadcrumbs
+            ("What's New?",#'Course_Action_Items_Intervals'
+             ));
     } else {
         $r->print(&Apache::lonhtmlcommon::breadcrumbs
             ("What's New?",#'Course_Action_Items_Display'
@@ -188,10 +196,17 @@
                    604800 => 'roles which expired since last week',
                     86400 => 'roles which expired since yesterday',
                    );
+    my %crslogins = (
+                       -1 => 'last logins for anyone who has ever logged in',
+                  2592000 => 'last logins for users in last 30 days',
+                   604800 => 'last logins for users in last 7 days',
+                    86400 => 'last logins for users in last 24 hours',
+                   );
     my %interval_titles = (
         versions => \%versions,
         newroles => \%newroles,
         oldroles => \%oldroles,
+        crslogin => \%crslogins,
     );
     my %initpage = &Apache::lonlocal::texthash (
                      firstres => "first resource in the $lctype",
@@ -220,6 +235,9 @@
     } elsif (($command eq 'chgoldroleinterval')
              && $checkallowed->{'oldroles'}) {
         &display_interval_config($r,$refpage,\%interval_titles,'oldroles');
+    } elsif (($command eq 'chgcrslogininterval')
+             && $checkallowed->{'crslogin'}) {
+        &display_interval_config($r,$refpage,\%interval_titles,'crslogin');
     } else {
         &display_actions_box($r,$command,$refpage,\%threshold_titles,
                         \%interval_titles,\%initpage,$cdom,$crs,$checkallowed);
@@ -245,9 +263,11 @@
     
     my $scripttag;
     unless ($command eq 'chgthreshold' || $command eq 'chginterval' || 
-            $command eq 'chgoldroleinterval' || $command eq 'chgnewroleinterval') {
+            $command eq 'chgoldroleinterval' ||
+            $command eq 'chgnewroleinterval' || $command eq 'chgcrslogininterval') {
        $scripttag = <<"END";
 <script type="text/javascript">
+// <![CDATA[
 function change_display(caller,change) {
     caller.value = change;
     document.visible.submit();
@@ -264,6 +284,52 @@
         }
         $scripttag.='document.visible.submit();
 }
+
+function togglelogins() {
+    var total = document.visible.logincount.value;
+    var sumrow = document.visible.loginrow.value;
+    if (total == 0) {
+        return;
+    }
+    var showlogindetails = 0;
+    for (var i=0; i<document.visible.logindetails.length; i++) {
+        if (document.visible.logindetails[i].checked) {
+            showlogindetails = document.visible.logindetails[i].value;
+        }
+    }
+    var detval = "none";
+    var sumval = "";
+    if (showlogindetails == 1) {
+        detval = "";
+        sumval = "none";
+    }
+    for (var j=0; j<total; j++) {
+        var counter = j+1;
+        var itemid = "logindet_"+counter;
+        personele = document.getElementById(itemid);
+        if (personele != null) {
+            personele.style.display = detval;
+        }
+    }
+    var detheaderele = document.getElementById("logintitledet");
+    if (detheaderele != null) {
+        detheaderele.style.display = detval;
+    }
+    for (var k=0; k<sumrow; k++) {
+        var counter = k+1;
+        var itemid = "loginsum_"+counter;
+        logincatele = document.getElementById(itemid);
+        if (logincatele != null) {
+            logincatele.style.display = sumval;
+        }
+    }
+    var sumheaderele = document.getElementById("logintitlesum");
+    if (sumheaderele != null) {
+        sumheaderele.style.display = sumval;
+    }
+    return;
+}
+// ]]>
 </script>
 ';
     }
@@ -315,6 +381,8 @@
     my %expired;
     my $activecount;
     my %activated;
+    my %loggedin;
+    my $logincount;
     my %res_title = ();
     my %show = ();
     my $needitems = 0;
@@ -445,6 +513,20 @@
         $headings{'newroles'} = &mt('Roles for which access to '.$lctype.' has become available since yesterday');
     }
 
+    $timediff{'crslogin'} = $display_settings{$cid.':crslogininterval'};
+    unless (defined($timediff{'crslogin'})) { $timediff{'crslogin'} = 604800; }
+    $interval{'crslogin'} = $interval_titles->{'crslogin'}->{$timediff{'crslogin'}};
+
+    if ($timediff{'crslogin'} == -1) {
+        $headings{'crslogin'} = &mt('Last login for anyone who has ever logged in');
+    } elsif ($timediff{'crslogin'} == 2592000) {
+        $headings{'crslogin'} = &mt('Last login for users in last 30 days');
+    } elsif ($timediff{'crslogin'} == 604800) {
+        $headings{'crslogin'} = &mt('Last login for users in last 7 days');
+    } elsif ($timediff{'crslogin'} == 86400) {
+        $headings{'crslogin'} = &mt('Last login for users in last 24 hours');
+    }
+
     my $now = time;
     if ($timediff{'versions'} == -1) {
         $timediff{'versions'} = time;
@@ -461,6 +543,12 @@
     }
     my $expiredstart = $now - $timediff{'oldroles'};
 
+    if ($timediff{'crslogin'} == -1) {
+        $timediff{'crslogin'} = time;
+    }
+
+    my $crsloginstart = $now - $timediff{'crslogin'};
+
     my $countunread = $display_settings{$cid.':countunread'};
     unless (defined($countunread)) {
         $countunread = 'on';
@@ -474,7 +562,7 @@
 	    $threshold{'av_attempts'},$threshold{'degdiff'},
 	    '<br />',$threshold{'numstudents'});
 
-    my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail','newroles','oldroles');
+    my @actionorder = ('handgrading','haserrors','abovethreshold','versionchanges','coursediscussion','coursenormalmail','coursecritmail','newroles','oldroles','crslogin');
 
     foreach my $key (keys(%{$checkallowed})) {
 	if ($key =~ /_section$/) { next; }
@@ -512,6 +600,9 @@
     if ($show{'newroles'}) {
         $activecount = &getactivated(\%activated,$activatedstart,'active');
     }
+    if ($show{'crslogin'}) {
+        $logincount = &getloggedin($cdom,$crs,\%loggedin,$crsloginstart);
+    }
     $r->print(qq|<a href="javascript:changeAll('hide');">$lt{'hial'}</a>
        <a href="javascript:changeAll('show');">$lt{'shal'}</a>
      <form method="post" name="visible" action="/adm/whatsnew">\n|);
@@ -522,7 +613,7 @@
         }
     }
 
-    $r->print('<input type="hidden" name="refpage" value="'.$refpage.'" /></form><table class="LC_double_column"><tr><td class="LC_left_col">');
+    $r->print('<input type="hidden" name="refpage" value="'.$refpage.'" /><table class="LC_double_column"><tr><td class="LC_left_col">');
 
     my $displayed = 0;
     my $totalboxes = 0;
@@ -540,7 +631,7 @@
             if ($displayed == $halfway) {
                 $r->print('</td><td> </td><td class="LC_right_col" >');
             }
-            &display_launcher($r,$actionitem,$refpage,$checkallowed,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,\%interval,$countunread,\%expired,$expirecount,\%activated,$activecount,$crstype,$itemserror);
+            &display_launcher($r,$actionitem,$refpage,$checkallowed,\%show,\%headings,\%res_title,\@tograde,\%ungraded,\@bombs,\%bombed,\%changed,\@warnings,\%triggered,\@newdiscussions,\%unread,$msgcount,\@newmsgs,$critmsgcount,\@critmsgs,\%interval,$countunread,\%expired,$expirecount,\%activated,$activecount,$crstype,$itemserror,\%loggedin,$logincount);
             $displayed ++; 
         }
     }
@@ -548,6 +639,7 @@
       </td>
     </tr>
    </table>
+   </form>
 ');
 }
 
@@ -628,6 +720,8 @@
         $r->print('<br />'.&mt('Choose the time window to use to display roles for which access to the '.$lctype.' expired.').'<br />');
     } elsif ($context eq 'newroles') {
         $r->print('<br />'.&mt('Choose the time window to use to display roles for which access to the '.$lctype.' became available.').'<br />');
+    } elsif ($context eq 'crslogin') {
+        $r->print('<br />'.&mt('Choose the time window to use to display the last login by a user in the '.$lctype).'<br />');
     } else {
         $r->print('<br />'.&mt('Choose the time window to use to display resources in the '.$lctype.' with version changes.').'<br />');
     }
@@ -793,10 +887,10 @@
         $tograde,$ungraded,$bombs,$bombed,$changed,$warnings,$triggered,
         $newdiscussions,$unread,$msgcount,$newmsgs,$critmsgcount,$critmsgs,
         $interval,$countunread,$expired,$expirecount,$activated,$activecount,
-        $crstype,$itemserror) = @_;
+        $crstype,$itemserror,$loggedin,$logincount) = @_;
 
     if ($$checkallowed{$action}) {
-        &start_box($r,$show,$headings,$action,$refpage,$action);
+        &start_box($r,$show,$headings,$action,$refpage);
         if ($$show{$action}) {
             if ($action eq 'handgrading') {    # UNGRADED ITEMS
                 &display_handgrade($r,$tograde,$ungraded,$itemserror);
@@ -820,6 +914,9 @@
             } elsif ($action eq 'oldroles') { # EXPIRED ROLES
                 &display_rolechanges($r,$expirecount,$expired,$interval->{'oldroles'},
                                      $crstype);
+            } elsif ($action eq 'crslogin') { #LAST LOGIN
+                &display_crslogins($r,$logincount,$loggedin,$interval->{'crslogin'},
+                                   $crstype);
             }
         }
         &end_box($r);
@@ -1419,6 +1516,39 @@
     return $rolechgcount;
 }
 
+sub getloggedin {
+    my ($cdom,$crs,$lastlogins,$starttime) = @_;
+    my $context = 'course';
+    my ($permission,$allowed) =
+        &Apache::lonuserutils::get_permission($context);
+    my $viewablesec = &Apache::lonuserutils::viewable_section($permission);
+    my %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$crs);
+    my $logincount = 0;
+    my ($tmp) = keys(%crslogins);
+    unless ($tmp =~ /^(con_lost|error|no_such_host)/i) {
+        if (keys(%crslogins) > 0) {
+            foreach my $key (keys(%crslogins)) {
+                my ($uname,$udom,$section,$role) = split(/:/,$key);
+                my $eventtime = $crslogins{$key};
+                if ($eventtime > $starttime) {
+                    if (($viewablesec ne '') && ($section ne '')) {
+                        next if ($viewablesec ne $section);
+                    }
+                    my %chginfo = (
+                                   'section' => $section,
+                                   'uname'   => $uname,
+                                   'udom'    => $udom,
+                                   'role'    => $role,
+                    );
+                    $logincount ++;
+                    push (@{$lastlogins->{$eventtime}},\%chginfo);
+                }
+            }
+        }
+    }
+    return $logincount;
+}
+
 sub checkversions {
     my ($cdom,$crs,$navmap,$changed,$starttime) = @_;
     my %changes=&Apache::lonnet::dump('versionupdate',$cdom,$crs);
@@ -1675,6 +1805,92 @@
     }
     return;
 }
+
+sub display_crslogins {
+    my ($r,$logincount,$loggedin,$interval,$crstype) = @_;
+    my %lt = &Apache::lonlocal::texthash(
+        'user'   => 'User',
+        'role'   => 'Role',
+        'sec'    => 'Section',
+        'number' => 'Total number of logins',
+    );
+    if ($logincount) {
+
+        my $hdr = '<tr class="LC_info_row" style="display:none" id="logintitledet">'.
+                  '<td class="LC_left_item">'.$lt{'user'}.'</td>'.
+                  '<td class="LC_left_item">'.$lt{'role'}.'</td>'.
+                  '<td class="LC_left_item">'.$lt{'sec'}.'</td></tr>'.
+                  '<tr class="LC_info_row" id="logintitlesum">'.
+                  '<td class="LC_left_item">'.$lt{'number'}.'</td>'.
+                  '<td class="LC_left_item">'.$lt{'role'}.'</td>'.
+                  '<td class="LC_left_item">'.$lt{'sec'};
+        my (%bylastname,%counts);
+        if (ref($loggedin) eq 'HASH') {
+            my @logins = sort { $b <=> $a } (keys(%{$loggedin}));
+            my $numlogin = 0;
+            foreach my $item (@logins) {
+                if (ref($loggedin->{$item}) eq 'ARRAY') {
+                    foreach my $user (@{$loggedin->{$item}}) {
+                        if (ref($user) eq 'HASH') {
+                            my $section;
+                            my $role =
+                                &Apache::lonnet::plaintext($user->{'role'},$crstype);
+                            my $status = &mt($user->{'status'});
+                            if ($user->{'section'} eq '') {
+                                $section = &mt('none');
+                            } else {
+                                $section = $user->{'section'};
+                            }
+                            $counts{$user->{'role'}}{$section} ++;
+                            my $uname = $user->{'uname'};
+                            my $udom = $user->{'udom'};
+                            my $fullname = &Apache::loncommon::plainname($uname,$udom,'lastname');
+                            my $link =
+                                &Apache::loncommon::aboutmewrapper($fullname,$uname,$udom);
+                            push(@{$bylastname{$fullname}},
+                                                          '<td>'.$link.'</td>'.
+                                                          '<td>'.$role.'</td>'.
+                                                          '<td>'.$section.'</td>');
+                        }
+                    }
+                }
+            }
+            my $table;
+            foreach my $person (sort(keys(%bylastname))) {
+                if (ref($bylastname{$person}) eq 'ARRAY') {
+                    foreach my $item (@{$bylastname{$person}}) {
+                        $numlogin ++;
+                        my $css_class = $numlogin%2?' class="LC_odd_row"':'';
+                        $table .= '<tr'.$css_class.' style="display:none;"  id="logindet_'.$numlogin.'">'.$item.'</tr>';
+                    }
+                }
+            }
+            my $numrow = 0;
+            foreach my $role (sort(keys(%counts))) {
+                my $showrole = &Apache::lonnet::plaintext($role,$crstype);
+                if (ref($counts{$role}) eq 'HASH') {
+                    foreach my $sec (sort { $b <=> $a } (keys(%{$counts{$role}}))) {
+                        $numrow ++;
+                        my $css_class = $numrow%2?' class="LC_odd_row"':'';
+                        $table .= '<tr '.$css_class.' id="loginsum_'.$numrow.'">'.
+                                  '<td>'.$counts{$role}{$sec}.'</td>'.
+                                  '<td>'.$showrole.'</td>'.
+                                  '<td>'.$sec.'</td></tr>';
+                   }
+                }
+            }
+            $r->print($hdr.'<input type="hidden" name="logincount" value="'.$numlogin.
+                      '" /><input type="hidden" name="loginrow" value="'.$numrow.
+                      '" /></td></tr>'.$table);
+        }
+    } else {
+        $r->print('<tr class="LC_empty_row"><td>'.
+                  &mt('There are no '.$interval).
+                  '<input type="hidden" name="logincount" value="'.$logincount.
+                  '." /></td></tr>');
+    }
+    return;
+}
  
 sub display_coursediscussion {
     my ($r,$newdiscussions,$unread,$countunread,$res_title,$itemserror) = @_;
@@ -1836,6 +2052,8 @@
             $interval_settings{$cid.':oldroleinterval'} = $env{'form.interval'};
         } elsif ($context eq 'newroles') {
             $interval_settings{$cid.':newroleinterval'} = $env{'form.interval'};
+        } elsif ($context eq 'crslogin') {
+            $interval_settings{$cid.':crslogininterval'} = $env{'form.interval'};
         } else {
             $interval_settings{$cid.':interval'} = $env{'form.interval'};
         }
@@ -1990,7 +2208,15 @@
                 <td class="LC_subheader" colspan="2"><a href="/adm/whatsnew?command=chgoldroleinterval&refpage='.$refpage.'">'.$lt{'chin'}.'</a></td>
               </tr>');
          }
-     }
+    } elsif (($caller eq 'crslogin') && ($$show{$caller})) {
+        if ($$show{$caller}) {
+            $r->print('
+              <tr>
+                <td class="LC_subheader" align="left"><span class="LC_nobreak"><label><input type="radio" name="logindetails" value="0" checked="checked" onclick="javascript:togglelogins();" /> '.&mt('Summary').'</label><label><input type="radio" name="logindetails" value="1" onclick="javascript:togglelogins();" /> '.&mt('Details').'</label></span></td><td class="LC_subheader"><a href="/adm/whatsnew?command=chgcrslogininterval&refpage='.$refpage.'">'.$lt{'chin'}.'</a></td>
+              </tr>');
+        }
+    }
+
     $r->print('
               <tr>
                <td colspan="2">
Index: loncom/interface/lonuserutils.pm
diff -u loncom/interface/lonuserutils.pm:1.138 loncom/interface/lonuserutils.pm:1.139
--- loncom/interface/lonuserutils.pm:1.138	Wed Apr 25 21:22:01 2012
+++ loncom/interface/lonuserutils.pm	Sun Aug 19 00:18:16 2012
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Utility functions for managing LON-CAPA user accounts
 #
-# $Id: lonuserutils.pm,v 1.138 2012/04/25 21:22:01 raeburn Exp $
+# $Id: lonuserutils.pm,v 1.139 2012/08/19 00:18:16 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2321,6 +2321,7 @@
                        'type'       => "enroll type/action",
                        'email'      => "e-mail address",
                        'photo'      => "photo",
+                       'lastlogin'  => "last login", 
                        'extent'     => "extent",
                        'pr'         => "Proceed",
                        'ca'         => "check all",
@@ -2369,6 +2370,9 @@
             push(@cols,'groups');
         }
         push(@cols,'email');
+        if ($context eq 'course') {
+            push(@cols,'lastlogin');
+        }
     }
 
     my $rolefilter = $env{'form.showrole'};
@@ -2593,6 +2597,11 @@
                                                 Future  => 'Future',
                                                 Expired => 'Expired',
                                                );
+    # If this is for a single course get last course "log-in".
+    my %crslogins;
+    if ($context eq 'course') {
+        %crslogins=&Apache::lonnet::dump('nohist_crslastlogin',$cdom,$cnum);
+    }
     # Get groups, role, permanent e-mail so we can sort on them if
     # necessary.
     foreach my $user (keys(%{$userlist})) {
@@ -2741,6 +2750,12 @@
                 $in{'end'} = &Apache::lonlocal::locallocaltime($in{'end'});
             }
         }
+        if ($context eq 'course') {
+            my $lastlogin = $crslogins{$in{'username'}.':'.$in{'domain'}.':'.$in{'section'}.':'.$role};
+            if ($lastlogin ne '') {
+                $in{'lastlogin'} = &Apache::lonlocal::locallocaltime($lastlogin);
+            }
+        }
         if ($mode eq 'view' || $mode eq 'html' || $mode eq 'autoenroll' || $mode eq 'pickauthor') {
             $r->print(&Apache::loncommon::start_data_table_row());
             my $checkval;
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.1184 loncom/lonnet/perl/lonnet.pm:1.1185
--- loncom/lonnet/perl/lonnet.pm:1.1184	Fri Aug 17 22:43:58 2012
+++ loncom/lonnet/perl/lonnet.pm	Sun Aug 19 00:18:41 2012
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.1184 2012/08/17 22:43:58 raeburn Exp $
+# $Id: lonnet.pm,v 1.1185 2012/08/19 00:18:41 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -5049,15 +5049,19 @@
 sub check_adhoc_privs {
     my ($cdom,$cnum,$update,$refresh,$now,$checkrole,$caller) = @_;
     my $cckey = 'user.role.'.$checkrole.'./'.$cdom.'/'.$cnum;
+    my $setprivs;
     if ($env{$cckey}) {
         my ($role,$where,$trolecode,$tstart,$tend,$tremark,$tstatus,$tpstart,$tpend);
         &role_status($cckey,$update,$refresh,$now,\$role,\$where,\$trolecode,\$tstatus,\$tstart,\$tend);
         unless (($tstatus eq 'is') || ($tstatus eq 'will_not')) {
             &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
+            $setprivs = 1;
         }
     } else {
         &set_adhoc_privileges($cdom,$cnum,$checkrole,$caller);
+        $setprivs = 1;
     }
+    return $setprivs;
 }
 
 sub set_adhoc_privileges {


More information about the LON-CAPA-cvs mailing list