--- loncom/homework/lonhomework.pm 2009/03/04 16:00:14 1.304 +++ loncom/homework/lonhomework.pm 2015/06/29 15:42:07 1.355 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Homework handler # -# $Id: lonhomework.pm,v 1.304 2009/03/04 16:00:14 bisitz Exp $ +# $Id: lonhomework.pm,v 1.355 2015/06/29 15:42:07 damieng Exp $ # # Copyright Michigan State University Board of Trustees # @@ -47,9 +47,12 @@ use Apache::externalresponse(); use Apache::rankresponse(); use Apache::matchresponse(); use Apache::chemresponse(); +use Apache::functionplotresponse(); use Apache::drawimage(); +use Apache::loncapamath(); use Apache::Constants qw(:common); use Apache::loncommon(); +use Apache::lonparmset(); use Apache::lonlocal; use Time::HiRes qw( gettimeofday tv_interval ); use HTML::Entities(); @@ -111,7 +114,11 @@ sub get_target { } elsif ( $env{'form.grade_target'} eq 'webgrade' && ($Apache::lonhomework::queuegrade eq 'F' )) { return ($env{'form.grade_target'}); - } + } elsif ($env{'form.grade_target'} eq 'answer') { + if ($env{'form.answer_output_mode'} eq 'tex') { + return ($env{'form.grade_target'}); + } + } if ($env{'form.webgrade'} && ($Apache::lonhomework::modifygrades eq 'F' || $Apache::lonhomework::queuegrade eq 'F' )) { @@ -124,43 +131,46 @@ sub get_target { return ('web'); } } elsif ($env{'request.state'} eq "construct") { +# +# We are in construction space, editing and testing problems +# if ( defined($env{'form.grade_target'}) ) { return ($env{'form.grade_target'}); } if ( defined($env{'form.preview'})) { if ( defined($env{'form.submitted'})) { +# +# We are doing a problem preview +# return ('grade', 'web'); } else { return ('web'); } } else { if ($env{'form.problemstate'} eq 'WEB_GRADE') { - #$env{'form.webgrade'} = 'yes'; return ('grade','webgrade','answer'); - } elsif (($env{'form.problemmode'} eq 'view') || - ($env{'form.problemmode'} eq 'discard')) { - if ( defined($env{'form.submitted'}) && - (!defined($env{'form.resetdata'})) && - (!defined($env{'form.newrandomization'}))) { - return ('grade', 'web','answer'); - } else { - return ('web','answer'); - } - } elsif ($env{'form.problemmode'} eq 'edit') { - if ( $env{'form.submitted'} eq 'edit' ) { - if ( $env{'form.submitbutton'} eq &mt('Save and View') ) { - return ('modified','web','answer'); - } else { - return ('modified','no_output_web','edit'); - } - } else { - return ('no_output_web','edit'); - } + } elsif ($env{'form.problemmode'} eq 'view') { + return ('grade','web','answer'); + } elsif ($env{'form.problemmode'} eq 'saveview') { + return ('modified','web','answer'); + } elsif ($env{'form.problemmode'} eq 'discard') { + return ('web','answer'); + } elsif (($env{'form.problemmode'} eq 'saveedit') || + ($env{'form.problemmode'} eq 'undo')) { + return ('modified','no_output_web','edit'); + } elsif ($env{'form.problemmode'} eq 'edit') { + return ('no_output_web','edit'); } else { return ('web'); } - } + } +# +# End of Authoring Space +# } +# +# Huh? We are nowhere, so do nothing. +# return (); } @@ -170,16 +180,6 @@ sub setup_vars { # return ';$external::target='.$target.';'; } -sub createmenu { - my ($which,$request)=@_; - if ($which eq 'grade') { - $request->print(''); - } -} - sub proctor_checked_in { my ($slot_name,$slot,$type)=@_; my @possible_proctors=split(",",$slot->{'proctor'}); @@ -248,25 +248,29 @@ sub check_slot_access { # } my $slotstatus='NOT_IN_A_SLOT'; my ($returned_slot,$slot_name); + my $now = time; + my $num_usable_slots = 0; foreach my $slot (@slots) { $slot =~ s/(^\s*|\s*$)//g; &Apache::lonxml::debug("getting $slot"); my %slot=&Apache::lonnet::get_slot($slot); &Apache::lonhomework::showhash(%slot); - if ($slot{'starttime'} < time && - $slot{'endtime'} > time && + next if ($slot{'endtime'} < $now); + $num_usable_slots ++; + if ($slot{'starttime'} < $now && + $slot{'endtime'} > $now && &Apache::loncommon::check_ip_acc($slot{'ip'})) { &Apache::lonxml::debug("$slot is good"); $slotstatus='NEEDS_CHECKIN'; $returned_slot=\%slot; $slot_name=$slot; last; - } + } } if ($slotstatus eq 'NEEDS_CHECKIN' && &proctor_checked_in($slot_name,$returned_slot,$type)) { - &Apache::lonxml::debug("protoctor checked in"); - $slotstatus='CAN_ANSWER'; + &Apache::lonxml::debug("proctor checked in"); + $slotstatus=$status; } my ($is_correct,$got_grade,$checkedin); @@ -297,12 +301,40 @@ sub check_slot_access { return ('WAITING_FOR_GRADE'); } - # no slot is currently open, and has been checked in for this version - # previous slot is therefore CLOSED, so therefore the problem is - if (!defined($slot_name) - && $checkedin - && $type eq 'problem') { - return ('CLOSED',$datemsg); + # Previously used slot is no longer open, and has been checked in for this version. + # However, the problem is not closed, and potentially, another slot might be + # used to gain access to it to work on it, until the due date is reached, and the + # problem then becomes CLOSED. Therefore return the slotstatus - + # (which will be one of: NOT_IN_A_SLOT, RESERVABLE, RESERVABLE_LATER, or NOTRESERVABLE. + if (!defined($slot_name) && $type eq 'problem') { + if ($slotstatus eq 'NOT_IN_A_SLOT') { + if (!$num_usable_slots) { + if ($env{'request.course.id'}) { + my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; + my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; + my ($symb)=&Apache::lonnet::whichuser(); + $slotstatus = 'NOTRESERVABLE'; + my ($reservable_now_order,$reservable_now,$reservable_future_order, + $reservable_future) = + &Apache::loncommon::get_future_slots($cnum,$cdom,$now,$symb); + if ((ref($reservable_now_order) eq 'ARRAY') && (ref($reservable_now) eq 'HASH')) { + if (@{$reservable_now_order} > 0) { + $slotstatus = 'RESERVABLE'; + $datemsg = $reservable_now->{$reservable_now_order->[-1]}{'endreserve'}; + } + } + unless ($slotstatus eq 'RESERVABLE') { + if ((ref($reservable_future_order) eq 'ARRAY') && (ref($reservable_future) eq 'HASH')) { + if (@{$reservable_future_order} > 0) { + $slotstatus = 'RESERVABLE_LATER'; + $datemsg = $reservable_future->{$reservable_future_order->[0]}{'startreserve'}; + } + } + } + } + } + } + return ($slotstatus,$datemsg); } if ($slotstatus eq 'NOT_IN_A_SLOT' @@ -375,7 +407,12 @@ sub check_access { $date=&mt("can not be accessed from your location."); return($status,$date); } - + if ($env{'form.grade_imsexport'}) { + if (($env{'request.course.id'}) && + (&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { + return ('SHOW_ANSWER'); + } + } foreach my $temp ("opendate","duedate","answerdate") { $lastdate = $date; if ($temp eq 'duedate') { @@ -416,13 +453,14 @@ sub check_access { $datemsg=$date; } elsif ($type eq 'opendate') { $status='CLOSED'; - $datemsg = &mt("will open on")." $date"; + $datemsg = &mt('will open on [_1]',$date); } elsif ($type eq 'duedate') { $status='CAN_ANSWER'; - $datemsg = &mt("is due at")." $date"; + $datemsg = &mt('is due at [_1]',$date); } elsif ($type eq 'answerdate') { $status='CLOSED'; - $datemsg = &mt("was due on")." $lastdate".&mt(", and answers will be available on")." $date"; + $datemsg = &mt('was due on [_1], and answers will be available on [_2]', + $lastdate,$date); } } if ($status eq 'CAN_ANSWER' || @@ -435,11 +473,13 @@ sub check_access { $env{'request.state'} ne 'construct') { $maxtries = '2'; } if ($maxtries && $tries >= $maxtries) { $status = 'CANNOT_ANSWER'; } # if (correct and show prob status) or excused then CANNOT_ANSWER - if(($Apache::lonhomework::history{"resource.$id.solved"}=~/^correct/ - && - &show_problem_status()) - || - $Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) { + if ( ($Apache::lonhomework::history{"resource.$id.solved"}=~/^correct/) + && (&show_problem_status()) ) { + if (($Apache::lonhomework::history{"resource.$id.awarded"} >= 1) || + (&Apache::lonnet::EXT("resource.$id.retrypartial") !~/^1|on|yes$/i)) { + $status = 'CANNOT_ANSWER'; + } + } elsif ($Apache::lonhomework::history{"resource.$id.solved"}=~/^excused/) { $status = 'CANNOT_ANSWER'; } if ($status eq 'CANNOT_ANSWER' @@ -470,7 +510,6 @@ sub check_access { # return ('UNCHECKEDOUT','needs to be checked out'); #} - &Apache::lonxml::debug("sending back :$status:$datemsg:"); if (($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED')) { &Apache::lonxml::debug("should be allowed to browse a resource when closed"); @@ -503,7 +542,7 @@ sub due_date { } else { $date = $due_date; } - return $date + return $date; } sub seconds_to_human_length { @@ -552,7 +591,7 @@ sub showarray { sub showhashsubset { my ($hash,$keyre) = @_; my $resultkey; - foreach $resultkey (sort keys %$hash) { + foreach $resultkey (sort(keys(%$hash))) { if ($resultkey !~ /$keyre/) { next; } if (ref($$hash{$resultkey}) eq 'ARRAY' ) { &Apache::lonxml::debug("$resultkey ---- ". @@ -570,6 +609,9 @@ sub showhashsubset { sub setuppermissions { $Apache::lonhomework::browse= &Apache::lonnet::allowed('bre',$env{'request.filename'}); + unless ($Apache::lonhomework::browse eq 'F') { + $Apache::lonhomework::browse=&Apache::lonnet::allowed('bro',$env{'request.filename'}); + } my $viewgrades = &Apache::lonnet::allowed('vgr',$env{'request.course.id'}); if (! $viewgrades && exists($env{'request.course.sec'}) && @@ -629,12 +671,13 @@ sub setupheader { } sub handle_save_or_undo { - my ($request,$problem,$result) = @_; + my ($request,$problem,$result,$getobjref) = @_; + my $file = &Apache::lonnet::filelocation("",$request->uri); my $filebak =$file.".bak"; my $filetmp =$file.".tmp"; my $error=0; - if ($env{'form.Undo'} eq &mt('undo')) { + if (($env{'form.problemmode'} eq 'undo') || ($env{'form.problemmode'} eq 'undoxml')) { my $error=0; if (!&File::Copy::copy($file,$filetmp)) { $error=1; } if ((!$error) && (!&File::Copy::copy($filebak,$file))) { $error=1; } @@ -657,6 +700,7 @@ sub handle_save_or_undo { } } else { &Apache::lonnet::correct_line_ends($result); + my $fs=Apache::File->new(">$filebak"); if (defined($fs)) { print $fs $$problem; @@ -670,6 +714,30 @@ sub handle_save_or_undo { my $fh=Apache::File->new(">$file"); if (defined($fh)) { print $fh $$result; + if (ref($getobjref) eq 'SCALAR') { + if ($file =~ m{([^/]+)\.(html?)$}) { + my $fname = $1; + my $ext = $2; + my $path = $file; + $path =~ s/\Q$fname\E\.\Q$ext\E$//; + my (%allfiles,%codebase); + &Apache::lonnet::extract_embedded_items($file,\%allfiles, + \%codebase,$result); + if (keys(%allfiles) > 0) { + my $url = $request->uri; + my $state = < + +STATE + $$getobjref = "

