[LON-CAPA-cvs] cvs: loncom /interface loncommunicate.pm lonmsg.pm lonmsgdisplay.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Wed, 06 Dec 2006 23:44:33 -0000


This is a MIME encoded message

--raeburn1165448673
Content-Type: text/plain

raeburn		Wed Dec  6 18:44:33 2006 EDT

  Modified files:              
    /loncom/interface	lonmsg.pm lonmsgdisplay.pm loncommunicate.pm 
  Log:
  Bug 4636.  Mail folders can now be deleted (if empty) or renamed.
  
  email_status_X.db and nohist_email_X.db files used to store e-mail in different folders now have X set to a unique number (instead of the folder name) for newly created or renamed folders. Legacy data still supported.
  
  
--raeburn1165448673
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20061206184433.txt"

Index: loncom/interface/lonmsg.pm
diff -u loncom/interface/lonmsg.pm:1.188 loncom/interface/lonmsg.pm:1.189
--- loncom/interface/lonmsg.pm:1.188	Wed Dec  6 12:14:50 2006
+++ loncom/interface/lonmsg.pm	Wed Dec  6 18:44:33 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines for messaging
 #
-# $Id: lonmsg.pm,v 1.188 2006/12/06 17:14:50 www Exp $
+# $Id: lonmsg.pm,v 1.189 2006/12/06 23:44:33 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -601,7 +601,31 @@
 sub foldersuffix {
     my $folder=shift;
     unless ($folder) { return ''; }
-    return '_'.&escape($folder);
+    my $suffix;
+    my %folderhash = &get_user_folders($folder);
+    if (ref($folderhash{$folder}) eq 'HASH') {
+        $suffix = '_'.&escape($folderhash{$folder}{'id'});
+    } else {
+        $suffix = '_'.&escape($folder);
+    }
+    return $suffix;
+}
+
+# ========================================================= User-defined folders 
+
+sub get_user_folders {
+    my ($folder) = @_;
+    my %userfolders = 
+          &Apache::lonnet::dump('email_folders',undef,undef,$folder);
+    my $lock = "\0".'lock_counter'; # locks db while counter incremented
+    my $counter = "\0".'idcount';   # used in suffix for email db files
+    if (defined($userfolders{$lock})) {
+        delete($userfolders{$lock});
+    }
+    if (defined($userfolders{$counter})) {
+        delete($userfolders{$counter});
+    }
+    return %userfolders;
 }
 
 1;
Index: loncom/interface/lonmsgdisplay.pm
diff -u loncom/interface/lonmsgdisplay.pm:1.45 loncom/interface/lonmsgdisplay.pm:1.46
--- loncom/interface/lonmsgdisplay.pm:1.45	Wed Nov 29 14:31:47 2006
+++ loncom/interface/lonmsgdisplay.pm	Wed Dec  6 18:44:33 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Routines for messaging display
 #
