[LON-CAPA-cvs] cvs: loncom /interface lonfeedback.pm
raeburn
lon-capa-cvs@mail.lon-capa.org
Wed, 21 Jul 2004 21:47:14 -0000
This is a MIME encoded message
--raeburn1090446434
Content-Type: text/plain
raeburn Wed Jul 21 17:47:14 2004 EDT
Modified files:
/loncom/interface lonfeedback.pm
Log:
Can choose different sorting mechanism for discussion posts. Interface provided for filtering of posts for display (by poster's role, status -active/inactive, section). Choices currently have no effect (work-in-progress).
--raeburn1090446434
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20040721174714.txt"
Index: loncom/interface/lonfeedback.pm
diff -u loncom/interface/lonfeedback.pm:1.99 loncom/interface/lonfeedback.pm:1.100
--- loncom/interface/lonfeedback.pm:1.99 Fri Jul 9 19:05:52 2004
+++ loncom/interface/lonfeedback.pm Wed Jul 21 17:47:13 2004
@@ -1,7 +1,7 @@
# The LearningOnline Network
# Feedback
#
-# $Id: lonfeedback.pm,v 1.99 2004/07/09 23:05:52 raeburn Exp $
+# $Id: lonfeedback.pm,v 1.100 2004/07/21 21:47:13 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -80,7 +80,9 @@
$symb=&Apache::lonnet::symbread();
}
unless ($symb) { return ''; }
-
+ my %usernamesort = ();
+ my %namesort =();
+ my %subjectsort = ();
# backward compatibility (bulletin boards used to be 'wrapped')
my $ressymb=$symb;
if ($mode eq 'board') {
@@ -104,7 +106,8 @@
my $newpostsflag = 0;
# Retain identification of "NEW" posts identified in last display, if continuing 'previous' browsing of posts.
- &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous']);
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['previous','sortposts']);
+ my $sortposts = $ENV{'form.sortposts'};
$previous = $ENV{'form.previous'};
if ($previous > 0) {
$prevread = $previous;
@@ -184,12 +187,17 @@
my $hidden=($contrib{'hidden'}=~/\.$idx\./);
my $deleted=($contrib{'deleted'}=~/\.$idx\./);
my $origindex='0.';
- if (($contrib{$idx.':replyto'}) && ($ENV{'environment.threadeddiscussion'})) {
+ if ($contrib{$idx.':replyto'}) {
+ if ( (($ENV{'environment.threadeddiscussion'}) && (($sortposts eq '') || ($sortposts eq 'ascdate'))) || ($sortposts eq 'thread')) {
# this is a follow-up message
- $original[$idx]=$original[$contrib{$idx.':replyto'}];
- $depth[$idx]=$depth[$contrib{$idx.':replyto'}]+1;
- $origindex=$index[$contrib{$idx.':replyto'}];
- if ($depth[$idx]>$maxdepth) { $maxdepth=$depth[$idx]; }
+ $original[$idx]=$original[$contrib{$idx.':replyto'}];
+ $depth[$idx]=$depth[$contrib{$idx.':replyto'}]+1;
+ $origindex=$index[$contrib{$idx.':replyto'}];
+ if ($depth[$idx]>$maxdepth) { $maxdepth=$depth[$idx]; }
+ } else {
+ $original[$idx]=0;
+ $depth[$idx]=0;
+ }
} else {
# this is an original message
$original[$idx]=0;
@@ -231,6 +239,20 @@
$contrib{$idx.':senderdomain'});
my $sender=&mt('Anonymous');
+# Set up for sorting by subject
+ if ($contrib{$idx.':subject'} eq '') {
+ if (defined($subjectsort{'__No subject'})) {
+ push @{$subjectsort{'__No subject'}}, $idx;
+ } else {
+ @{$subjectsort{'__No subject'}} = ("$idx");
+ }
+ } else {
+ if (defined($subjectsort{$contrib{$idx.':subject'}})) {
+ push @{$subjectsort{$contrib{$idx.':subject'}}}, $idx;
+ } else {
+ @{$subjectsort{$contrib{$idx.':subject'}}} = ("$idx");
+ }
+ }
if ((!$contrib{$idx.':anonymous'}) || ($seeid)) {
$sender=&Apache::loncommon::aboutmewrapper(
$plainname,
@@ -242,6 +264,34 @@
$sender.=' ['.&mt('anonymous').'] '.
$screenname;
}
+# Set up for sorting by domain, then username
+ unless (defined($usernamesort{$contrib{$idx.':senderdomain'}})) {
+ %{$usernamesort{$contrib{$idx.':senderdomain'}}} = ();
+ }
+ if (defined($usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}})) {
+ push @{$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}}, $idx;
+ } else {
+ @{$usernamesort{$contrib{$idx.':senderdomain'}}{$contrib{$idx.':sendername'}}} = ("$idx");
+ }
+# Set up for sorting by last name, then first name
+ my %names = &Apache::lonnet::get('environment',['firstname','lastname'],
+ $contrib{$idx.':senderdomain'},$contrib{$idx.':sendername'});
+ my $lastname = $names{'lastname'};
+ my $firstname = $names{'firstname'};
+ if ($lastname eq '') {
+ $lastname = '_';
+ }
+ if ($firstname eq '') {
+ $firstname = '_';
+ }
+ unless (defined($namesort{$lastname})) {
+ %{$namesort{$lastname}} = ();
+ }
+ if (defined($namesort{$lastname}{$firstname})) {
+ push @{$namesort{$lastname}{$firstname}}, $idx;
+ } else {
+ @{$namesort{$lastname}{$firstname}} = ("$idx");
+ }
if ($seeid) {
if ($hidden) {
$sender.=' <a href="/adm/feedback?unhide='.
@@ -260,15 +310,33 @@
}
$sender.=' <a href="/adm/feedback?deldisc='.
$ressymb.':::'.$idx;
- if ($newpostsflag) {
- $sender .= '&previous='.$prevread;
- }
- $sender .= '">'.&mt('Delete').'</a>';
+ if ($newpostsflag) {
+ $sender .= '&previous='.$prevread;
+ }
+ $sender .= '">'.&mt('Delete').'</a>';
}
} else {
if ($screenname) {
$sender='<i>'.$screenname.'</i>';
}
+# Set up for sorting by domain, then username for anonymous
+ unless (defined($usernamesort{'__anon'})) {
+ %{$usernamesort{'__anon'}} = ();
+ }
+ if (defined($usernamesort{'__anon'}{'__anon'})) {
+ push @{$usernamesort{'__anon'}{'__anon'}}, $idx;
+ } else {
+ @{$usernamesort{'__anon'}{'__anon'}} = ("$idx");
+ }
+# Set up for sorting by last name, then first name for anonymous
+ unless (defined($namesort{'__anon'})) {
+ %{$namesort{'__anon'}} = ();
+ }
+ if (defined($namesort{'__anon'}{'__anon'})) {
+ push @{$namesort{'__anon'}{'__anon'}}, $idx;
+ } else {
+ @{$namesort{'__anon'}{'__anon'}} = ("$idx");
+ }
}
if (&discussion_open($status) &&
&Apache::lonnet::allowed('pch',
@@ -288,7 +356,7 @@
}
#figure out at what position this needs to print
my $thisindex=$idx;
- if ($ENV{'environment.threadeddiscussion'}) {
+ if ( (($ENV{'environment.threadeddiscussion'}) && (($sortposts eq '') || ($sortposts eq 'ascdate'))) || ($sortposts eq 'thread')) {
$thisindex=$origindex.substr('00'.$replies[$depth[$idx]],-2,2);
}
$alldiscussion{$thisindex}=$idx;
@@ -381,8 +449,20 @@
if ($newpostsflag) {
$discussion .= '&previous='.$prevread;
}
- $discussion .='">'.&mt('Chronological View').'</a> </td>';
- }
+ $discussion .='">'.&mt('Chronological View').'</a>
+ <a href= "/adm/feedback?sortfilter='.$ressymb;
+ if ($newpostsflag) {
+ $discussion .= '&previous='.$prevread;
+ }
+ $discussion .='">'.&mt('Sorting/Filtering options').'</a>  ';
+ } else {
+ $discussion .= '<td align="left">';
+ }
+ $discussion .='<a href= "/adm/feedback?export='.$ressymb;
+ if ($newpostsflag) {
+ $discussion .= '&previous='.$prevread;
+ }
+ $discussion .= '">'.&mt('Export').'?</a> </td>';
if ($newpostsflag) {
if (!$markondisp) {
$discussion .='<td align="right"><a href="/adm/feedback?markread='.$ressymb.'">'.&mt('Mark new posts as read').'</a> ';
@@ -412,7 +492,37 @@
$numhidden.' '.&mt('previously viewed posts').
'<br/></td></tr>';
}
- foreach (sort { $a <=> $b } keys %alldiscussion) {
+
+# Choose sort mechanism
+ my @showposts = ();
+ if ($sortposts eq 'descdate') {
+ @showposts = (sort { $b <=> $a } keys %alldiscussion);
+ } elsif ($sortposts eq 'thread') {
+ @showposts = (sort { $a <=> $b } keys %alldiscussion);
+ } elsif ($sortposts eq 'subject') {
+ foreach (sort keys %subjectsort) {
+ push @showposts, @{$subjectsort{$_}};
+ }
+ } elsif ($sortposts eq 'username') {
+ foreach my $domain (sort keys %usernamesort) {
+ foreach (sort keys %{$usernamesort{$domain}}) {
+ push @showposts, @{$usernamesort{$domain}{$_}};
+ }
+ }
+ } elsif ($sortposts eq 'lastfirst') {
+ foreach my $last (sort keys %namesort) {
+ foreach (sort keys %{$namesort{$last}}) {
+ push @showposts, @{$namesort{$last}{$_}};
+ }
+ }
+ } else {
+ $sortposts = 'ascdate';
+ @showposts = (sort { $a <=> $b } keys %alldiscussion);
+ }
+ foreach (@showposts) {
+ unless (($sortposts eq 'thread') || ($sortposts eq 'ascdate' && $ENV{'environment.threadeddiscussion'})) {
+ $alldiscussion{$_} = $_;
+ }
unless ($notshown{$alldiscussion{$_}} eq '1') {
if ($outputtarget ne 'tex') {
$discussion.="\n<tr>";
@@ -519,7 +629,7 @@
'<img src="/adm/lonMisc/chat.gif" border="0" />'.
&mt('Post Discussion').'</a></td></tr></table>';
}
- }
+ }
}
return $discussion;
}
@@ -770,6 +880,148 @@
return;
}
+sub print_sortfilter_options {
+ my ($r,$symb,$previous,$feedurl) = @_;
+ # backward compatibility (bulletin boards used to be 'wrapped')
+ if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
+ $feedurl=~s|^/adm/wrapper||;
+ }
+ my @sections = ();
+ my $section_sel = '';
+ my $numsections = 0;
+ my $numvisible = 5;
+ my ($classlist) = &Apache::loncoursedata::get_classlist(
+ $ENV{'request.course.id'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.domain'},
+ $ENV{'course.'.$ENV{'request.course.id'}.'.num'});
+
+ my $sec_index = &Apache::loncoursedata::CL_SECTION();
+ my $status_index = &Apache::loncoursedata::CL_STATUS();
+ my %sectioncount = ();
+ while (my ($student,$data) = each %$classlist) {
+ my ($section,$status) = ($data->[$sec_index],
+ $data->[$status_index]);
+ unless ($section eq '' || $section =~ /^\s*$/) {
+ if (!defined($sectioncount{$section})) {
+ $sectioncount{$section} = 1;
+ $numsections ++;
+ } else {
+ $sectioncount{$section} ++;
+ }
+ }
+ }
+
+ if ($ENV{'request.course.sec'} !~ /^\s*$/) {
+ @sections = ($ENV{'request.course.sec'});
+ $numvisible = 1;
+ } else {
+ @sections = sort {$a cmp $b} keys(%sectioncount);
+ unshift(@sections,'all'); # Put 'all' at the front of the list
+ if ($numsections < 4) {
+ $numvisible = $numsections + 1;
+ }
+ }
+ foreach (@sections) {
+ $section_sel .= " <option value=\"$_\" />$_\n";
+ }
+
+ my $function = &Apache::loncommon::get_users_function();
+ my $tabcolor = &Apache::loncommon::designparm($function.'.tabbg',
+ $ENV{'user.domain'});
+ my $bodytag=&Apache::loncommon::bodytag('Discussion options',
+ '','');
+ my %lt = &Apache::lonlocal::texthash(
+ 'diso' => 'Discussion sorting and filtering options',
+ 'diop' => 'Display Options',
+ 'curr' => 'Current setting ',
+ 'actn' => 'Action',
+ 'prca' => 'Options can be set that control the sort order of the posts, in
+addition to which posts are displayed.',
+ 'soor' => 'Sort order',
+ 'disp' => 'Specific user roles',
+ 'actv' => 'Specific role status',
+ 'spse' => 'Specific sections',
+ 'psub' => 'Pick specific users (by name)',
+ 'shal' => 'Show a list of current posters',
+ 'yhni' => 'You have not indicated that you do not wish to change any of the discussion settings',
+ 'ywbr' => 'You will be returned to the previous page if you click OK.'
+ );
+ $r->print(<<END);
+<html>
+<head>
+<title>$lt{'diso'}</title>
+<meta http-equiv="pragma" content="no-cache" />
+</head>
+$bodytag
+<form name="modifyshown" method="post" action="/adm/feedback">
+<b>$lt{'diso'}</b><br/> $lt{'prca'}
+<br /><br />
+<table border="0">
+ <tr>
+ <td><b>$lt{'soor'}</b></td>
+ <td> </td>
+ <td><b>$lt{'disp'}</b></td>
+ <td> </td>
+ <td><b>$lt{'actv'}</b></td>
+ <td> </td>
+ <td><b>$lt{'spse'}</b></td>
+ <td> </td>
+ <td><b>$lt{'psub'}</b></td>
+ </tr>
+ <tr>
+ <td>
+ <select name="sortposts">
+ <option value="ascdate" />Date order - oldest first
+ <option value="descdate" />Date order - newest first
+ <option value="thread" />Threaded
+ <option value="subject" />By subject
+ <option value="username" />By domain and username
+ <option value="lastfirst" />By last name, first name
+ </select>
+ </td>
+ <td> </td>
+ <td>
+ <select name="filterposts" multiple="true" size="5">
+ <option value="all" />All users
+ <option value="st" />Students
+ <option value="cc" />Course Coordinators
+ <option value="in" />Instructors
+ <option value="ta" />TAs
+ <option value="pr" />Exam proctors
+ <option value="cr" />Custom roles
+ </select>
+ </td>
+ <td> </td>
+ <td>
+ <select name="statusfilter">
+ <option value="all" />Roles of any status
+ <option value="act" />Only active roles
+ <option value="ina" />Only inactive roles
+ </select>
+ </td>
+ <td> </td>
+ <td>
+ <select name="sectionpick" multiple="true" size="$numvisible">
+ $section_sel
+ </select>
+ </td>
+ <td> </td>
+ <td><input type="checkbox" name="posterlist" value="$symb" />$lt{'shal'}</td>
+ </tr>
+</table>
+<br />
+<br />
+<input type="hidden" name="previous" value="$previous" />
+<input type="hidden" name="applysort" value="$symb" />
+<input type="button" name="sub" value="Store Changes" onClick="javascript:document.modifyshown.submit()" />
+<br />
+<br />
+</form>
+</body>
+</html>
+END
+}
+
sub fail_redirect {
my ($r,$feedurl) = @_;
if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
@@ -788,14 +1040,14 @@
}
sub redirect_back {
- my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous) = @_;
+ my ($r,$feedurl,$typestyle,$sendsomething,$sendposts,$status,$previous,$sort) = @_;
+ my $sorttag = '';
my $prevtag = '';
my $qrystr = '';
# backward compatibility (bulletin boards used to be 'wrapped')
if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
$feedurl=~s|^/adm/wrapper||;
}
-
if ($feedurl=~/^\/adm\//) { $feedurl.='?register=1' };
if ($previous > 0) {
$qrystr = 'previous='.$previous;
@@ -806,6 +1058,15 @@
}
$prevtag = '<input type="hidden" name="previous" value="'.$previous.'" />';
}
+ if (defined($sort)) {
+ my $sortqry = 'sortposts='.$sort;
+ if (($feedurl =~ /\?register=1/) || ($feedurl =~ /\?previous=/)) {
+ $feedurl .= '&'.$sortqry;
+ } else {
+ $feedurl .= '?'.$sortqry;
+ }
+ $sorttag = '<input type="hidden" name="sortposts" value="'.$sort.'" />';
+ }
$r->print (<<ENDREDIR);
<html>
<head>
@@ -820,6 +1081,7 @@
<font color="red">$status</font>
<form name="reldt" action="$feedurl" target="loncapaclient">
$prevtag
+$sorttag
</form>
</body>
</html>
@@ -1136,8 +1398,38 @@
# --------------------------- Get query string for limited number of parameters
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['hide','unhide','deldisc','postdata','preview','replydisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp','modifydisp','changes','navmaps','navurl']);
- if ($ENV{'form.navmaps'}) {
+ ['hide','unhide','deldisc','postdata','preview','replydisc','threadedon','threadedoff','onlyunread','allposts','previous','markread','markonread','markondisp','modifydisp','changes','navmaps','navurl','sortfilter','sortposts','applysort']);
+ if ($ENV{'form.applysort'}) {
+ &Apache::loncommon::content_type($r,'text/html');
+ $r->send_http_header;
+ my $symb=$ENV{'form.applysort'};
+ my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
+ my $previous=$ENV{'form.previous'};
+ my $sort = $ENV{'form.sortposts'};
+ my $filter = $ENV{'form.filterposts'};
+ my $statusfilter = $ENV{'form.statusfilter'};
+ my $secpick = $ENV{'form.sectionpick'};
+ my $feedurl = &Apache::lonnet::clutter($url);
+ # backward compatibility (bulletin boards used to be 'wrapped')
+ if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
+ $feedurl=~s|^/adm/wrapper||;
+ }
+ &redirect_back($r,$feedurl,&mt('Changed sort/filter').'<br />','0','0','',$previous,$sort,$filter,$secpick);
+ return OK;
+ } elsif ($ENV{'form.sortfilter'}) {
+ &Apache::loncommon::content_type($r,'text/html');
+ $r->send_http_header;
+ my $symb=$ENV{'form.sortfilter'};
+ my ($map,$ind,$url)=&Apache::lonnet::decode_symb($symb);
+ my $previous=$ENV{'form.previous'};
+ my $feedurl = &Apache::lonnet::clutter($url);
+ # backward compatibility (bulletin boards used to be 'wrapped')
+ if ($feedurl=~m|^/adm/wrapper/adm/.*/bulletinboard$|) {
+ $feedurl=~s|^/adm/wrapper||;
+ }
+ &print_sortfilter_options($r,$symb,$previous,$feedurl);
+ return OK;
+ } elsif ($ENV{'form.navmaps'}) {
my %discinfo = ();
my @resources = ();
if ($ENV{'form.navmaps'} =~ /:/) {
--raeburn1090446434--