".&mt("Reference Warning")."

". + "

".&mt("Completed upload of the file. This file contained references to other files.")."

". + "

".&mt("Please select the locations from which the referenced files are to be uploaded.")."

". + &Apache::loncommon::ask_for_embedded_content($url,$state,\%allfiles,\%codebase, + {'error_on_invalid_names' => 1, + 'ignore_remote_references' => 1,}); + } + } + } } else { &Apache::lonxml::info(''. &mt("Unable to write to [_1]", @@ -685,12 +753,23 @@ sub handle_save_or_undo { sub analyze_header { my ($request) = @_; my $js = &Apache::structuretags::setmode_javascript(); - my $result = - &Apache::loncommon::start_page('Analyzing a problem',$js); + # Breadcrumbs + my $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri), + 'text' => 'Authoring Space'}, + {'href' => '', + 'text' => 'Problem Testing'}, + {'href' => '', + 'text' => 'Analyzing a problem'}]; + + my $result = + &Apache::loncommon::start_page('Analyzing a problem', + $js, + {'bread_crumbs' => $brcrum,}) + .&Apache::loncommon::head_subbox( + &Apache::loncommon::CSTR_pageheader()); $result .= - &Apache::lonxml::message_location().' -
'. ''. @@ -700,12 +779,13 @@ sub analyze_header { 'onclick="javascript:setmode(this.form,'."'editxml'".')" /> -
+
-
- -
'; +
+ ' + .&Apache::lonxml::message_location(). + ''; &Apache::lonxml::add_messages(\$result); $request->print($result); $request->rflush(); @@ -727,13 +807,9 @@ sub analyze { my $rndseed=$env{'form.rndseed'}; &analyze_header($request); my %prog_state= - &Apache::lonhtmlcommon::Create_PrgWin($request,&mt('Analyze Progress'), - &mt('Getting Problem Variants'), - $env{'form.numtoanalyze'}, - 'inline',undef); + &Apache::lonhtmlcommon::Create_PrgWin($request,$env{'form.numtoanalyze'}); for(my $i=1;$i<$env{'form.numtoanalyze'}+1;$i++) { - &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state, - &mt('last problem')); + &Apache::lonhtmlcommon::Increment_PrgWin($request,\%prog_state,'last problem'); if (&Apache::loncommon::connection_aborted($request)) { return; } my $thisseed=$i+$rndseed; my $subresult=&Apache::lonnet::ssi($request->uri, @@ -742,7 +818,7 @@ sub analyze { (my $garbage,$subresult)=split(/_HASH_REF__/,$subresult,2); my %analyze=&Apache::lonnet::str2hash($subresult); my @parts; - if (defined(@{ $analyze{'parts'} })) { + if (ref($analyze{'parts'}) eq 'ARRAY') { @parts=@{ $analyze{'parts'} }; } foreach my $part (@parts) { @@ -775,39 +851,64 @@ sub analyze { } } } - &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state, - &mt('Analyzing Results')); - $request->print('
'.&mt('List of possible answers').': '); + &Apache::lonhtmlcommon::Update_PrgWin($request,\%prog_state,&mt('Analyzing Results')); + $request->print('
' + .'