-# $Id: lonmsgdisplay.pm,v 1.45 2006/11/29 19:31:47 raeburn Exp $
+# $Id: lonmsgdisplay.pm,v 1.46 2006/12/06 23:44:33 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -138,24 +138,133 @@
 
 sub folderlist {
     my $folder=shift;
-    my @allfolders=&Apache::lonnet::getkeys('email_folders');
-    if ($allfolders[0]=~/^error:/) { @allfolders=(); }
-    return '<form method="post" action="/adm/email">'.
-	&mt('Folder').': '.
-	&Apache::loncommon::select_form($folder,'folder',
-			     ('' => &mt('INBOX'),'trash' => &mt('TRASH'),
-			      'new' => &mt('New Messages Only'),
-                              'critical' => &mt('Critical'),
-			      'sent' => &mt('Sent Messages'),
-			      map { $_ => $_ } @allfolders)).
-			      ' '.&mt('Show').
-			      '<select name="interdis">'.
-			      join("\n",map { '<option value="'.$_.'"'.
+    my %lt = &Apache::lonlocal::texthash(
+                actn => 'Action',
+                fold => 'Folder',
+                show => 'Show',
+                go   => 'Go',
+    );
+
+    my %actions = &Apache::lonlocal::texthash(
+                                view => 'View Folder',
+                                rename => 'Rename Folder',
+                                delete => 'Delete Folder',
+    );
+    $actions{'select_form_order'} = ['view','rename','delete'];
+
+    my %permfolders = &get_permanent_folders();
+    my $permlist = join("','",sort(keys(%permfolders)));
+    my ($permlistkeys,$permlistvals);
+    foreach my $key (sort(keys(%permfolders))) {
+        $permlistvals .= $permfolders{$key}."','";
+        $permlistkeys .= $key."','";
+    }
+    $permlistvals =~ s/','$//;
+    $permlistkeys =~ s/','$//;
+    my %gotfolders = &Apache::lonmsg::get_user_folders();
+    my %userfolders;
+
+    foreach my $key (keys(%gotfolders)) {
+        $userfolders{$key} = $key;
+    }
+    my @userorder = sort(keys(%userfolders));
+    my %formhash = (%permfolders,%userfolders);
+    my $folderlist = join("','",@userorder);
+    $folderlist .= "','".$permlistvals;
+
+    $formhash{'select_form_order'} = ['','critical','new',@userorder,'sent','trash'];
+    my $output = qq|<script type="text/javascript">
+function folder_choice(targetform,caller) {
+    var permfolders_keys = new Array('$permlistkeys');
+    var permfolders_vals = new Array('$permlistvals');
+    var allfolders = new Array('$folderlist');
+    if (caller == 'change') {
+        if (targetform.folderaction.options[targetform.folderaction.selectedIndex].value == 'rename') {
+            for (var i=0; i<permfolders_keys.length; i++) {
+                if (permfolders_keys[i] == targetform.folder.value) {
+                    alert("The '"+permfolders_vals[i]+"' folder may not be renamed as it is a mail folder provided by the system.");
+                    return;
+                }
+            }
+            var foldername=prompt('New Name for Folder','New Name');
+            if (foldername) {
+                targetform.renamed.value=foldername;
+                for (var i=0; i<allfolders.length; i++) {
+                    if (allfolders[i] == foldername) {
+                        alert("The folder may not be renamed '"+foldername+"' as this name is already in use for a system-provided or user-defined folder.");
+                        return;
+                    }
+                }
+                targetform.submit();
+            }
+        }
+        else {
+            targetform.submit();
+        }
+    }
+    if (caller == 'new') {
+        var newname=targetform.newfolder.value;
+        if (newname) {
+            for (var i=0; i<allfolders.length; i++) {
+                if (allfolders[i] == newname) {
+                    alert("The new folder may not be named '"+newname+"' as this name is already in use for a system-provided or user-defined folder.");
+                    return;
+                }
+            }
+            targetform.submit();
+        }
+    }
+}
+</script>|;
+    $output .= '
+<form method="post" action="/adm/email" name="folderlist">
+<table border="0" cellspacing="2" cellpadding="2">
+ <tr>
+  <td align="left">
+   <table border="0" cellspacing="2" cellpadding="2">
+    <tr>
+     <td align="center"><b>'.$lt{'fold'}.'</b><br />'."\n".
+	&Apache::loncommon::select_form($folder,'folder',%formhash).'
+     </td>
+     <td align="center"><b>'.$lt{'show'}.'</b><br />
+      <select name="interdis">'.
+	      join("\n",map { '<option value="'.$_.'"'.
 	 ($_==$interdis?' selected="selected"':'').'>'.$_.'</option>' }
-				   (10,20,50,100,200)).'</select>'.	
-   '<input type="submit" value="'.&mt('View Folder').'" /><br />'.
+		   (10,20,50,100,200)).'</select>
+     </td>
+     <td align="center"><b>'.$lt{'actn'}.'</b><br />'.
+    &Apache::loncommon::select_form('view','folderaction',%actions).'
+     </td><td><br />'.
+    '<input type="button" value="'.$lt{'go'}.'" onClick="javascript:folder_choice(this.form,'."'change'".');" />
+     </td>
+    </tr>
+   </table>
+  </td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td>
+  <td align="right">
+   <table><tr><td><br />
+    <input type="button" value="'.&mt('Make New Folder').
+    '" onClick="javascript:folder_choice(this.form,'."'new'".');" /></td>'.
+    '<td align="center"><b>'.&mt('New Folder').'<br />'.
+    '<input type="text" size="15" name="newfolder" value="" />
+    </td></tr></table>
+  </td>
+ </tr>
+</table>'."\n".
     '<input type="hidden" name="sortedby" value="'.$env{'form.sortedby'}.'" />'.
-			      ($folder=~/^(new|critical)/?'</form>':'');
+    '<input type="hidden" name="renamed" value="" />'.
+    ($folder=~/^(new|critical)/?'</form>':'');
+    return $output;
+}
+
+sub get_permanent_folders {
+    my %permfolders = &Apache::lonlocal::texthash (
+                                ''         => 'INBOX',
+                                'trash'    => 'TRASH',
+                                'new'      => 'New Messages Only',
+                                'critical' => 'Critical',
+                                'sent'     => 'Sent Messages',
+    );
+    return %permfolders;
 }
 
 sub scrollbuttons {
@@ -195,14 +304,128 @@
 # ============================================================= Make new folder
 
 sub makefolder {
-    my ($newfolder)=@_;
-    if (($newfolder eq 'sent')
-     || ($newfolder eq 'critical')
-     || ($newfolder eq 'trash')
-     || ($newfolder eq 'new')) { return; }
-    &Apache::lonnet::put('email_folders',{$newfolder => time});
+    my ($newfolder) = @_;
+    my %permfolders = &get_permanent_folders();
+    my %userfolders = &Apache::lonmsg::get_user_folders();
+    my ($outcome,$warning);
+    if (defined($userfolders{$newfolder})) {
+        return &mt('The folder name: "[_1]" is already in use for an existing folder.',$newfolder);
+    }
+    foreach my $perm (keys(%permfolders)) {
+        if ($permfolders{$perm} eq $newfolder) {
+            return &mt('The folder name: "[_1]" is already used for one of the folders automatically generated by the system.',$newfolder);
+        }
+    } 
+    if (&get_msgfolder_lock() eq 'ok') {
+        my %counter_hash = &Apache::lonnet::get('email_folders',["\0".'idcount']);
+        my $lastcount = $counter_hash{"\0".'idcount'};
+        my $folder_id = $lastcount + 1;
+        while (defined($userfolders{$folder_id})) {
+            $folder_id ++;
+        }
+        my %folderinfo = (
+                           id => $folder_id,
+                           created => time,
+                         );
+        $outcome =  
+        &Apache::lonnet::put('email_folders',{$newfolder => \%folderinfo,
+                                             "\0".'idcount' => $folder_id});
+        my $releaseresult = &release_msgfolder_lock();
+        if ($releaseresult ne 'ok') {
+            $warning = $releaseresult;
+        }
+    } else {
+        $outcome = 'Error - could not obtain lock on email folders record.';
+    }
+    return ($outcome,$warning);
 }
 
+# ============================================================= Delete folder
+
+sub deletefolder {
+    my ($folder)=@_;
+    my %permfolders = &get_permanent_folders();
+    if (defined($permfolders{$folder})) {
+        return &mt('The folder [_1] may not be deleted',$folder); 
+    }
+    my %userfolders = &Apache::lonmsg::get_user_folders();
+    if (!defined($userfolders{$folder})) {
+        return &mt('The folder [_1] does not exist so deletion is not required.',
+                   $folder);
+    }
+    # check folder is empty;
+    my $suffix=&Apache::lonmsg::foldersuffix($folder);
+    my @messages = &Apache::lonnet::getkeys('nohist_email'.$suffix);
+    if (@messages > 0) {
+        return &mt('The folder [_1] contains messages so it may not be deleted.').
+               '<br />'.
+               &mt('Delete or move the messages to a different folder first.');
+    }
+    my $delresult = &Apache::lonnet::del('email_folders',[$folder]);
+    return $delresult;
+}
+
+sub renamefolder {
+    my ($folder) = @_;
+    my $newname = $env{'form.renamed'};
+    my %permfolders = &get_permanent_folders();
+    if ($env{'form.renamed'} eq '') {
+        return &mt('The folder "[_1]" may not be renamed to "[_2]" as the new name you requested is an invalid name.',$folder,$newname);
+    }
+    if (defined($permfolders{$newname})) {
+        return &mt('The folder "[_1]" may not be renamed to "[_2]" as the new name you requested is reserved for folders provided automatically by the system.',$folder,$newname);
+    }
+    my %userfolders = &Apache::lonmsg::get_user_folders();
+    if (defined($userfolders{$newname})) {
+        return &mt('The folder "[_1]" may not be renamed to "[_2]" because the new name you requested is already being used for an existing folder.',$folder,$newname);
+    }
+    if (!defined($userfolders{$folder})) {
+        return &mt('The folder "[_1]" could not be renamed to "[_2]" because the folder does not exist.',$folder,$newname);
+    }
+    my %folderinfo;
+    if (ref($userfolders{$folder}) eq 'HASH') {
+        %folderinfo = %{$userfolders{$folder}};
+    } else {
+        %folderinfo = (
+                             id => $folder,
+                        created => $userfolders{$folder},
+                      );
+    }
+    my $outcome =
+     &Apache::lonnet::put('email_folders',{$newname => \%folderinfo});
+    if ($outcome eq 'ok') {
+        $outcome = &Apache::lonnet::del('email_folders',[$folder]);
+    }
+    return $outcome;
+}
+
+sub get_msgfolder_lock {
+    # get lock for mail folder counter.
+    my $lockhash = {
+                  "\0".'lock_counter' => time,
+                   };
+    my $tries = 0;
+    my $gotlock = &Apache::lonnet::newput('email_folders',$lockhash);
+    while (($gotlock ne 'ok') && $tries <3) {
+        $tries ++;
+        sleep 1;
+        $gotlock = &Apache::lonnet::newput('email_folders',$lockhash);
+    }
+    return $gotlock;
+}
+
+sub release_msgfolder_lock {
+    #  remove lock
+    my @del_lock = ("\0".'lock_counter');
+    my $dellockoutcome=&Apache::lonnet::del('email_folders',\@del_lock);
+    if ($dellockoutcome ne 'ok') {
+        return ('<br />'.&mt('Warning: failed to release lock for counter').'<br />');
+    } else {
+        return 'ok';
+    }
+}
+
+
 # ======================================================== Move between folders
 
 sub movemsg {
@@ -520,6 +743,7 @@
     my ($blocked,$startblock,$endblock,$numblocked,$folder) = @_;
     my $suffix=&Apache::lonmsg::foldersuffix($folder);
     my @messages = &Apache::lonnet::getkeys('nohist_email'.$suffix);
+
     #unpack the varibles and repack into temp for sorting
     my @temp;
     my %descriptions;
@@ -640,7 +864,7 @@
     my %lt=&Apache::lonlocal::texthash(
 				       'nm' => 'New Messages',
 				       'su' => 'Subject',
-                                       'co' => 'Course/Group',
+                                       'co' => 'Course',
 				       'da' => 'Date',
 				       'us' => 'Username',
 				       'op' => 'Open',
@@ -799,9 +1023,9 @@
     }
     $r->print('</th><th>');
     if ($env{'form.sortedby'} eq "revcourse") {
-        $r->print('<a href = "?sortedby=course'.$fsqs.'">'.&mt('Course/Group').'</a>');
+        $r->print('<a href = "?sortedby=course'.$fsqs.'">'.&mt('Course').'</a>');
     } else {
-        $r->print('<a href = "?sortedby=revcourse'.$fsqs.'">'.&mt('Course/Group').'</a>');
+        $r->print('<a href = "?sortedby=revcourse'.$fsqs.'">'.&mt('Course').'</a>');
     }
     $r->print('</th><th>');
     if ($env{'form.sortedby'} eq "revstatus") {
@@ -864,12 +1088,14 @@
 	      '<p><input type="submit" name="markeddel" value="'.&mt('Delete Checked').'" /></p>');
     }
     $r->print('<p><input type="submit" name="markedmove" value="'.&mt('Move Checked to Folder').'" />');
-    my @allfolders=&Apache::lonnet::getkeys('email_folders');
-    if ($allfolders[0]=~/^error:/) { @allfolders=(); }
+    my %gotfolders = &Apache::lonmsg::get_user_folders();
+    my %userfolders;
+    foreach my $key (keys(%gotfolders)) {
+        $userfolders{$key} = $key;
+    }
     $r->print(
 	&Apache::loncommon::select_form('','movetofolder',
-			     ( map { $_ => $_ } @allfolders))
-	      );
+			                %userfolders));
     my $postedstartdis=$startdis+1;
     $r->print('<input type="hidden" name="folder" value="'.$folder.'" /><input type="hidden" name="startdis" value="'.$postedstartdis.'" /><input type="hidden" name="interdis" value="'.$env{'form.interdis'}.'" /></form>');
     if ($numblocked > 0) {
@@ -2207,11 +2433,43 @@
 	}
     } elsif ($env{'form.newfolder'}) {
 	&printheader($r,'','New Folder');
-	&makefolder($env{'form.newfolder'});
-	&Apache::loncommunicate::menu($r);
-	&disall($r,$env{'form.newfolder'});
+        my $showfolder = $env{'form.newfolder'};
+	my ($makeresult,$warning) = &makefolder($env{'form.newfolder'});
+        if ($makeresult eq 'ok') {
+            $r->print(&mt('Mail folder "[_1]" created.',$showfolder).'<br />');
+        } else {
+            $r->print(&mt('Creation failed.').' '.$makeresult.'<br />'.
+                      $warning);
+            $showfolder = $folder;
+        }
+        &Apache::loncommunicate::menu($r);
+	&disall($r,$showfolder);
     } elsif ($env{'form.showcommentbaseurl'}) {
 	&storedcommentlisting($r);
+    } elsif ($env{'form.folderaction'} eq 'delete') {
+        &printheader($r,'','Deleted Folder');
+        my $showfolder = '';
+        my $delresult = &deletefolder($folder);
+        if ($delresult eq 'ok') {
+            $r->print(&mt('Mail folder "[_1]" deleted.',$folder).'<br />');
+        } else {
+            $r->print(&mt('Deletion failed.').' '.$delresult.'<br />');
+            $showfolder = $folder;
+        }
+        &Apache::loncommunicate::menu($r);
+        &disall($r,$showfolder);
+    } elsif ($env{'form.folderaction'} eq 'rename') {
+        &printheader($r,'','Renamed Folder');
+        my $showfolder = $env{'form.renamed'};
+        my $renresult = &renamefolder($folder);
+        if ($renresult eq 'ok') {
+            $r->print(&mt('Mail folder "[_1]" renamed "[_2]".',$folder,$showfolder).'<br />');
+        } else {
+            $r->print(&mt('Renaming failed.').' '.$renresult.'<br />');
+            $showfolder = $folder;
+        }
+        &Apache::loncommunicate::menu($r);
+        &disall($r,$showfolder);
     } else {
 	&printheader($r,'','Display All Messages');
 	&Apache::loncommunicate::menu($r);
Index: loncom/interface/loncommunicate.pm
diff -u loncom/interface/loncommunicate.pm:1.35 loncom/interface/loncommunicate.pm:1.36
--- loncom/interface/loncommunicate.pm:1.35	Wed Nov 29 02:53:55 2006
+++ loncom/interface/loncommunicate.pm	Wed Dec  6 18:44:33 2006
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Communicate
 #
-# $Id: loncommunicate.pm,v 1.35 2006/11/29 07:53:55 raeburn Exp $
+# $Id: loncommunicate.pm,v 1.36 2006/12/06 23:44:33 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -47,7 +47,6 @@
         }   
     }
     my %lt=&Apache::lonlocal::texthash(
-'mnf' => 'Make New Folder',
 'vcm' => 'View Critical Messages',
 'smu' => 'Send Message to User(s)',
 'bmc' => "Broadcast Message to $crstype",
@@ -80,23 +79,21 @@
     }   
     $r->print(<<END);
 <table cellspacing="10" cellpadding="2">
-<tr><td bgcolor="#FFFFAA"><form method="post" action="/adm/email">
-<input type="submit" value="$lt{'mnf'}" />
-<input type="text" size="15" name="newfolder" value="" />
-</form></td>
+<tr>
 <td bgcolor="#FFFFAA">
   <b><a href="/adm/email?compose=individual">$lt{'smu'}</a></b>
-</td></tr>
-<tr><td bgcolor="#FFFFAA">
+</td>
+<td bgcolor="#FFFFAA">
   <b><a href="/adm/$env{'user.domain'}/$env{'user.name'}/_rss.html">$lt{'blog'}</a></b>
 </td>
+</tr>
 END
     if ($can_srm || !$can_dcm) {
-        $r->print('<td></td></tr>');
+        $r->print('<tr>');
     }
     if ($can_srm) {
         $r->print(<<END);
-<tr><td bgcolor="#FFFFAA">
+<td bgcolor="#FFFFAA">
     <b><a href="/adm/email?compose=group">$lt{'bmc'}</a></b>$help{'Course_Broadcast_Message'}
 </td>
 <td bgcolor="#FFFFAA">

--raeburn1165448673--