--- loncom/interface/lonmsgdisplay.pm 2006/12/08 20:32:36 1.51
+++ loncom/interface/lonmsgdisplay.pm 2007/04/22 02:25:36 1.69
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines for messaging display
#
-# $Id: lonmsgdisplay.pm,v 1.51 2006/12/08 20:32:36 raeburn Exp $
+# $Id: lonmsgdisplay.pm,v 1.69 2007/04/22 02:25:36 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,12 +33,13 @@ package Apache::lonmsgdisplay;
=head1 NAME
-Apache::lonmsg: supports internal messaging
+Apache::lonmsgdisplay: supports internal messaging
=head1 SYNOPSIS
-lonmsg provides routines for sending messages, receiving messages, and
-a handler to allow users to read, send, and delete messages.
+lonmsgdisplay provides a handler to allow users to read, send,
+and delete messages, and to create and delete message folders,
+and to move messages between folders.
=head1 OVERVIEW
@@ -93,25 +94,6 @@ addresses on their B screen, but g
are much more useful than traditional email can be made to be, even
with HTML support.
-Right now, this document will cover just how to send a message, since
-it is likely you will not need to programmatically read messages,
-since lonmsg already implements that functionality.
-
-The routines used to package messages and unpackage messages are not
-only used by lonmsg when creating/extracting messages for LON-CAPA's
-internal messaging system, but also by lonnotify.pm which is available
-for use by Domain Coordinators to broadcast standard e-mail to specified
-users in their domain. The XML packaging used in the two cases is very
-similar. The differences are the use of $uname and
-$udom in stored internal messages, compared
-with $email in stored
-Domain Coordinator e-mail for the storage of information about
-recipients of the message/e-mail.
-
-=head1 FUNCTIONS
-
-=over 4
-
=cut
use strict;
@@ -119,6 +101,7 @@ use Apache::lonnet;
use HTML::TokeParser();
use Apache::Constants qw(:common);
use Apache::loncommon();
+use Apache::lonhtmlcommon();
use Apache::lontexconvert();
use HTML::Entities();
use Apache::lonlocal;
@@ -132,16 +115,16 @@ use LONCAPA;
# Querystring component with sorting type
my $sqs;
my $startdis;
-my $interdis;
# ============================================================ List all folders
sub folderlist {
- my $folder=shift;
+ my ($folder,$msgstatus) = @_;
my %lt = &Apache::lonlocal::texthash(
actn => 'Action',
fold => 'Folder',
show => 'Show',
+ status => 'Message Status',
go => 'Go',
nnff => 'New Name for Folder',
newn => 'New Name',
@@ -160,6 +143,10 @@ sub folderlist {
);
$actions{'select_form_order'} = ['view','rename','delete'];
+ my %statushash = &get_msgstatus_types();
+
+ $statushash{'select_form_order'} = ['','new','read','replied','forwarded'];
+
my %permfolders = &get_permanent_folders();
my $permlist = join("','",sort(keys(%permfolders)));
my ($permlistkeys,$permlistvals);
@@ -173,6 +160,7 @@ sub folderlist {
my %userfolders;
foreach my $key (keys(%gotfolders)) {
+ $key =~ s/(['"])/\$1/g; #' stupid emacs
$userfolders{$key} = $key;
}
my @userorder = sort(keys(%userfolders));
@@ -180,7 +168,7 @@ sub folderlist {
my $folderlist = join("','",@userorder);
$folderlist .= "','".$permlistvals;
- $formhash{'select_form_order'} = ['','critical','new',@userorder,'sent','trash'];
+ $formhash{'select_form_order'} = ['','critical',@userorder,'sent','trash'];
my $output = qq||;
+ my %show = ('select_form_order' => [10,20,50,100,200],
+ map {$_=>$_} (10,20,50,100,200));
+
+
$output .= '
':'');
+ ($folder=~/^critical/?'':'');
return $output;
}
@@ -269,25 +261,43 @@ sub get_permanent_folders {
my %permfolders =
&Apache::lonlocal::texthash('' => 'INBOX',
'trash' => 'TRASH',
- 'new' => 'New Messages Only',
'critical' => 'Critical',
'sent' => 'Sent Messages',
);
return %permfolders;
}
+sub get_msgstatus_types {
+ my %statushash = &Apache::lonlocal::texthash(
+ '' => 'Any',
+ new => 'Unread',
+ read => 'Read',
+ replied => 'Replied to',
+ forwarded => 'Forwarded',
+ );
+ return %statushash;
+}
+
sub scrollbuttons {
- my ($start,$maxdis,$first,$finish,$total)=@_;
+ my ($start,$maxdis,$first,$finish,$total,$msgstatus)=@_;
unless ($total>0) { return ''; }
$start++; $maxdis++;$first++;$finish++;
+
+ my %statushash = &get_msgstatus_types();
+ my $status;
+ if ($msgstatus eq '') {
+ $status = &mt('All');
+ } else {
+ $status = $statushash{$msgstatus};
+ }
return
- &mt('Page').': '.
+ ''.&mt('Page').': '.
''.
''.
' of '.$maxdis.
''.
' '.
- &mt('Showing messages [_1] through [_2] of [_3]',$first,$finish,$total).'';
+ &mt('[_1] messages: showing messages [_2] through [_3] of [_4].',$status,$first,$finish,$total).'';
}
# =============================================================== Status Change
@@ -354,18 +364,18 @@ sub deletefolder {
my ($folder)=@_;
my %permfolders = &get_permanent_folders();
if (defined($permfolders{$folder})) {
- return &mt('The folder [_1] may not be deleted',$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.',
+ 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.').
+ return &mt('The folder "[_1]" contains messages so it may not be deleted.',$folder).
' '.
&mt('Delete or move the messages to a different folder first.');
}
@@ -744,10 +754,9 @@ $content{'sendername'}.':'.
}
sub sortedmessages {
- my ($blocked,$startblock,$endblock,$numblocked,$folder) = @_;
+ my ($blocked,$startblock,$endblock,$numblocked,$folder,$msgstatus) = @_;
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;
@@ -762,9 +771,10 @@ sub sortedmessages {
foreach my $msgid (@messages) {
my $esc_msgid=&escape($msgid);
- my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid)=
+ my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$fromcid,$processid,$symb,$error) =
&Apache::lonmsg::unpackmsgid($esc_msgid,$folder,undef,
\%status_cache);
+ next if ($msgstatus ne '' && $msgstatus ne $status);
my $description = &get_course_desc($fromcid,\%descriptions);
my @temp1 = ($sendtime,$shortsubj,$fromname,$fromdomain,$status,
$esc_msgid,$description);
@@ -860,148 +870,119 @@ sub get_course_desc {
}
}
-# ======================================================== Display new messages
-
-
-sub disnew {
- my $r=shift;
- my %lt=&Apache::lonlocal::texthash(
- 'nm' => 'New Messages',
- 'su' => 'Subject',
- 'co' => 'Course',
- 'da' => 'Date',
- 'us' => 'Username',
- 'op' => 'Open',
- 'do' => 'Domain'
- );
- my @msgids = sort(&Apache::lonnet::getkeys('nohist_email'));
- my @newmsgs;
- my %setters = ();
- my %blocked = ();
- my $numblocked = 0;
- # Check for blocking of display because of scheduled online exams.
- my ($startblock,$endblock) = &Apache::loncommon::blockcheck(\%setters,'com');
- my %status_cache =
- &Apache::lonnet::get('email_status',\@msgids);
- my %descriptions;
- foreach my $id (@msgids) {
- my $msgid=&escape($id);
- my ($sendtime,$shortsubj,$fromname,$fromdom,$status,$fromcid)=
- &Apache::lonmsg::unpackmsgid($msgid,undef,undef,\%status_cache);
- if (defined($sendtime) && $sendtime!~/error/) {
- my $description = &get_course_desc($fromcid,\%descriptions);
- my $numsendtime = $sendtime;
- $sendtime = &Apache::lonlocal::locallocaltime($sendtime);
- if ($status eq 'new') {
- if ($numsendtime >= $startblock && ($numsendtime <= $endblock && $endblock > 0) ) {
- $blocked{$id} = 'ON';
- $numblocked ++;
- } else {
- push(@newmsgs, {
- msgid => $msgid,
- sendtime => $sendtime,
- shortsub => $shortsubj,
- from => $fromname,
- fromdom => $fromdom,
- course => $description,
- });
- }
- }
- }
- }
- if ($#newmsgs >= 0) {
- $r->print(<$lt{'nm'}
-
-
$lt{'da'}
$lt{'us'}
$lt{'do'}
$lt{'su'}
$lt{'co'}
-TABLEHEAD
- foreach my $msg (@newmsgs) {
- $r->print(<<"ENDLINK");
-
-ENDLINK
- foreach my $item ('sendtime','from','fromdom','shortsub','course') {
- $r->print("
$msg->{$item}
");
- }
- $r->print("
");
- }
- $r->print('
');
- } elsif ($numblocked == 0) {
- $r->print("
".&mt('You have no unread messages')."
");
- }
- if ($numblocked > 0) {
- my $beginblock = &Apache::lonlocal::locallocaltime($startblock);
- my $finishblock = &Apache::lonlocal::locallocaltime($endblock);
- $r->print('
'.&mt('You have [quant,_1,blocked unread message,blocked unread messages].',$numblocked).'
'."\n".
- &mt('[quant,_1,message is,messages are] not viewable because display of LON-CAPA messages sent to you by other students between [_2] and [_3] is currently being blocked because of online exams.',$numblocked,$beginblock,$finishblock).' '."\n".
- &Apache::loncommon::build_block_table($startblock,$endblock,
- \%setters));
- }
-}
-
-
# ======================================================== Display all messages
sub disall {
- my ($r,$folder)=@_;
- $r->print(&folderlist($folder));
- if ($folder eq 'new') {
- &disnew($r);
- } elsif ($folder eq 'critical') {
+ my ($r,$folder,$msgstatus)=@_;
+ my %saveable = ('folder' => 'scalar',
+ 'msgstatus' => 'scalar',
+ 'sortedby' => 'scalar',
+ 'interdis' => 'scalar',
+ );
+ &Apache::loncommon::store_settings('user','mail',\%saveable);
+ &Apache::loncommon::restore_settings('user','mail',\%saveable);
+ $folder ||= $env{'form.folder'};
+ $msgstatus ||= $env{'form.msgstatus'};
+ $env{'form.interdis'} ||= 20;
+
+ $r->print(&folderlist($folder,$msgstatus));
+ if ($folder eq 'critical') {
&discrit($r);
} else {
- &disfolder($r,$folder);
+ &disfolder($r,$folder,$msgstatus);
}
}
# ============================================================ Display a folder
sub disfolder {
- my ($r,$folder)=@_;
+ my ($r,$folder,$msgstatus)=@_;
+ my %statushash = &get_msgstatus_types();
my %blocked = ();
my %setters = ();
my $numblocked = 0;
my ($startblock,$endblock) = &Apache::loncommon::blockcheck(\%setters,'com');
+ my %lt = &Apache::lonlocal::texthash(
+ sede => 'Select a destination folder to which the messages will be moved.',
+ nome => 'No messages have been selected to apply ths action to.',
+ chec => 'Check the checkbox for at least one message.',
+ );
+ my $jscript = &Apache::loncommon::check_uncheck_jscript();
$r->print(<
- function checkall() {
- for (i=0; i 0) {
+ for (var i=0; i
ENDDISHEADER
+
my $fsqs='&folder='.$folder;
- my @temp=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder);
+ my @temp=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder,$msgstatus);
my $totalnumber=$#temp+1;
- unless ($totalnumber>0) {
- $r->print('
'.&mt('Empty Folder').'
');
+ if ($totalnumber < 1) {
+ if ($msgstatus eq '') {
+ $r->print('
'.&mt('You have not replied to any messages in this folder.').'
');
+ } else {
+ $r->print('
'.&mt('There are no '.lc($statushash{$msgstatus}).' messages in this folder.').'
');
+ }
+ if ($numblocked > 0) {
+ $r->print(&blocked_in_folder($numblocked,$startblock,$endblock,
+ \%setters));
+ }
return;
}
- unless ($interdis) {
- $interdis=20;
- }
+ my $interdis = $env{'form.interdis'};
my $number=int($totalnumber/$interdis);
+ if ($totalnumber%$interdis == 0) {
+ $number--;
+ }
+
if (($startdis<0) || ($startdis>$number)) { $startdis=$number; }
my $firstdis=$interdis*$startdis;
if ($firstdis>$#temp) { $firstdis=$#temp-$interdis+1; }
my $lastdis=$firstdis+$interdis-1;
if ($lastdis>$#temp) { $lastdis=$#temp; }
- $r->print(&scrollbuttons($startdis,$number,$firstdis,$lastdis,$totalnumber));
+ $r->print(&scrollbuttons($startdis,$number,$firstdis,$lastdis,$totalnumber,$msgstatus));
$r->print('');
+ $r->print('');
if ($numblocked > 0) {
- my $beginblock = &Apache::lonlocal::locallocaltime($startblock);
- my $finishblock = &Apache::lonlocal::locallocaltime($endblock);
- $r->print('
'.
- &mt('[quant,_1,message is, messages are] not viewable because display of LON-CAPA messages sent to you by other students between [_2] and [_3] is currently being blocked because of online exams.',$numblocked,$beginblock,$finishblock));
- $r->print(&Apache::loncommon::build_block_table($startblock,$endblock,
- \%setters));
+ $r->print(&blocked_in_folder($numblocked,$startblock,$endblock,
+ \%setters));
}
}
+sub blocked_in_folder {
+ my ($numblocked,$startblock,$endblock,$setters) = @_;
+ my $beginblock = &Apache::lonlocal::locallocaltime($startblock);
+ my $finishblock = &Apache::lonlocal::locallocaltime($endblock);
+ my $output = '
'.
+ &mt('[quant,_1,message is, messages are] not viewable because display of LON-CAPA messages sent to you by other students between [_2] and [_3] is currently being blocked because of online exams.',$numblocked,$beginblock,$finishblock);
+ $output .= &Apache::loncommon::build_block_table($startblock,$endblock,
+ $setters);
+ return $output;
+}
+
# ============================================================== Compose output
sub compout {
- my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder,$dismode)=@_;
+ my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder,$dismode,
+ $multiforward)=@_;
my $suffix=&Apache::lonmsg::foldersuffix($folder);
my ($cdom,$cnum,$group,$refarg);
if (exists($env{'form.group'})) {
@@ -1145,6 +1180,13 @@ sub compout {
} elsif ($replycrit) {
$r->print('
'.&mt('Replying to a Critical Message').'
');
$replying=$replycrit;
+ } elsif ($multiforward) {
+ &Apache::lonhtmlcommon::add_breadcrumb
+ ({href=>"/adm/email?folder=".&escape($folder),
+ text=>"Display All Messages"});
+ &printheader($r,'/adm/email?compose=multiforward',
+ 'Forwarding Multiple Messages');
+ $r->print(&mt('Each of the [quant,_1,message] you checked will be forwarded to the recipient(s) you select below.',$multiforward).' ');
} else {
&printheader($r,'/adm/email?compose=upload',
'Distribute from Uploaded File');
@@ -1161,6 +1203,7 @@ sub compout {
'sb' => 'Subject',
'ca' => 'Cancel',
'ma' => 'Mail',
+ 'msg' => 'Messages',
'gen' => 'Generate messages from a file',
'gmt' => 'General message text',
'tff' => 'The file format for the uploaded portion of the message is',
@@ -1262,24 +1305,49 @@ sub compout {
}
}
my $latexHelp = Apache::loncommon::helpLatexCheatsheet();
- if ($broadcast ne 'upload') {
- $r->print(<<"ENDCOMP");
-
$lt{'ad'}: username:domain,username:domain, ...
-
-
-
$lt{'sb'}:
-
+ my $subj_size;
+ if ($multiforward) {
+ $r->print(&additional_rec_row(\%lt));
+ $r->print('
'.
+ &mt('Unless you choose otherwise:').'
'.
+ &mt("The subject in each forwarded message will be 'Forwarding:' followed by the original subject.").'
'.
+ &mt("The message itself will begin with a first line: 'Forwarded message from' followed by the original sender's name.").'
';
+ return $output;
+}
+
sub retrieve_instructor_comments {
my ($user,$domain)=@_;
my $target=$env{'form.grade_target'};
@@ -1835,7 +1932,7 @@ sub blocktype_text {
# ----------------------------------------------------------- Display a message
sub displaymessage {
- my ($r,$msgid,$folder)=@_;
+ my ($r,$msgid,$folder,$msgstatus)=@_;
my $suffix=&Apache::lonmsg::foldersuffix($folder);
my %blocked = ();
my %setters = ();
@@ -1844,14 +1941,16 @@ sub displaymessage {
# info to generate "next" and "previous" buttons and check if message is blocked
my ($startblock,$endblock) = &Apache::loncommon::blockcheck(\%setters,'com');
- my @messages=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder);
+ my @messages=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked,$folder,$msgstatus);
if ( $blocked{$msgid} eq 'ON' ) {
&printheader($r,'/adm/email',&mt('Display a Message'));
$r->print(&mt('You attempted to display a message that is currently blocked because you are enrolled in one or more courses for which there is an ongoing online exam.'));
&build_block_table($r,$startblock,$endblock,\%setters);
return;
}
- &statuschange($msgid,'read',$folder);
+ if ($msgstatus eq '') {
+ &statuschange($msgid,'read',$folder);
+ }
my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]);
my %content=&Apache::lonmsg::unpackagemsg($message{$msgid});
@@ -1880,7 +1979,6 @@ sub displaymessage {
'
');
&Apache::loncommunicate::menu($r);
- &disall($r,($folder?$folder:$dismode));
+ &disall($r,($folder?$folder:$dismode),$msgstatus);
} elsif ($env{'form.markunread'}) {
&printheader($r,'','Marked Message as Unread');
&statuschange($env{'form.markunread'},'new');
&Apache::loncommunicate::menu($r);
- &disall($r,($folder?$folder:$dismode));
+ &disall($r,($folder?$folder:$dismode),$msgstatus);
} elsif ($env{'form.compose'}) {
&compout($r,'','',$env{'form.compose'});
} elsif ($env{'form.recordftf'}) {
@@ -2425,7 +2627,63 @@ sub handler {
} elsif ($env{'form.block'}) {
&examblock($r,$env{'form.block'});
} elsif ($env{'form.sendmail'}) {
- &sendoffmail($r,$folder);
+ if ($env{'form.multiforward'}) {
+ &printheader($r,'','Messages being sent.');
+ my $fixed_subj = $env{'form.subject'};
+ my $suffix=&Apache::lonmsg::foldersuffix($folder);
+ my (%sendresult,%forwardok,%forwardfail,$fwdcount);
+ my @to_forward = &Apache::loncommon::get_env_multiple('form.delmark');
+ foreach my $item (@to_forward) {
+ my $msgid=&unescape($item);
+ my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]);
+ my %content=&Apache::lonmsg::unpackagemsg($message{$msgid},1);
+ if ($env{'form.showorigsubj'}) {
+ $env{'form.subject'} = $fixed_subj.$content{'subject'};
+ } else {
+ $env{'form.subject'} = '';
+ }
+ my $uname = $content{'sendername'};
+ my $udom = $content{'senderdomain'};
+ &statuschange($msgid,'forwarded',$folder);
+ if ($env{'form.showorigsender'}) {
+ $env{'form.message'} = $env{'form.msgheader'}.' '.
+ &Apache::loncommon::plainname($uname,$udom).' ('.
+ $uname.':'.$udom.')';
+ }
+ $env{'form.message'} .= "\n\n-- Forwarded message --\n\n".
+ $content{'message'};
+ $fwdcount ++;
+ $r->print($fwdcount.': ');
+ $sendresult{$msgid} = &sendoffmail($r,$folder);
+ $r->print(' ');
+ }
+ foreach my $key (keys(%sendresult)) {
+ if ($sendresult{$key} =~/^(\s*(?:ok|con_delayed)\s*)*$/) {
+ $forwardok{$key} = $sendresult{$key};
+ } else {
+ $forwardfail{$key} = $sendresult{$key};
+ }
+ }
+ if (keys(%forwardok) > 0) {
+ my $count = keys(%forwardok);
+ $r->print(' '.
+ &mt('[quant,_1,message] forwarded.',$count).
+ '');
+ }
+ if (keys(%forwardfail) > 0) {
+ my $count = keys(%forwardfail);
+ $r->print('
'.
+ &mt('Could not forward [quant,_1,message].',$count).
+ ' ');
+ foreach my $key (keys(%forwardfail)) {
+ $r->print(&mt('Could not deliver forwarded message.').' '.
+ &mt('The recipient addresses may need to be corrected').' ('.$forwardfail{$key}.').