' + .&mt('List of possible answers') + .'

' + ); foreach my $part (sort(keys(%allparts))) { - if (defined(@{ $overall{$part.'.answer'} })) { + if ((ref($overall{$part.'.answer'}) eq 'ARRAY') && + (@{$overall{$part.'.answer'}} > 0)) { for (my $i=0;$iprint(''); + $request->print('' + .&Apache::loncommon::end_data_table_header_row() + ); my %frequency; foreach my $answer (sort {$a->[0] <=> $b->[0]} (@{ $overall{$part.'.answer'}[$i] })) { $frequency{join("\0",@{ $answer })}++; } - $request->print(''); + $request->print(&Apache::loncommon::start_data_table_header_row() + .'' + .'' + .&Apache::loncommon::end_data_table_header_row() + ); foreach my $answer (sort {(split("\0",$a))[0] <=> (split("\0",$b))[0]} (keys(%frequency))) { - $request->print(''); + $request->print(&Apache::loncommon::start_data_table_row() + .'' + .'' + .&Apache::loncommon::end_data_table_row() + ); } - $request->print('
'.&mt('Part').' '.$part); + $request->print(&Apache::loncommon::start_data_table() + .&Apache::loncommon::start_data_table_header_row() + .'' + .&mt('Part').' '.$part + ); if (scalar(@{ $overall{$part.'.answer'} }) > 1) { - $request->print(&mt(' Answer [_1]',$i+1)); + $request->print(' '.&mt('Answer [_1]',$i+1)); } - $request->print('
'.&mt('Answer').''.&mt('Frequency').'
(' - .&mt('click for example').')
'.&mt('Answer').''.&mt('Frequency').'
' + .'('.&mt('click for example').')
'. - join('',split("\0",$answer)). - ''.$frequency{$answer}. - '
' + .join('',split("\0",$answer)) + .'' + .''.$frequency{$answer}.'' + .'
'); + $request->print(&Apache::loncommon::end_data_table()); } } else { - $request->print('

