[LON-CAPA-cvs] cvs: doc /loncapafiles loncapafiles.lpml loncom/homework grades.pm inputtags.pm lonhomework.pm structuretags.pm loncom/html/res/adm/pages viewuser.png loncom/interface loncommon.pm loncourseuser.pm lonmenu.pm
raeburn
raeburn at source.lon-capa.org
Sat Apr 1 23:16:31 EDT 2023
raeburn Sun Apr 2 03:16:31 2023 EDT
Added files:
/loncom/interface loncourseuser.pm
/loncom/html/res/adm/pages viewuser.png
Modified files:
/loncom/interface lonmenu.pm loncommon.pm
/loncom/homework inputtags.pm structuretags.pm lonhomework.pm
grades.pm
/doc/loncapafiles loncapafiles.lpml
Log:
- Bug 6979
- Shortcut to student's view of problem etc. from 'View As' item in Functions
menu above problem.
- Part of code in &submission() subroutine in grades.pm moved to separate
subroutine -- &show_last_submission() which can be called by &view_as_user(),
which in turn is called from lonhomework.pm
-------------- next part --------------
Index: loncom/interface/lonmenu.pm
diff -u loncom/interface/lonmenu.pm:1.529 loncom/interface/lonmenu.pm:1.530
--- loncom/interface/lonmenu.pm:1.529 Sat Oct 29 14:47:00 2022
+++ loncom/interface/lonmenu.pm Sun Apr 2 03:16:26 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines to control the menu
#
-# $Id: lonmenu.pm,v 1.529 2022/10/29 14:47:00 raeburn Exp $
+# $Id: lonmenu.pm,v 1.530 2023/04/02 03:16:26 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1062,6 +1062,69 @@
'Folder/Page Content');
}
# End modifiable folder/page container check
+
+#
+# Determine whether to show View As button for shortcut to display problem, answer, and submissions
+#
+
+ if (($env{'request.symb'} ne '') &&
+ ($env{'request.filename'}=~/$LONCAPA::assess_re/) &&
+ (($perms{'mgr'}) || ($perms{'vgr'}))) {
+ my ($viewas,$text,$change,$visibility,$vuname,$vudom,$vid,$leftvis,$defdom,$righticon);
+ my %lt = &Apache::lonlocal::texthash(
+ view => 'View',
+ upda => 'Update',
+ );
+ if ($env{'request.user_in_effect'} =~ /^($match_username):($match_domain)$/) {
+ ($vuname,$vudom) = ($1,$2);
+ $vid = (&Apache::lonnet::idrget($vudom,$vuname))[1];
+ $viewas = $env{'request.user_in_effect'};
+ $text = $lt{'upda'};
+ $change = 'off';
+ $visibility = 'inline';
+ $leftvis = 'none';
+ $defdom = $vudom;
+ $righticon = '✖';
+ } else {
+ $text = $lt{'view'};
+ $change = 'on';
+ $visibility = 'none';
+ $leftvis = 'inline';
+ $defdom = $cdom;
+ }
+ my $sellink = &Apache::loncommon::selectstudent_link('userview','vuname','vudom');
+ my $selscript=&Apache::loncommon::studentbrowser_javascript();
+ my $shownsymb = &HTML::Entities::encode(&Apache::lonenc::check_encrypt($env{'request.symb'}),'<>&"');
+ my $input = &mt('User: [_1] or ID: [_2] at: [_3]',
+ '<input name="vuname" type="text" size="8" value="'.$vuname.'" />',
+ '<input name="vid" type="text" size="8" value="'.$vid.'" />',
+ &Apache::loncommon::select_dom_form($defdom,'vudom')).
+ '<input name="LC_viewas" type="hidden" value="'.$viewas.'" />',
+ '<input name="symb" type="hidden" value="'.$shownsymb.'" />';
+ my $chooser = <<END;
+$selscript
+<a href="javascript:toggleViewAsUser('$change');" class="LC_menubuttons_link">
+<span id="usexpand" class="LC_menubuttons_inline_text" style="display:$leftvis">► </span>
+</a>
+<fieldset id="LC_selectuser" style="display:$visibility">
+<form name="userview" action="" method="post" onsubmit="event.preventDefault(); return validCourseUser(this,'$change');">
+<span class="LC_menubuttons_inline_text LC_nobreak">
+$input
+$sellink
+</span>
+ <input type="submit" value="$text" />
+</form>
+</fieldset>
+<a href="javascript:toggleViewAsUser('$change');" class="LC_menubuttons_link">
+<span id="uscollapse" class="LC_menubuttons_inline_text">$righticon</span>
+</a>
+END
+ &switch('','',7,5,'viewuser.png','View As','user[_1]',
+ 'toggleViewAsUser('."'$change'".')',
+ 'View As','','',$chooser);
+ }
+# End view as user check
+
}
# End course context
@@ -1641,7 +1704,7 @@
'advtools', @funcs[61,73,74,71,72]);
} else {
&Apache::lonhtmlcommon::add_breadcrumb_tool(
- 'advtools', @funcs[61,71,72,73,74,92]);
+ 'advtools', @funcs[61,71,72,73,74,75,92]);
}
} elsif ($env{'request.noversionuri'} eq '/adm/viewclasslist') {
&Apache::lonhtmlcommon::add_breadcrumb_tool(
@@ -1663,7 +1726,7 @@
# The javascript is usually similar to "go('/adm/roles')" or "cstrgo(..)".
sub switch {
- my ($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat,$nobreak)=@_;
+ my ($uname,$udom,$row,$col,$img,$top,$bot,$act,$desc,$cat,$nobreak,$form)=@_;
$act=~s/\$uname/$uname/g;
$act=~s/\$udom/$udom/g;
$top=&mt($top);
@@ -1714,7 +1777,7 @@
} else {
$inlineremote[$idx] =
'<a title="'.$desc.'" class="LC_menubuttons_link" href="javascript:'.$act.';">'.$pic.
- '<span class="LC_menubuttons_inline_text">'.$top.' </span></a>';
+ '<span class="LC_menubuttons_inline_text">'.$top.' </span></a>'.$form;
}
}
return '';
@@ -2255,6 +2318,79 @@
}
}
+sub view_as_js {
+ my ($url,$symb) = @_;
+ my %lt = &Apache::lonlocal::texthash(
+ ente => 'Enter a username or a student/employee ID',
+ info => 'Information you entered does not match a valid course user',
+ );
+ &js_escape(\%lt);
+ return <<"END";
+
+function toggleViewAsUser(change) {
+ var seluserid = document.getElementById('LC_selectuser');
+ var currstyle = seluserid.style.display;
+ if (change == 'off') {
+ document.userview.elements['LC_viewas'].value = '';
+ document.userview.elements['vuname'].value = '';
+ document.userview.elements['vid'].value = '';
+ document.userview.submit();
+ return;
+ }
+ if (currstyle == 'inline') {
+ seluserid.style.display = 'none';
+ document.getElementById('usexpand').innerHTML='► ';
+ document.getElementById('uscollapse').innerHTML='';
+ } else {
+ seluserid.style.display = 'inline';
+ document.getElementById('usexpand').innerHTML='';
+ document.getElementById('uscollapse').innerHTML='◄ ';
+ }
+ return;
+}
+
+function validCourseUser(form,change) {
+ var possuname = form.elements['vuname'].value;
+ var possuid = form.elements['vid'].value;
+ var possudom = form.elements['vudom'].options[form.elements['vudom'].selectedIndex].value;
+ if ((possuname == '') && (possuid == '')) {
+ if (change == 'off') {
+ form.elements['LC_viewas'].value = '';
+ form.submit();
+ } else {
+ alert("$lt{'ente'}");
+ }
+ return;
+ }
+ var http = new XMLHttpRequest();
+ var url = "/adm/courseuser";
+ var params = "uname="+possuname+"&uid="+possuid+"&udom="+possudom;
+ http.open("POST", url, true);
+ http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
+ http.onreadystatechange = function() {
+ if (http.readyState == 4 && http.status == 200) {
+ var data = JSON.parse(http.responseText);
+ if (Array.isArray(data.match)) {
+ var len = data.match.length;
+ if (len == 2) {
+ if (data.match[0] != '' && data.match[1] != '') {
+ form.elements['LC_viewas'].value = data.match[0]+':'+data.match[1];
+ form.submit();
+ }
+ } else {
+ alert("$lt{'info'}");
+ }
+ }
+ }
+ return;
+ }
+ http.send(params);
+ return false;
+}
+
+END
+}
+
sub utilityfunctions {
my ($httphost) = @_;
my $currenturl=&Apache::lonnet::clutter(&Apache::lonnet::fixversion((split(/\?/,$env{'request.noversionuri'}))[0]));
@@ -2296,6 +2432,24 @@
my $countdown = &countdown_toggle_js();
+ my $viewuser;
+ if (($env{'request.course.id'}) &&
+ ($env{'request.symb'} ne '') &&
+ ($env{'request.filename'}=~/$LONCAPA::assess_re/)) {
+ my $canview;
+ foreach my $priv ('msg','vgr') {
+ $canview = &Apache::lonnet::allowed($priv,$env{'request.course.id'});
+ if (!$canview && $env{'request.course.sec'} ne '') {
+ $canview =
+ &Apache::lonnet::allowed($priv,"$env{'request.course.id'}/$env{'request.course.sec'}");
+ }
+ last if ($canview);
+ }
+ if ($canview) {
+ $viewuser = &view_as_js($esc_url,$esc_symb);
+ }
+ }
+
my ($ltitarget,$deeplinktarget);
if ($env{'request.lti.login'}) {
$ltitarget = $env{'request.lti.target'};
@@ -2512,6 +2666,8 @@
$countdown
+$viewuser
+
ENDUTILITY
}
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.1403 loncom/interface/loncommon.pm:1.1404
--- loncom/interface/loncommon.pm:1.1403 Wed Mar 29 16:01:13 2023
+++ loncom/interface/loncommon.pm Sun Apr 2 03:16:27 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1403 2023/03/29 16:01:13 raeburn Exp $
+# $Id: loncommon.pm,v 1.1404 2023/04/02 03:16:27 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -8160,6 +8160,11 @@
/* overflow: hidden; */
}
+fieldset#LC_selectuser {
+ margin: 0;
+ padding: 0;
+}
+
article.geogebraweb div {
margin: 0;
}
Index: loncom/homework/inputtags.pm
diff -u loncom/homework/inputtags.pm:1.357 loncom/homework/inputtags.pm:1.358
--- loncom/homework/inputtags.pm:1.357 Thu Mar 30 23:25:47 2023
+++ loncom/homework/inputtags.pm Sun Apr 2 03:16:28 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# input definitons
#
-# $Id: inputtags.pm,v 1.357 2023/03/30 23:25:47 raeburn Exp $
+# $Id: inputtags.pm,v 1.358 2023/04/02 03:16:28 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -1787,12 +1787,17 @@
}
if ( $showbutton ) {
if ($target ne 'tex') {
- $button =
+ if ($env{'form.disable_submit'}) {
+ $button = '<input type="submit" name="submit_'.$id.'" id="submit_'.$id.'" class="LC_hwk_submit" value="'.&mt('Submit Answer').'" disabled="disabled" /> '.
+ '<div id="msg_submit_'.$id.'" style="display:none"></div>';
+ } else {
+ $button =
'<input onmouseup="javascript:setSubmittedPart(\''.$id.'\');this.form.action+=\'#'.&escape($id).'\';"
type="submit" name="submit_'.$id.'" id="submit_'.$id.'" class="LC_hwk_submit"
value="'.&mt('Submit Answer').'" /> '.
'<div id="msg_submit_'.$id.'" style="display:none">'.
&mt('Processing your submission ...').'</div>';
+ }
}
}
Index: loncom/homework/structuretags.pm
diff -u loncom/homework/structuretags.pm:1.573 loncom/homework/structuretags.pm:1.574
--- loncom/homework/structuretags.pm:1.573 Fri Feb 3 16:52:57 2023
+++ loncom/homework/structuretags.pm Sun Apr 2 03:16:28 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# definition of tags that give a structure to a document
#
-# $Id: structuretags.pm,v 1.573 2023/02/03 16:52:57 raeburn Exp $
+# $Id: structuretags.pm,v 1.574 2023/04/02 03:16:28 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -625,7 +625,9 @@
my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser();
my ($path,$multiresp) =
&Apache::loncommon::get_turnedin_filepath($symb,$uname,$udom);
- if (($is_task) || ($needs_upload)) {
+ if ($env{'request.user_in_effect'}) {
+ $form_tag_start .= ' onsubmit="preventDefault();"';
+ } elsif (($is_task) || ($needs_upload)) {
$form_tag_start .= ' onsubmit="return file_submission_check(this,'."'$path','$multiresp'".');"';
}
$form_tag_start.='>'."\n";
@@ -1845,6 +1847,11 @@
}
}
+ if (($target eq 'web') && ($env{'request.user_in_effect'})) {
+ &Apache::lonxml::get_all_text("/problem",$parser,$style);
+ return $result;
+ }
+
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
$target eq 'tex') {
@@ -2129,6 +2136,12 @@
}
}
$result =~ s/INSERTTEXFRONTMATTERHERE/$frontmatter/;
+ } elsif ($target eq 'web') {
+ if ($env{'request.user_in_effect'}) {
+ &reset_problem_globals('problem');
+ $result .= &Apache::lonhtmlcommon::set_compute_end_time();
+ return $result;
+ }
}
my $status=$Apache::inputtags::status['-1'];
Index: loncom/homework/lonhomework.pm
diff -u loncom/homework/lonhomework.pm:1.374 loncom/homework/lonhomework.pm:1.375
--- loncom/homework/lonhomework.pm:1.374 Thu Sep 20 14:16:51 2018
+++ loncom/homework/lonhomework.pm Sun Apr 2 03:16:28 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Homework handler
#
-# $Id: lonhomework.pm,v 1.374 2018/09/20 14:16:51 raeburn Exp $
+# $Id: lonhomework.pm,v 1.375 2023/04/02 03:16:28 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -50,6 +50,8 @@
use Apache::functionplotresponse();
use Apache::drawimage();
use Apache::loncapamath();
+use Apache::loncourseuser();
+use Apache::grades();
use Apache::Constants qw(:common);
use Apache::loncommon();
use Apache::lonparmset();
@@ -795,6 +797,9 @@
$env{'request.course.sec'} !~ /^\s*$/) {
$viewgrades = &Apache::lonnet::allowed('vgr',$env{'request.course.id'}.
'/'.$env{'request.course.sec'});
+ if ($viewgrades) {
+ $Apache::lonhomework::viewgradessec = $env{'request.course.sec'};
+ }
}
$Apache::lonhomework::viewgrades = $viewgrades;
@@ -812,6 +817,9 @@
$modifygrades =
&Apache::lonnet::allowed('mgr',$env{'request.course.id'}.
'/'.$env{'request.course.sec'});
+ if ($modifygrades) {
+ $Apache::lonhomework::modifygradessec = $env{'request.course.sec'};
+ }
}
$Apache::lonhomework::modifygrades = $modifygrades;
@@ -830,7 +838,9 @@
sub unset_permissions {
undef($Apache::lonhomework::queuegrade);
undef($Apache::lonhomework::modifygrades);
+ undef($Apache::lonhomework::modifygradessec);
undef($Apache::lonhomework::viewgrades);
+ undef($Apache::lonhomework::viewgradessec);
undef($Apache::lonhomework::browse);
}
@@ -1278,7 +1288,7 @@
# Render the page in whatever target desired.
#
sub renderpage {
- my ($request,$file,$targets,$return_string,$donebuttonmsg) = @_;
+ my ($request,$file,$targets,$return_string,$donebuttonmsg,$viewasuser,$symb) = @_;
my @targets = @{$targets || [&get_target()]};
&Apache::lonhomework::showhashsubset(\%env,'form.');
@@ -1319,6 +1329,10 @@
if ($target eq 'answer') { &showhash(%Apache::lonhomework::history); }
if ($target eq 'web') {&Apache::lonhomework::showhashsubset(\%env,'^form');}
+ if (($target eq 'web') && ($viewasuser ne '') && ($symb ne '')) {
+ $env{'request.user_in_effect'} = $viewasuser;
+ }
+
&Apache::lonxml::debug("Should be parsing now");
$result .= &Apache::lonxml::xmlparse($request, $target, $problem,
&setup_vars($target),%mystyle);
@@ -1344,15 +1358,23 @@
#}
# $request->print($result);
$overall_result.=$result;
+ if (($target eq 'web') && ($viewasuser ne '') && ($symb ne '')) {
+ my ($vuname,$vudom) = split(/:/,$viewasuser);
+ $overall_result .= &Apache::grades::view_as_user($symb,$vuname,$vudom).
+ '</body></html>';
+ }
# $request->rflush();
}
+ if (($target eq 'web') && ($viewasuser ne '') && ($symb ne '')) {
+ undef($env{'request.user_in_effect'});
+ }
#$request->print(":Result ends");
#my $td=&tv_interval($t0);
}
if (!$return_string) {
&Apache::lonxml::add_messages(\$overall_result);
$request->print($overall_result);
- $request->rflush();
+ $request->rflush();
} else {
return $overall_result;
}
@@ -1674,16 +1696,40 @@
} else {
# Set the event timer to zero if the "done button" was clicked. The button is
# part of the doneButton form created in lonmenu.pm
- my ($donebuttonresult,$donemsg);
+ my ($donebuttonresult,$donemsg,$viewasuser);
if ($symb && $env{'form.LC_interval_done'} eq 'true') {
($donebuttonresult,$donemsg) = &zero_timer($symb);
undef($env{'form.LC_interval_done'});
undef($env{'form.LC_interval_done_proctorpass'});
}
+ if (($env{'form.LC_viewas'} ne '') && $symb && $env{'request.course.id'} &&
+ ($Apache::lonhomework::viewgrades || $Apache::lonhomework::modifygrades)) {
+ if ($env{'form.LC_viewas'} =~ /^($match_username):($match_domain)$/) {
+ my ($possuname,$possudom) = ($1,$2);
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my ($canview,$posssec);
+ if ($env{'request.course.sec'} ne '') {
+ if ($Apache::lonhomework::modifygradessec eq $env{'request.course.sec'}) {
+ $canview = 'section';
+ $posssec = $env{'request.course.sec'};
+ } elsif ($Apache::lonhomework::viewgradessec eq $env{'request.course.sec'}) {
+ $canview = 'section';
+ $posssec = $env{'request.course.sec'};
+ }
+ }
+ my $crstype = &Apache::loncommon::course_type();
+ if (&Apache::loncourseuser::is_course_user($possudom,$possuname,$cdom,$cnum,
+ $canview,$crstype,$posssec)) {
+ $viewasuser = $possuname.':'.$possudom;
+ }
+ }
+ undef($env{'form.LC_viewas'});
+ }
# just render the page normally outside of construction space
&Apache::lonxml::debug("not construct");
undef(@Apache::lonhomework::ltipassback);
- &renderpage($request,$file,undef,undef,$donemsg);
+ &renderpage($request,$file,undef,undef,$donemsg,$viewasuser,$symb);
if (@Apache::lonhomework::ltipassback) {
unless ($registered_cleanup) {
my $handlers = $request->get_handlers('PerlCleanupHandler');
Index: loncom/homework/grades.pm
diff -u loncom/homework/grades.pm:1.792 loncom/homework/grades.pm:1.793
--- loncom/homework/grades.pm:1.792 Sun Feb 12 21:01:30 2023
+++ loncom/homework/grades.pm Sun Apr 2 03:16:28 2023
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.792 2023/02/12 21:01:30 raeburn Exp $
+# $Id: grades.pm,v 1.793 2023/04/02 03:16:28 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -2558,182 +2558,12 @@
# (3) All transactions (by date)
# (4) The whole record (with detailed information for all transactions)
- my ($string,$timestamp,$lastgradetime,$lastsubmittime) =
- &get_last_submission(\%record,$is_tool);
-
- my $lastsubonly;
-
- if ($timestamp eq '') {
- $lastsubonly.='<div class="LC_grade_submissions_body">'.$string->[0].'</div>';
- } elsif ($is_tool) {
- $lastsubonly =
- '<div class="LC_grade_submissions_body">'
- .'<b>'.&mt('Date Grade Passed Back:').'</b> '.$timestamp."</div>\n";
- } else {
- my ($shownsubmdate,$showngradedate);
- if ($lastsubmittime && $lastgradetime) {
- $shownsubmdate = &Apache::lonlocal::locallocaltime($lastsubmittime);
- if ($lastgradetime > $lastsubmittime) {
- $showngradedate = &Apache::lonlocal::locallocaltime($lastgradetime);
- }
- } else {
- $shownsubmdate = $timestamp;
- }
- $lastsubonly =
- '<div class="LC_grade_submissions_body">'
- .'<b>'.&mt('Date Submitted:').'</b> '.$shownsubmdate."\n";
- if ($showngradedate) {
- $lastsubonly .= '<br /><b>'.&mt('Date Graded:').'</b> '.$showngradedate."\n";
- }
-
- my %seenparts;
- my @part_response_id = &flatten_responseType($responseType);
- foreach my $part (@part_response_id) {
- my ($partid,$respid) = @{ $part };
- my $display_part=&get_display_part($partid,$symb);
- if ($env{"form.$uname:$udom:$partid:submitted_by"}) {
- if (exists($seenparts{$partid})) { next; }
- $seenparts{$partid}=1;
- $request->print(
- '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
- ' <b>'.&mt('Collaborative submission by: [_1]',
- '<a href="javascript:viewSubmitter(\''.
- $env{"form.$uname:$udom:$partid:submitted_by"}.
- '\');" target="_self">'.
- $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').
- '<br />');
- next;
- }
- my $responsetype = $responseType->{$partid}->{$respid};
- if (!exists($record{"resource.$partid.$respid.submission"})) {
- $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
- '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
- ' <span class="LC_internal_info">'.
- '('.&mt('Response ID: [_1]',$respid).')'.
- '</span> '.
- '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';
- next;
- }
- foreach my $submission (@$string) {
- my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);
- if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }
- my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4);
- # Similarity check
- my $similar='';
- my ($type,$trial,$rndseed);
- if ($hide eq 'rand') {
- $type = 'randomizetry';
- $trial = $record{"resource.$partid.tries"};
- $rndseed = $record{"resource.$partid.rndseed"};
- }
- if ($env{'form.checkPlag'}) {
- my ($oname,$odom,$ocrsid,$oessay,$osim)=
- &most_similar($uname,$udom,$symb,$subval);
- if ($osim) {
- $osim=int($osim*100.0);
- if ($hide eq 'anon') {
- $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.
- &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';
- } else {
- $similar='<hr />';
- if ($essayurl eq 'lib/templates/simpleproblem.problem') {
- $similar .= '<h3><span class="LC_warning">'.
- &mt('Essay is [_1]% similar to an essay by [_2]',
- $osim,
- &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
- '</span></h3>';
- } else {
- my %old_course_desc;
- if ($ocrsid ne '') {
- if (ref($coursedesc_by_cid{$ocrsid}) eq 'HASH') {
- %old_course_desc = %{$coursedesc_by_cid{$ocrsid}};
- } else {
- my $args;
- if ($ocrsid ne $env{'request.course.id'}) {
- $args = {'one_time' => 1};
- }
- %old_course_desc =
- &Apache::lonnet::coursedescription($ocrsid,$args);
- $coursedesc_by_cid{$ocrsid} = \%old_course_desc;
- }
- $similar .=
- '<h3><span class="LC_warning">'.
- &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
- $osim,
- &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
- $old_course_desc{'description'},
- $old_course_desc{'num'},
- $old_course_desc{'domain'}).
- '</span></h3>';
- } else {
- $similar .=
- '<h3><span class="LC_warning">'.
- &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',
- $osim,
- &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
- '</span></h3>';
- }
- }
- $similar .= '<blockquote><i>'.
- &keywords_highlight($oessay).
- '</i></blockquote><hr />';
- }
- }
- }
- my $order=&get_order($partid,$respid,$symb,$uname,$udom,
- undef,$type,$trial,$rndseed);
- if (($env{'form.lastSub'} eq 'lastonly') ||
- ($env{'form.lastSub'} eq 'datesub') ||
- ($env{'form.lastSub'} =~ /^(last|all)$/)) {
- my $display_part=&get_display_part($partid,$symb);
- $lastsubonly.='<div class="LC_grade_submission_part">'.
- '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
- ' <span class="LC_internal_info">'.
- '('.&mt('Response ID: [_1]',$respid).')'.
- '</span> ';
- my $files=&get_submitted_files($udom,$uname,$partid,$respid,\%record);
- if (@$files) {
- if ($hide eq 'anon') {
- $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));
- } else {
- $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'
- .'<br /><span class="LC_warning">';
- if(@$files == 1) {
- $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');
- } else {
- $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');
- }
- $lastsubonly .= '</span>';
- foreach my $file (@$files) {
- &Apache::lonnet::allowuploaded('/adm/grades',$file);
- $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';
- }
- }
- $lastsubonly.='<br />';
- }
- if ($hide eq 'anon') {
- $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>';
- } else {
- $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>';
- if ($draft) {
- $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';
- }
- $subval =
- &cleanRecord($subval,$responsetype,$symb,$partid,
- $respid,\%record,$order,undef,$uname,$udom,$type,$trial,$rndseed);
- if ($responsetype eq 'essay') {
- $subval =~ s{\n}{<br />}g;
- }
- $lastsubonly.=$subval."\n";
- }
- if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
- $lastsubonly.='</div>';
- }
- }
- }
- $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body
- }
+ my ($lastsubonly,$partinfo) =
+ &show_last_submission($uname,$udom,$symb,$essayurl,$responseType,$env{'form.lastSub'},
+ $is_tool,$fullname,\%record,\%coursedesc_by_cid);
+ $request->print($partinfo);
$request->print($lastsubonly);
+
if ($env{'form.lastSub'} eq 'datesub') {
my ($parts,$handgrade,$responseType) = &response_type($symb,\$res_error);
$request->print(&displaySubByDates($symb,\%record,$parts,$responseType,$checkIcon,$uname,$udom));
@@ -2857,6 +2687,186 @@
return '';
}
+sub show_last_submission {
+ my ($uname,$udom,$symb,$essayurl,$responseType,$viewtype,$is_tool,$fullname,
+ $record,$coursedesc_by_cid) = @_;
+ my ($string,$timestamp,$lastgradetime,$lastsubmittime) =
+ &get_last_submission($record,$is_tool);
+
+ my ($lastsubonly,$partinfo);
+ if ($timestamp eq '') {
+ $lastsubonly.='<div class="LC_grade_submissions_body">'.$string->[0].'</div>';
+ } elsif ($is_tool) {
+ $lastsubonly =
+ '<div class="LC_grade_submissions_body">'
+ .'<b>'.&mt('Date Grade Passed Back:').'</b> '.$timestamp."</div>\n";
+ } else {
+ my ($shownsubmdate,$showngradedate);
+ if ($lastsubmittime && $lastgradetime) {
+ $shownsubmdate = &Apache::lonlocal::locallocaltime($lastsubmittime);
+ if ($lastgradetime > $lastsubmittime) {
+ $showngradedate = &Apache::lonlocal::locallocaltime($lastgradetime);
+ }
+ } else {
+ $shownsubmdate = $timestamp;
+ }
+ $lastsubonly =
+ '<div class="LC_grade_submissions_body">'
+ .'<b>'.&mt('Date Submitted:').'</b> '.$shownsubmdate."\n";
+ if ($showngradedate) {
+ $lastsubonly .= '<br /><b>'.&mt('Date Graded:').'</b> '.$showngradedate."\n";
+ }
+
+ my %seenparts;
+ my @part_response_id = &flatten_responseType($responseType);
+ foreach my $part (@part_response_id) {
+ my ($partid,$respid) = @{ $part };
+ my $display_part=&get_display_part($partid,$symb);
+ if ($env{"form.$uname:$udom:$partid:submitted_by"}) {
+ if (exists($seenparts{$partid})) { next; }
+ $seenparts{$partid}=1;
+ $partinfo .=
+ '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
+ ' <b>'.&mt('Collaborative submission by: [_1]',
+ '<a href="javascript:viewSubmitter(\''.
+ $env{"form.$uname:$udom:$partid:submitted_by"}.
+ '\');" target="_self">'.
+ $$fullname{$env{"form.$uname:$udom:$partid:submitted_by"}}.'</a>').
+ '<br />';
+ next;
+ }
+ my $responsetype = $responseType->{$partid}->{$respid};
+ if (!exists($record->{"resource.$partid.$respid.submission"})) {
+ $lastsubonly.="\n".'<div class="LC_grade_submission_part">'.
+ '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
+ ' <span class="LC_internal_info">'.
+ '('.&mt('Response ID: [_1]',$respid).')'.
+ '</span> '.
+ '<span class="LC_warning">'.&mt('Nothing submitted - no attempts.').'</span><br /><br /></div>';
+ next;
+ }
+ foreach my $submission (@$string) {
+ my ($partid,$respid) = ($submission =~ /^resource\.([^\.]*)\.([^\.]*)\.submission/);
+ if (join('_',@{$part}) ne ($partid.'_'.$respid)) { next; }
+ my ($ressub,$hide,$draft,$subval) = split(/:/,$submission,4);
+ # Similarity check
+ my $similar='';
+ my ($type,$trial,$rndseed);
+ if ($hide eq 'rand') {
+ $type = 'randomizetry';
+ $trial = $record->{"resource.$partid.tries"};
+ $rndseed = $record->{"resource.$partid.rndseed"};
+ }
+ if ($env{'form.checkPlag'}) {
+ my ($oname,$odom,$ocrsid,$oessay,$osim)=
+ &most_similar($uname,$udom,$symb,$subval);
+ if ($osim) {
+ $osim=int($osim*100.0);
+ if ($hide eq 'anon') {
+ $similar='<hr /><span class="LC_warning">'.&mt("Essay was found to be similar to another essay submitted for this assignment.").'<br />'.
+ &mt('As the current submission is for an anonymous survey, no other details are available.').'</span><hr />';
+ } else {
+ $similar='<hr />';
+ if ($essayurl eq 'lib/templates/simpleproblem.problem') {
+ $similar .= '<h3><span class="LC_warning">'.
+ &mt('Essay is [_1]% similar to an essay by [_2]',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
+ '</span></h3>';
+ } else {
+ my %old_course_desc;
+ if ($ocrsid ne '') {
+ if (ref($coursedesc_by_cid->{$ocrsid}) eq 'HASH') {
+ %old_course_desc = %{$coursedesc_by_cid->{$ocrsid}};
+ } else {
+ my $args;
+ if ($ocrsid ne $env{'request.course.id'}) {
+ $args = {'one_time' => 1};
+ }
+ %old_course_desc =
+ &Apache::lonnet::coursedescription($ocrsid,$args);
+ $coursedesc_by_cid->{$ocrsid} = \%old_course_desc;
+ }
+ $similar .=
+ '<h3><span class="LC_warning">'.
+ &mt('Essay is [_1]% similar to an essay by [_2] in course [_3] (course id [_4]:[_5])',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')',
+ $old_course_desc{'description'},
+ $old_course_desc{'num'},
+ $old_course_desc{'domain'}).
+ '</span></h3>';
+ } else {
+ $similar .=
+ '<h3><span class="LC_warning">'.
+ &mt('Essay is [_1]% similar to an essay by [_2] in an unknown course',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom).' ('.$oname.':'.$odom.')').
+ '</span></h3>';
+ }
+ }
+ $similar .= '<blockquote><i>'.
+ &keywords_highlight($oessay).
+ '</i></blockquote><hr />';
+ }
+ }
+ }
+ my $order=&get_order($partid,$respid,$symb,$uname,$udom,
+ undef,$type,$trial,$rndseed);
+ if (($viewtype eq 'lastonly') ||
+ ($viewtype eq 'datesub') ||
+ ($viewtype =~ /^(last|all)$/)) {
+ my $display_part=&get_display_part($partid,$symb);
+ $lastsubonly.='<div class="LC_grade_submission_part">'.
+ '<b>'.&mt('Part: [_1]',$display_part).'</b>'.
+ ' <span class="LC_internal_info">'.
+ '('.&mt('Response ID: [_1]',$respid).')'.
+ '</span> ';
+ my $files=&get_submitted_files($udom,$uname,$partid,$respid,$record);
+ if (@$files) {
+ if ($hide eq 'anon') {
+ $lastsubonly.='<br />'.&mt('[quant,_1,file] uploaded to this anonymous survey',scalar(@{$files}));
+ } else {
+ $lastsubonly.='<br /><br />'.'<b>'.&mt('Submitted Files:').'</b>'
+ .'<br /><span class="LC_warning">';
+ if(@$files == 1) {
+ $lastsubonly .= &mt('Like all files provided by users, this file may contain viruses!');
+ } else {
+ $lastsubonly .= &mt('Like all files provided by users, these files may contain viruses!');
+ }
+ $lastsubonly .= '</span>';
+ foreach my $file (@$files) {
+ &Apache::lonnet::allowuploaded('/adm/grades',$file);
+ $lastsubonly.='<br /><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.&Apache::loncommon::icon($file).'" border="0" alt="" /> '.$file.'</a>';
+ }
+ }
+ $lastsubonly.='<br />';
+ }
+ if ($hide eq 'anon') {
+ $lastsubonly.='<br /><b>'.&mt('Anonymous Survey').'</b>';
+ } else {
+ $lastsubonly.='<br /><b>'.&mt('Submitted Answer:').' </b>';
+ if ($draft) {
+ $lastsubonly.= ' <span class="LC_warning">'.&mt('Draft Copy').'</span>';
+ }
+ $subval =
+ &cleanRecord($subval,$responsetype,$symb,$partid,
+ $respid,$record,$order,undef,$uname,$udom,$type,$trial,$rndseed);
+ if ($responsetype eq 'essay') {
+ $subval =~ s{\n}{<br />}g;
+ }
+ $lastsubonly.=$subval."\n";
+ }
+ if ($similar) {$lastsubonly.="<br /><br />$similar\n";}
+ $lastsubonly.='</div>';
+ }
+ }
+ }
+ $lastsubonly.='</div>'."\n"; # End: LC_grade_submissions_body
+ }
+ return ($lastsubonly,$partinfo);
+}
+
sub check_collaborators {
my ($symb,$uname,$udom,$record,$handgrade,$counter) = @_;
my ($result, at col_fullnames);
@@ -11555,6 +11565,77 @@
$r->print('<input type="submit" value="'.&mt('Next').' →" /></form>');
}
+#----- display problem, answer, and submissions for a single student (no grading)
+
+sub view_as_user {
+ my ($symb,$vuname,$vudom,$hasperm) = @_;
+ my $plainname = &Apache::loncommon::plainname($vuname,$vudom,'lastname');
+ my $displayname = &nameUserString('',$plainname,$vuname,$vudom);
+ my $output = &Apache::loncommon::get_student_view($symb,$vuname,$vudom,
+ $env{'request.course.id'},
+ undef,{'disable_submit' => 1}).
+ "\n\n".
+ '<div class="LC_grade_show_user">'.
+ '<h2>'.$displayname.'</h2>'.
+ "\n".
+ &Apache::loncommon::track_student_link('View recent activity',
+ $vuname,$vudom,'check').' '.
+ "\n";
+ if (&Apache::lonnet::allowed('opa',$env{'request.course.id'}) ||
+ (($env{'request.course.sec'} ne '') &&
+ &Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.$env{'request.course.sec'}))) {
+ $output .= &Apache::loncommon::pprmlink(&mt('Set/Change parameters'),
+ $vuname,$vudom,$symb,'check');
+ }
+ $output .= "\n";
+ my $companswer = &Apache::loncommon::get_student_answers($symb,$vuname,$vudom,
+ $env{'request.course.id'});
+ $companswer=~s|<form(.*?)>||g;
+ $companswer=~s|</form>||g;
+ $companswer=~s|name="submit"|name="would_have_been_submit"|g;
+ $output .= '<div class="LC_Box">'.
+ '<h3 class="LC_hcell">'.&mt('Correct answer for[_1]',$displayname).'</h3>'.
+ $companswer.
+ '</div>'."\n";
+ my $is_tool = ($symb =~ /ext\.tool$/);
+ my ($essayurl,%coursedesc_by_cid);
+ (undef,undef,$essayurl) = &Apache::lonnet::decode_symb($symb);
+ my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},$vudom,$vuname);
+ my $res_error;
+ my ($partlist,$handgrade,$responseType,$numresp,$numessay) =
+ &response_type($symb,\$res_error);
+ my $fullname;
+ my $collabinfo;
+ if ($numessay) {
+ unless ($hasperm) {
+ &init_perm();
+ }
+ ($collabinfo,$fullname)=
+ &check_collaborators($symb,$vuname,$vudom,\%record,$handgrade,0);
+ unless ($hasperm) {
+ &reset_perm();
+ }
+ }
+ my $checkIcon = '<img alt="'.&mt('Check Mark').
+ '" src="'.$Apache::lonnet::perlvar{'lonIconsURL'}.
+ '/check.gif" height="16" border="0" />';
+ my ($lastsubonly,$partinfo) =
+ &show_last_submission($vuname,$vudom,$symb,$essayurl,$responseType,'datesub',
+ '',$fullname,\%record,\%coursedesc_by_cid);
+ $output .= '<div class="LC_Box">'.
+ '<h3 class="LC_hcell">'.&mt('Submissions').'</h3>'."\n".$collabinfo."\n";
+ if (($numresp > $numessay) & !$is_tool) {
+ $output .='<p class="LC_info">'.
+ &mt('Part(s) graded correct by the computer is marked with a [_1] symbol.',$checkIcon).
+ "</p>\n";
+ }
+ $output .= $partinfo;
+ $output .= $lastsubonly;
+ $output .= &displaySubByDates($symb,\%record,$partlist,$responseType,$checkIcon,$vuname,$vudom);
+ $output .= '</div></div>'."\n";
+ return $output;
+}
+
sub handler {
my $request=$_[0];
&reset_caches();
Index: doc/loncapafiles/loncapafiles.lpml
diff -u doc/loncapafiles/loncapafiles.lpml:1.1035 doc/loncapafiles/loncapafiles.lpml:1.1036
--- doc/loncapafiles/loncapafiles.lpml:1.1035 Sat Dec 31 14:09:02 2022
+++ doc/loncapafiles/loncapafiles.lpml Sun Apr 2 03:16:31 2023
@@ -2,7 +2,7 @@
"http://lpml.sourceforge.net/DTD/lpml.dtd">
<!-- loncapafiles.lpml -->
-<!-- $Id: loncapafiles.lpml,v 1.1035 2022/12/31 14:09:02 raeburn Exp $ -->
+<!-- $Id: loncapafiles.lpml,v 1.1036 2023/04/02 03:16:31 raeburn Exp $ -->
<!--
@@ -2744,6 +2744,15 @@
<status>works/unverified</status>
</file>
<file>
+<source>loncom/interface/loncourseuser.pm</source>
+<target dist='default'>home/httpd/lib/perl/Apache/loncourseuser.pm</target>
+<categoryname>handler</categoryname>
+<description>
+Handler to check if a user has a role (active, future or previous) in a course.
+</description>
+<status>works/unverified</status>
+</file>
+<file>
<source>loncom/interface/loncourserespicker.pm</source>
<target dist='default'>home/httpd/lib/perl/Apache/loncourserespicker.pm</target>
<categoryname>handler</categoryname>
@@ -8579,6 +8588,7 @@
uploadscores.png;
verify.png;
view-mode-22x22.png;
+viewuser.png;
wishlist.png;
wishlist-link.png;
wishlist-link-lighter.png;
Index: loncom/interface/loncourseuser.pm
+++ loncom/interface/loncourseuser.pm
# The LearningOnline Network
# Verify user is in course
#
# $Id: loncourseuser.pm,v 1.1 2023/04/02 03:16:27 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
package Apache::loncourseuser;
use strict;
use Apache::Constants qw(:common :http);
use Apache::lonnet;
use Apache::loncommon;
use Apache::lonuserutils;
use JSON::DWIW;
use LONCAPA qw(:DEFAULT :match);
sub handler {
my $r = shift;
&Apache::loncommon::content_type($r,'application/json');
$r->send_http_header;
my @userinfo;
if ($env{'request.course.id'}) {
my $canview;
foreach my $priv ('mgr','vgr') {
$canview = &Apache::lonnet::allowed($priv,$env{'request.course.id'});
if (!$canview && $env{'request.course.sec'} ne '') {
if (&Apache::lonnet::allowed($priv,"$env{'request.course.id'}/$env{'request.course.sec'}")) {
$canview = 'section';
}
}
last if ($canview);
}
if ($canview) {
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
my $crstype = &Apache::loncommon::course_type();
if (($cdom) && ($cnum)) {
my $possudom = $env{'form.udom'};
if (&Apache::lonnet::domain($possudom) ne '') {
my $possuname = $env{'form.uname'};
my $possuid = $env{'form.uid'};
if (($possuname eq '') && ($possuid ne '')) {
$possuname=(&Apache::lonnet::idget($possudom,[$possuid],'ids'))[1];
}
if ($possuname ne '') {
if (&is_course_user($possudom,$possuname,$cdom,$cnum,$canview,
$crstype,$env{'request.course.sec'})) {
@userinfo = ($possuname,$possudom);
}
}
}
}
}
}
$r->print(JSON::DWIW->to_json({match => \@userinfo}));
return OK;
}
sub is_course_user {
my ($possudom,$possuname,$cdom,$cnum,$canview,$crstype,$section) = @_;
my $found;
my @types = ('active','future','previous');
my @roles = &Apache::lonuserutils::roles_by_context('course',1,$crstype);
my %userhash = &Apache::lonnet::get_my_roles($possuname,$possudom,'userroles',\@types,\@roles,[$cdom],1);
if (keys(%userhash)) {
foreach my $key (keys(%userhash)) {
next unless ($key =~ /^\Q$cnum:$cdom:\E/);
if ($canview eq 'section') {
my $usec = (split(/:/,$key))[-1];
if ($usec eq $section) {
$found = 1;
}
} else {
$found = 1;
}
last if ($found);
}
}
return $found;
}
1;
More information about the LON-CAPA-cvs
mailing list