--- loncom/homework/structuretags.pm 2023/12/29 23:47:02 1.512.2.24.2.7 +++ loncom/homework/structuretags.pm 2024/03/01 17:05:45 1.512.2.24.2.14 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: structuretags.pm,v 1.512.2.24.2.7 2023/12/29 23:47:02 raeburn Exp $ +# $Id: structuretags.pm,v 1.512.2.24.2.14 2024/03/01 17:05:45 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -406,7 +406,7 @@ sub page_start { if (&Apache::lonhtmlcommon::htmlareabrowser()) { my %textarea_args; if (($env{'request.state'} ne 'construct') || - ($env{'environment.nocodemirror'})) { + (&Apache::loncommon::nocodemirror())) { %textarea_args = ( dragmath => 'math', ); @@ -514,23 +514,25 @@ sub page_start { } elsif (!defined($found{'body'}) && $env{'request.state'} eq 'construct') { if ($target eq 'web' || $target eq 'edit') { - # Breadcrumbs for Authoring Space - &Apache::lonhtmlcommon::clear_breadcrumbs(); - &Apache::lonhtmlcommon::add_breadcrumb({ - 'text' => 'Authoring Space', - 'href' => &Apache::loncommon::authorspace($env{'request.uri'}), - }); - # breadcrumbs (and tools) will be created - # in start_page->bodytag->innerregister + unless ($env{'form.inhibitmenu'} eq 'yes') { + # Breadcrumbs for Authoring Space + &Apache::lonhtmlcommon::clear_breadcrumbs(); + &Apache::lonhtmlcommon::add_breadcrumb({ + 'text' => 'Authoring Space', + 'href' => &Apache::loncommon::authorspace($env{'request.uri'}), + }); + # breadcrumbs (and tools) will be created + # in start_page->bodytag->innerregister # FIXME Where are we? -# &Apache::lonhtmlcommon::add_breadcrumb({ -# 'text' => 'Problem Editing', # 'Problem Testing' -# 'href' => '', -# }); - $pageheader =&Apache::loncommon::head_subbox( - &Apache::loncommon::CSTR_pageheader()); - } +# &Apache::lonhtmlcommon::add_breadcrumb({ +# 'text' => 'Problem Editing', # 'Problem Testing' +# 'href' => '', +# }); + $pageheader = &Apache::loncommon::head_subbox( + &Apache::loncommon::CSTR_pageheader()); + } + } } elsif (!defined($found{'body'})) { my %add_entries; my $background=&Apache::lonxml::get_param('background',$parstack, @@ -693,7 +695,7 @@ sub setup_rndseed { } $env{'form.'.$Apache::inputtags::part.'.rndseed'}=$rndseed; } - if ( ($env{'form.resetdata'} eq &mt('New Problem Variation') + if ( ($env{'form.resetdata'} eq 'new_problem_variation' && $env{'form.submitted'} eq 'yes') || $env{'form.newrandomization'} eq &mt('New Randomization')) { srand(time); @@ -776,13 +778,18 @@ sub problem_edit_action_button { sub problem_edit_buttons { my ($mode)=@_; + my %editors = &Apache::loncommon::permitted_editors(); # Buttons that save my $result = '
'; if ($mode eq 'editxml') { - $result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML'); + if ($editors{'xml'}) { + $result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML'); + } $result.=&problem_edit_action_button('subsaveview','saveviewxml','v','Save and View'); } else { - $result.=&problem_edit_action_button('subsaveedit','saveedit','s','Save and Edit'); + if ($editors{'edit'}) { + $result.=&problem_edit_action_button('subsaveedit','saveedit','s','Save and Edit'); + } $result.=&problem_edit_action_button('subsaveview','saveview','v','Save and View'); } $result.="\n
\n"; @@ -790,13 +797,23 @@ sub problem_edit_buttons { $result .= '
'. &problem_edit_action_button('subdiscview','discard','d','Discard Edits and View',1); if ($mode eq 'editxml') { - $result.=&problem_edit_action_button('subedit','edit','e','Edit',1); + if ($editors{'edit'}) { + $result.=&problem_edit_action_button('subedit','edit','e','Edit',1); + } + if ($editors{'daxe'}) { + $result.=&problem_edit_action_button('subdaxe','daxe','w','Edit with Daxe',1); + } $result.=&problem_edit_action_button('subundo','undoxml','u','Undo',1); - if ($env{'environment.nocodemirror'}) { + if (&Apache::loncommon::nocodemirror()) { $result.=&Apache::lonhtmlcommon::dragmath_button("LC_editxmltext",1); } } else { - $result.=&problem_edit_action_button('subeditxml','editxml','x','EditXML',1); + if ($editors{'xml'}) { + $result.=&problem_edit_action_button('subeditxml','editxml','x','EditXML',1); + } + if ($editors{'daxe'}) { + $result.=&problem_edit_action_button('subdaxe','daxe','w','Edit with Daxe',1); + } $result.=&problem_edit_action_button('subundo','undo','u','Undo',1); } $result.="\n
"; @@ -810,9 +827,9 @@ sub problem_edit_header {
'.&mt('Problem Editing').$mode.&Apache::loncommon::help_open_menu('Problem Editing','Problem_Editor_XML_Index',5,'Authoring').' -
'. - ''. - &problem_edit_buttons(); +
'. + ''. + &problem_edit_buttons(); $return .= '
' . &Apache::lonxml::message_location(); $return .= ' @@ -869,6 +886,7 @@ sub option { sub problem_web_to_edit_header { my ($rndseed)=@_; + my %editors = &Apache::loncommon::permitted_editors(); my $result .= '
'; if (!$Apache::lonhomework::parsing_a_task) { @@ -968,7 +986,8 @@ $show_all
- +
@@ -997,10 +1016,21 @@ $show_all
'; $result.=''; - $result .= ''; - $result .= ''; + if ($editors{'edit'}) { + $result .= ''; + } + if ($editors{'xml'}) { + $result .= ''; + } + if (($editors{'daxe'}) && + ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9)) { + my $uri = $env{'request.uri'}; + my $daxeurl = '/daxepage'.$uri; + $result .= ''; + } $result.='

@@ -1027,8 +1057,8 @@ sub initialize_storage { || $Apache::lonhomework::type eq 'practice') { my $namespace = $symb || $env{'request.uri'}; - if ($env{'form.resetdata'} eq &mt('Reset Submissions') || - ($env{'form.resetdata'} eq &mt('New Problem Variation') + if ($env{'form.resetdata'} eq 'reset_submissions' || + ($env{'form.resetdata'} eq 'new_problem_variation' && $env{'form.submitted'} eq 'yes') || $env{'form.newrandomization'} eq &mt('New Randomization')) { &Apache::lonnet::tmpreset($namespace,'',$domain,$name); @@ -1368,20 +1398,30 @@ sub needs_linkprot_passback { $lti_in_use = $domlti{$itemnum}; } my ($state,$others,$listed,$scope,$protect,$display,$target,$exit) = split(/,/,$deeplink); - my $passback; - if ($scope eq 'resource') { + my ($passback,$pbscope); + if ($scope eq 'res') { if ($deeplink_symb eq $symb) { $passback = 1; + $pbscope = 'resource'; } } elsif ($scope eq 'map') { if (&Apache::lonnet::clutter($deeplink_map) eq $map) { $passback = 1; + $pbscope = 'nonrec'; + } + } elsif ($scope eq 'rec') { + if (&Apache::lonnet::clutter($deeplink_map) eq $map) { + $passback = 1; + $pbscope = 'map'; + } else { + my @recurseup = &Apache::lonnet::get_map_hierarchy($map,$env{'request.course.id'}); + if (grep(/^\Q$deeplink_map\E$/,@recurseup)) { + $passback = 1; + $pbscope = 'map'; + } } - } elsif ($scope eq 'recurse') { -#FIXME check if $deeplink_map contains $map - $passback = 1; } - return ($passback,$scope,$deeplink_map,$deeplink_symb,$crsdef,$itemnum,$lti_in_use); + return ($passback,$pbscope,$deeplink_map,$deeplink_symb,$crsdef,$itemnum,$lti_in_use); } } } @@ -1523,6 +1563,99 @@ sub store_aggregates { } } +sub access_status_msg { + my ($mode,$status,$symb,$target,$ipused,$accessmsg) = @_; + my $msg; + if ($target eq 'web') { + if ($status eq 'UNAVAILABLE') { + $msg.='

'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'

'; + } elsif ($status eq 'NOT_IN_A_SLOT') { + $msg.='

'.&mt('You are not currently signed up to work at this time and/or place.').'

'; + } elsif (($status eq 'RESERVABLE') || ($status eq 'RESERVABLE_LATER') || + ($status eq 'NOTRESERVABLE')) { + $msg.='

'.&mt('Access requires reservation to work at specific time/place.').'

'; + } elsif ($status ne 'NOT_YET_VIEWED') { + $msg.='

'.&mt('Not open to be viewed').'

'; + } + if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { + $msg.=&mt('The problem ').$accessmsg; + } elsif ($status eq 'UNCHECKEDOUT') { + $msg.=&checkout_msg(); + } elsif ($status eq 'NOT_YET_VIEWED') { + $msg.=&firstaccess_msg($accessmsg,$symb); + } elsif ($status eq 'NOT_IN_A_SLOT') { + $msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); + } elsif ($status eq 'RESERVABLE') { + $msg.=&mt('Available to make a reservation.').' '.&mt('Reservation window closes [_1].', + &Apache::lonnavmaps::timeToHumanString($accessmsg,'end')). + '
'. + &Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); + } elsif ($status eq 'RESERVABLE_LATER') { + $msg.=&mt('Window to make a reservation will open [_1].', + &Apache::lonnavmaps::timeToHumanString($accessmsg,'start')); + } elsif ($status eq 'NOTRESERVABLE') { + $msg.=&mt('Not available to make a reservation.'); + } + $msg.='
'; + } elsif ($target eq 'tex') { + my $startminipage = ($env{'form.problem_split'}=~/yes/i)? '' + : '\begin{minipage}{\textwidth}'; + + $msg ='\noindent \vskip 1 mm '. + $startminipage.'\vskip 0 mm'; + if ($status eq 'UNAVAILABLE') { + $msg.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.'); + } elsif ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { + $msg.=&mt('Problem is not open to be viewed. It')." $accessmsg"; + } else { + $msg.=&mt('Problem is not open to be viewed.'); + } + $msg .= " \\vskip 0 mm "; + } + return $msg; +} + +sub checkin_prompt { + my ($target,$slot_name,$slot,$type) = @_; + my $result; + if ($target eq 'web') { + $result = &Apache::bridgetask::proctor_validation_screen($slot); + } elsif ($target eq 'grade') { + if (!&Apache::bridgetask::proctor_check_auth($slot_name,$slot,$type)) { + $result = &mt('An error occurred during check-in'); + } + } + return $result; +} + +sub selfcheckin_resource { + my ($resource_due,$slot_name,$slot,$symb) = @_; + if ($slot_name ne '') { + my $checked_in = + $Apache::lonhomework::history{'resource.0.checkedin'}; + if ($checked_in eq '') { + # unproctored slot access, self checkin + my $check = &Apache::bridgetask::check_in('problem',undef,undef, + $slot_name); + if ($check =~ /^error: /) { + &Apache::lonnet::logthis("Error during self-checkin of problem (symb: $symb) using slot: $slot_name"); + } else { + $checked_in = $Apache::lonhomework::results{"resource.0.checkedin"}; + } + } + if ((ref($slot) eq 'HASH') && ($checked_in ne '')) { + if ($slot->{'starttime'} < time()) { + if (!$resource_due) { + $resource_due = $slot->{'endtime'}; + } elsif ($slot->{'endtime'} < $resource_due) { + $resource_due = $slot->{'endtime'}; + } + } + } + } + return $resource_due; +} + sub checkout_msg { my %lt=&Apache::lonlocal::texthash( 'resource'=>'The resource needs to be checked out', @@ -1816,8 +1949,8 @@ sub start_problem { } $form_tag_start.=''. - ''; + ''; if (exists($env{'form.username'})) { $form_tag_start.= ''; - } elsif ($status eq 'NOT_IN_A_SLOT') { - $msg.='

'.&mt('You are not currently signed up to work at this time and/or place.').'

'; - } elsif (($status eq 'RESERVABLE') || ($status eq 'RESERVABLE_LATER') || - ($status eq 'NOTRESERVABLE')) { - $msg.='

'.&mt('Access requires reservation to work at specific time/place.').'

'; - } elsif ($status ne 'NOT_YET_VIEWED') { - $msg.='

'.&mt('Not open to be viewed').'

'; - } - if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { - $msg.=&mt('The problem ').$accessmsg; - } elsif ($status eq 'UNCHECKEDOUT') { - $msg.=&checkout_msg(); - } elsif ($status eq 'NOT_YET_VIEWED') { - if ($firstaccres) { - $msg .= '

'. - &mt('A problem occurred when trying to start the timer.').'

'; - } - $msg.=&firstaccess_msg($accessmsg,$symb); - } elsif ($status eq 'NOT_IN_A_SLOT') { - $msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); - } elsif ($status eq 'RESERVABLE') { - $msg.=&mt('Available to make a reservation.').' '.&mt('Reservation window closes [_1].', - &Apache::lonnavmaps::timeToHumanString($accessmsg,'end')). - '
'. - &Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); - } elsif ($status eq 'RESERVABLE_LATER') { - $msg.=&mt('Window to make a reservation will open [_1].', - &Apache::lonnavmaps::timeToHumanString($accessmsg,'start')); - } elsif ($status eq 'NOTRESERVABLE') { - $msg.=&mt('Not available to make a reservation.'); - } - $result.=$msg.'
'; - } elsif ($target eq 'tex') { - my $startminipage = ($env{'form.problem_split'}=~/yes/i)? '' - : '\begin{minipage}{\textwidth}'; - $result.='\noindent \vskip 1 mm '. - $startminipage.'\vskip 0 mm'; - if ($status eq 'UNAVAILABLE') { - $result.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm '; - } else { - $result.=&mt('Problem is not open to be viewed. It')." $accessmsg \\vskip 0 mm "; - } - } + if (($status eq 'NOT_YET_VIEWED') && ($firstaccres)) { + $result .= '

'. + &mt('A problem occurred when trying to start the timer.').'

'; + } + $result .= &access_status_msg('problem',$status,$symb,$target,'',$accessmsg); } elsif ($status eq 'NEEDS_CHECKIN') { my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, $style); - if ($target eq 'web') { - $result .= - &Apache::bridgetask::proctor_validation_screen($slot); - } elsif ($target eq 'grade') { - &Apache::bridgetask::proctor_check_auth($slot_name,$slot, - 'problem'); - } + $result .= &checkin_prompt($target,$slot_name,$slot,'problem'); } elsif ($target eq 'web') { if ($status eq 'CAN_ANSWER') { $resource_due = &Apache::lonhomework::due_date(0, $env{'request.symb'}); if ($slot_name ne '') { - my $checked_in = - $Apache::lonhomework::history{'resource.0.checkedin'}; - if ($checked_in eq '') { - # unproctored slot access, self checkin - &Apache::bridgetask::check_in('problem',undef,undef, - $slot_name); - $checked_in = - $Apache::lonhomework::results{"resource.0.checkedin"}; - } - if ((ref($slot) eq 'HASH') && ($checked_in ne '')) { - if ($slot->{'starttime'} < time()) { - if (!$resource_due) { - $resource_due = $slot->{'endtime'}; - } elsif ($slot->{'endtime'} < $resource_due) { - $resource_due = $slot->{'endtime'}; - } - } - } + $resource_due = &selfcheckin_resource($resource_due,$slot_name,$slot, + $env{'request.symb'}); } if ($resource_due) { my $time_left = $resource_due - time(); @@ -1960,10 +2029,15 @@ sub start_problem { ''; # create a page header and exit if ($env{'request.state'} eq "construct") { - $result.= &problem_web_to_edit_header($env{'form.rndseed'}); + if ($env{'form.inhibitmenu'} eq 'yes') { + # error messages can be useful in any case + $result.= &Apache::lonxml::message_location(); + } else { + $result.= &problem_web_to_edit_header($env{'form.rndseed'}); + } if ($Apache::lonhomework::type eq 'practice') { - $result.= ''. + $result.= ''. &practice_problem_header().'
'; } elsif ($Apache::lonhomework::type eq 'randomizetry') { my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries"); @@ -1990,8 +2064,6 @@ sub start_problem { } elsif ($target eq 'tex') { $result .= 'INSERTTEXFRONTMATTERHERE'; $result .= &select_metadata_hyphenation(); - - } } elsif ($target eq 'edit') { $result .= $form_tag_start.&problem_edit_header(); @@ -2271,8 +2343,8 @@ sub start_library { ''; $result.=&problem_web_to_edit_header($rndseed); if ($Apache::lonhomework::type eq 'practice') { - $result.= ''. + $result.= ''. &practice_problem_header().'
'; } } @@ -3224,7 +3296,7 @@ sub end_startouttext { .&Apache::edit::deletelist($target,$token) .'' .''; - if ($env{'environment.nocodemirror'}) { + if (&Apache::loncommon::nocodemirror()) { $result.=&Apache::lonhtmlcommon::dragmath_button($areaid,1); } else { $result.=' ';