'.&mt('Response').' '.$part.' '. - &mt('is not analyzable at this time').'

'); + $request->print('

' + .&mt('Response [_1] is not analyzable at this time.',$part) + .'

' + ); } } if (scalar(keys(%allparts)) == 0 ) { - $request->print('

'.&mt('Found no analyzable responses in this problem, currently only Numerical, Formula and String response styles are supported.').'

'); + $request->print('

' + .&mt('Found no analyzable responses in this problem.' + .' Currently only Numerical, Formula and String response styles are supported.') + .'

' + ); } &Apache::lonhtmlcommon::Close_PrgWin($request,\%prog_state); &analyze_footer($request); @@ -855,17 +956,23 @@ sub editxmlmode { my $result; my $problem=&Apache::lonnet::getfile($file); if ($problem eq -1) { - &Apache::lonxml::error(" ".&mt('Unable to find'). - " $file"); + &Apache::lonxml::error( + '

' + .&mt('Unable to find [_1]', + ''.$file.'') + .'

'); + $problem=''; } - if (defined($env{'form.editxmltext'}) || defined($env{'form.Undo'})) { + if (($env{'form.problemmode'} eq 'saveeditxml') || + ($env{'form.problemmode'} eq 'saveviewxml') || + ($env{'form.problemmode'} eq 'undoxml')) { my $error=&handle_save_or_undo($request,\$problem, \$env{'form.editxmltext'}); if (!$error) { $problem=&Apache::lonnet::getfile($file); } } &Apache::lonhomework::showhashsubset(\%env,'^form'); - if ( $env{'form.submitbutton'} eq &mt('Save and View') ) { + if ($env{'form.problemmode'} eq 'saveviewxml') { &Apache::lonhomework::showhashsubset(\%env,'^form'); $env{'form.problemmode'}='view'; &renderpage($request,$file); @@ -879,55 +986,113 @@ sub editxmlmode { &Apache::loncommon::resize_textarea_js(). &Apache::structuretags::setmode_javascript(). &Apache::lonhtmlcommon::dragmath_js("EditMathPopup"); - my $only_body = ($env{'environment.remote'} eq 'off')? 0 : 1; - my $dragmath_button = - &Apache::lonhtmlcommon::dragmath_button("LC_editxmltext",1); + + # Breadcrumbs + my $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri), + 'text' => 'Authoring Space'}, + {'href' => '', + 'text' => 'Problem Editing'}]; + my $start_page = &Apache::loncommon::start_page(&mt("EditXML [_1]",$file),$js, {'no_auto_mt_title' => 1, - 'only_body' => $only_body, + 'only_body' => 0, 'add_entries' => { 'onresize' => q[resize_textarea('LC_editxmltext','LC_aftertextarea')], 'onload' => q[resize_textarea('LC_editxmltext','LC_aftertextarea')], - }}); - $result.=$start_page. - &renderpage($request,$file,['no_output_web'],1). - '
'. &Apache::structuretags::remember_problem_state().' -
- -
- '.&mt('Problem Editing').&Apache::loncommon::help_open_topic('Problem_Editor_XML_Index').' - - '.&Apache::loncommon::helpLatexCheatsheet('Problem_LON-CAPA_Functions','Script Functions').' -
-
- - - - - - '.$dragmath_button.' -
-
- - -
-
- '.&Apache::lonxml::message_location().' -
- ' . ' - -
-
-
'.&Apache::loncommon::end_page(); - &Apache::lonxml::add_messages(\$result); - $request->print($result); +
+
'. + &mt('Problem Editing').' '.&Apache::loncommon::help_open_topic('Problem_Editor_XML_Index'). + '
'; + + $result.=''. + &Apache::structuretags::problem_edit_buttons('editxml'); + $result.='
'; + + $result .= '
    '; + + unless ($env{'environment.nocodemirror'}) { + # dropdown menus + $result .= Apache::lonmenu::create_submenu("#", "", + &mt("Problem Templates"), template_dropdown_datastructure()); + + $result .= Apache::lonmenu::create_submenu("#", "", + &mt("Response Types"), responseblock_dropdown_datastructure()); + + $result .= Apache::lonmenu::create_submenu("#", "", + &mt("Conditional Blocks"), conditional_scripting_datastructure()); + + $result .= Apache::lonmenu::create_submenu("#", "", + &mt("Miscellaneous"), misc_datastructure()); + } + + $result .= Apache::lonmenu::create_submenu("#", "", + &mt("Help") . ' ' . &mt(', + helpmenu_datastructure(),""); + + $result.="
"; + + $result .= '
' . + &Apache::lonxml::message_location() . + &Apache::loncommon::xmleditor_js() . + '
'; + + my $resource = $env{'request.ambiguous'}; + unless($env{'environment.nocodemirror'}){ + $result .= ' + + '; + } + + $result .= &Apache::loncommon::end_page(); + &Apache::lonxml::add_messages(\$result); + $request->print($result); } return ''; } @@ -962,12 +1127,13 @@ sub renderpage { $problem=''; my $filename=(split('/',$file))[-1]; my $error = - " ".&mt('Unable to find [_1]', - ' '.$filename.'') - .""; + '

' + .&mt('Unable to find [_1]', + ''.$filename.'') + ."

"; $result.= &Apache::loncommon::simple_error_page($request,'Not available', - $error); + $error,{'no_auto_mt_msg' => 1}); return; } @@ -1015,7 +1181,25 @@ sub finished_parsing { undef($Apache::lonhomework::parsing_a_task); } -sub get_template_list { +# function extracted from get_template_html +# returns "key" -> list +# key: path of template +# value 1: title +# value 2: category +# value 3: name of help topic ??? +sub get_template_list{ + my ($extension) = @_; + + my @files = glob($Apache::lonnet::perlvar{'lonIncludes'}. + '/templates/*.'.$extension); + @files = map {[$_,&mt(&Apache::lonnet::metadata($_, 'title')), + (&Apache::lonnet::metadata($_, 'category')?&mt(&Apache::lonnet::metadata($_, 'category')):&mt('Miscellaneous')), + &mt(&Apache::lonnet::metadata($_, 'help'))]} (@files); + @files = sort {$a->[2].$a->[1] cmp $b->[2].$b->[1]} (@files); + return @files; +} + +sub get_template_html { my ($extension) = @_; my $result; my @allnames; @@ -1024,13 +1208,9 @@ sub get_template_list { if ($extension eq 'survey' || $extension eq 'exam') { $glob_extension = 'problem'; } - my @files = glob($Apache::lonnet::perlvar{'lonIncludes'}. - '/templates/*.'.$glob_extension); - @files = map {[$_,&mt(&Apache::lonnet::metadata($_, 'title')), - (&Apache::lonnet::metadata($_, 'category')?&mt(&Apache::lonnet::metadata($_, 'category')):&mt('Miscellaneous')), - &mt(&Apache::lonnet::metadata($_, 'help'))]} (@files); - @files = sort {$a->[2].$a->[1] cmp $b->[2].$b->[1]} (@files); + my @files = &get_template_list($extension); my ($midpoint,$seconddiv,$numfiles); + my @noexamplelink = ('blank.problem','blank.library','script.library'); $numfiles = 0; foreach my $file (@files) { next if ($file->[1] !~ /\S/); @@ -1045,15 +1225,22 @@ sub get_template_list { } my $count = 0; my $currentcategory=''; + my $first = 1; + my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'}; foreach my $file (@files) { next if ($file->[1] !~ /\S/); if ($file->[2] ne $currentcategory) { $currentcategory=$file->[2]; if ((!$seconddiv) && ($count >= $midpoint)) { - $result .= ''."\n".'
'."\n"; + $result .= '
'."\n".'
'."\n"; $seconddiv = 1; + } elsif (!$first) { + $result.='
'."\n"; + } else { + $first = 0; } - $result.='

'.$currentcategory.'

'; + $result.= '
'."\n" + .'

'.$currentcategory.'

'."\n"; $count++; } $result .= @@ -1062,13 +1249,20 @@ sub get_template_list { if ($file->[3]) { $result.=&Apache::loncommon::help_open_topic($file->[3]); } + # Provide example link my $filename=$file->[0]; - $filename=~s/^\/home\/httpd\/html//; - $result.=' '.&mt('Example').'
'."\n"; + $filename=~s{^\Q$londocroot\E}{}; + if (!(grep($filename =~ /\Q$_\E$/,@noexamplelink))) { + $result .= ' ' + .&Apache::loncommon::modal_link( + $filename.'?inhibitmenu=yes',&mt('Example'),600,420,'sample') + .''; + } + $result .= '
'."\n"; $count ++; } if ($numfiles > 0) { - $result .= '
'."\n".''."\n"; + $result .= ''."\n".''."\n"; } return $result; } @@ -1076,6 +1270,12 @@ sub get_template_list { sub newproblem { my ($request) = @_; + if ($env{'form.mode'} eq 'blank'){ + my $dest = &Apache::lonnet::filelocation("",$request->uri); + &File::Copy::copy('/home/httpd/html/res/adm/includes/templates/blank.problem',$dest); + &renderpage($request,$dest); + return; + } if ($env{'form.template'}) { my $file = $env{'form.template'}; my $dest = &Apache::lonnet::filelocation("",$request->uri); @@ -1086,7 +1286,7 @@ sub newproblem { my ($extension) = ($request->uri =~ m/\.(\w+)$/); &Apache::lonxml::debug("Looking for :$extension:"); - my $templatelist=&get_template_list($extension); + my $templatelist=&get_template_html($extension); if ($env{'form.newfile'} && !$templatelist) { # no templates found my $templatefilename = @@ -1097,31 +1297,36 @@ sub newproblem { &renderpage($request,$dest); } else { my $url=&HTML::Entities::encode($request->uri,'<>&"'); - my $shownurl=$url; - $shownurl=~s-^/~-/priv/-; my $dest = &Apache::lonnet::filelocation("",$request->uri); my $errormsg; my $instructions; + my $brcrum = [{'href' => &Apache::loncommon::authorspace($request->uri), + 'text' => 'Authoring Space'}, + {'href' => '', + 'text' => "Create New $extension"}]; my $start_page = - &Apache::loncommon::start_page("Create New $extension"); - $request->print(" -$start_page -

".&mt("Creating a new $extension resource.")."

+ &Apache::loncommon::start_page("Create New $extension", + undef, + {'bread_crumbs' => $brcrum,}); + $request->print( + $start_page + .&Apache::loncommon::head_subbox( + &Apache::loncommon::CSTR_pageheader()) + .'

'.&mt("Creating a new $extension resource.")."

$errormsg ".&mt("The requested file [_1] currently does not exist.", - "$shownurl")." -

- -".&mt("To create a new $extension, select a template from the". - " list below. Then click on the \"Create $extension\" button.")." -

"); + ''.$url.'').' +

+'.&mt("To create a new $extension, select a template from the". + " list below. Then click on the \"Create $extension\" button.").' +

'); if (defined($templatelist)) { $request->print($templatelist); } $request->print('
'); - $request->print("

".&Apache::loncommon::end_page()); + $request->print('
'.&Apache::loncommon::end_page()); } return; } @@ -1143,10 +1348,46 @@ sub update_construct_style { } } +# +# Sets interval for current user so time left will be zero, either for the entire folder +# containing the current resource, or just the resource, depending on value of first item +# in interval array retrieved from EXT("resource.0.interval"); +# +sub zero_timer { + my ($symb) = @_; + my ($hastimeleft,$first_access,$now); + my @interval=&Apache::lonnet::EXT("resource.0.interval"); + if (@interval > 1) { + if ($interval[1] eq 'course') { + return; + } else { + my $now = time; + my $first_access=&Apache::lonnet::get_first_access($interval[1],$symb); + if ($first_access > 0) { + if ($first_access+$interval[0] > $now) { + my $done_time = $now - $first_access; + my $snum = 1; + if ($interval[1] eq 'map') { + $snum = 2; + } + my $result = + &Apache::lonparmset::storeparm_by_symb_inner($symb,'0_interval', + $snum,$done_time, + 'date_interval', + $env{'user.name'}, + $env{'user.domain'}); + return $result; + } + } + } + } + return; +} sub handler { #my $t0 = [&gettimeofday()]; my $request=$_[0]; + $Apache::lonxml::request=$request; $Apache::lonxml::debug=$env{'user.debug'}; $env{'request.uri'}=$request->uri; @@ -1155,7 +1396,7 @@ sub handler { my $file=&Apache::lonnet::filelocation("",$request->uri); #check if we know where we are - if ($env{'request.course.fn'} && !&Apache::lonnet::symbread()) { + if ($env{'request.course.fn'} && !&Apache::lonnet::symbread('','',1,1)) { # if we are browsing we might not be able to know where we are if ($Apache::lonhomework::browse ne 'F' && $env{'request.state'} ne "construct") { @@ -1169,6 +1410,7 @@ sub handler { &unset_permissions(); return OK; } + &Apache::lonxml::debug("Permissions:$Apache::lonhomework::browse:$Apache::lonhomework::viewgrades:$Apache::lonhomework::modifygrades:$Apache::lonhomework::queuegrade"); &Apache::lonxml::debug("Problem Mode ".$env{'form.problemmode'}); my ($symb) = &Apache::lonnet::whichuser(); @@ -1181,7 +1423,10 @@ sub handler { #first visit to problem in construction space $env{'form.problemmode'}= 'view'; &renderpage($request,$file); - } elsif ($env{'form.problemmode'} eq 'editxml') { + } elsif (($env{'form.problemmode'} eq 'editxml') || + ($env{'form.problemmode'} eq 'saveeditxml') || + ($env{'form.problemmode'} eq 'saveviewxml') || + ($env{'form.problemmode'} eq 'undoxml')) { &editxmlmode($request,$file); } elsif ($env{'form.problemmode'} eq 'calcanswers') { &analyze($request,$file); @@ -1190,10 +1435,18 @@ sub handler { &renderpage($request,$file); } } else { + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['mode']); # requested file doesn't exist in contruction space &newproblem($request); } } 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 + if ($symb && $env{'form.LC_interval_done'} eq 'true') { + &zero_timer($symb); + undef($env{'form.LC_interval_done'}); + } # just render the page normally outside of construction space &Apache::lonxml::debug("not construct"); &renderpage($request,$file); @@ -1207,5 +1460,175 @@ sub handler { } +sub template_dropdown_datastructure { + # gathering the all templates and their path, title, category and help topic + my @templates = get_template_list('problem'); + # template category => title + my %tmplthash = (); + # template title => path + my %tmpltcontent = (); + + foreach my $template (@templates){ + # put in hash if the template is not empty + unless ($template->[1] eq ''){ + push(@{$tmplthash{$template->[2]}}, $template->[1]); + push(@{$tmpltcontent{$template->[1]}},$template->[0]); + } + } + + my $catList = []; + foreach my $cat (sort keys %tmplthash) { + my $catItems = []; + foreach my $title (sort @{$tmplthash{$cat}}) { + my $path = $tmpltcontent{$title}->[0]; + my $code; + open(FH, "<$path"); + while(){ + $code.= $_ unless $_ =~ /()|(<\/problem>)/; + } + close(FH); + + if ($code ne '') { + my $href = 'javascript:insertText(\'' . &convert_for_js(&HTML::Entities::encode($code,'<>&"')) . '\')'; + my $currItem = [$href, $title, undef]; + push @{$catItems}, $currItem; + } + } + push @{$catList}, [$catItems, $cat, undef]; + } + + return $catList; +} + +sub responseblock_dropdown_datastructure { + + my $mathCat = [ + [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_formularesponse())) . "\')", &mt("Formula Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_functionplotresponse())) . "\')", &mt("Function Plot Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_mathresponse())) . "\')", &mt("Math Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_numericalresponse())) . "\')", &mt("Numerical Response"), undef] + ], + &mt("Math"), + undef + ]; + + my $miscCat = [ + [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_imageresponse())) . "\')", &mt("Click on Image"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_customresponse())) . "\')", &mt("Custom Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_externalresponse())) . "\')", &mt("External Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_matchresponse())) . "\')", &mt("Match Two Lists"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_radiobuttonresponse())) . "\')", &mt("One out of N statements"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_optionresponse())) . "\')", &mt("Select from Options"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_rankresponse())) . "\')", &mt("Rank Values"), undef] + ], + &mt("Miscellaneous"), + undef + ]; + + my $chemCat = [ + [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_reactionresponse())) . "\')", &mt("Chemical Reaction"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_organicresponse())) . "\')", &mt("Organic Chemical Structure"), undef] + ], + &mt("Chemistry"), + undef + ]; + + my $textCat = [ + [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_stringresponse())) . "\')", &mt("String Response"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_essayresponse())) . "\')", &mt("Essay"), undef] + ], + &mt("Text"), + undef + ]; + + return [$mathCat, $miscCat, $chemCat, $textCat]; +} + + +sub conditional_scripting_datastructure { +# TODO: corresponding routines should be used for the javascript:insertText parts +# instead of the placeholder routine default_xml_tag with the tags +# e.g. &default_xml_tag("postanswerdate") should be replaced with a routine which +# returns the corresponding content for this case + +#TODO translated is currently temporarily here, another solution should be found where the +# needed string can be retrieved + + my $translatedTag = ' + + + +'; + return [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode($translatedTag)) . "\')", &mt("Translated Block"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("block"))) . "\')", &mt("Conditional Block"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("postanswerdate"))) . "\')", &mt("After Answer Date Block"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("preduedate"))) . "\')", &mt("Before Due Date Block"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("solved"))) . "\')", &mt("Block For After Solved"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("notsolved"))) . "\')", &mt("Block For When Not Solved"), undef] + ]; +} + +sub misc_datastructure { + return [ + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_img())) . "\')", &mt("Image"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::lonplot::insert_gnuplot())) . "\')", &mt("GNU Plot"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_organicstructure())) . "\')", &mt("Organic Structure"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::edit::insert_script())) . "\')", &mt("Script Block"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("allow"))) . "\')", &mt("File Dependencies"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("import"))) . "\')", &mt("Import a File"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&Apache::londefdef::insert_meta())) . "\')", &mt("Custom Metadata"), undef], + ["javascript:insertText(\'" . &convert_for_js(&HTML::Entities::encode(&default_xml_tag("part"))) . "\')", &mt("Problem Part"), undef] + ]; +} + +# helper routine for the datastructure building subroutines +sub default_xml_tag { + my ($tag) = @_; + return "\n<$tag>"; +} + + +sub helpmenu_datastructure { + + my $width = 500; + my $height = 600; + + my $helpers = [ + ['Problem_LON-CAPA_Functions', &mt('Script Functions')], + ['Greek_Symbols', &mt('Greek Symbols')], + ['Other_Symbols', &mt('Other Symbols')], + ['Authoring_Output_Tags', &mt('Output Tags')], + ['Authoring_Multilingual_Problems', + &mt('How to create problems in different languages')] + ]; + + my $help_structure = []; + + foreach my $count (0..(scalar(@{$helpers})-1)) { + my $filename = $helpers->[$count]->[0]; + my $title = $helpers->[$count]->[1]; + my $href = &HTML::Entities::encode("javascript:openMyModal('/adm/help/$filename.hlp',$width,$height,'yes');"); + push @{$help_structure}, [$href, $title, undef]; + } + + return $help_structure; +} + +# we need substitution to not break javascript code +sub convert_for_js { + my $return = shift; + $return =~ s|script|ESCAPEDSCRIPT|g; + $return =~ s|\\|\\\\|g; + $return =~ s|\n|\\r\\n|g; + $return =~ s|'|\\'|g; + $return =~ s|'|\\'|g; + return $return; +} + 1; __END__