Annotation of loncom/interface/lonparmset.pm, revision 1.618

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.618   ! raeburn     4: # $Id: lonparmset.pm,v 1.617 2023/04/03 15:32:54 raeburn Exp $
1.40      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.617     raeburn   332: use Text::Wrap();
1.416     jms       333: use LONCAPA qw(:DEFAULT :match);
                    334: 
                    335: 
1.560     damieng   336: ##################################################
                    337: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    338: ##################################################
                    339: 
                    340: # Page header
1.561     damieng   341: #
                    342: # @param {Apache2::RequestRec} $r - Apache request object
                    343: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    344: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       345: sub startSettingsScreen {
1.531     raeburn   346:     my ($r,$mode,$crstype)=@_;
1.507     www       347: 
1.531     raeburn   348:     my $tabtext = &mt('Course Settings');
                    349:     if ($crstype eq 'Community') {
                    350:         $tabtext = &mt('Community Settings');
                    351:     } 
1.507     www       352:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    353:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   354:                                           $tabtext.
1.507     www       355:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    356: 
1.523     raeburn   357:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       358:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    359:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   360:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       361: }
                    362: 
1.560     damieng   363: # Page footer
1.507     www       364: sub endSettingsScreen {
                    365:    my ($r)=@_;
                    366:    $r->print('</div></div></div>');
                    367: }
                    368: 
                    369: 
                    370: 
1.560     damieng   371: ##################################################
1.563     damieng   372: # (mostly) TABLE MODE
1.560     damieng   373: # (parmval is also used for the log of parameter changes)
                    374: ##################################################
                    375: 
1.566     damieng   376: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   377: #
                    378: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   379: # @param {string} $id - resource id or map pc
1.561     damieng   380: # @param {string} $def - the resource's default value for this parameter
                    381: # @param {string} $uname - user name
                    382: # @param {string} $udom - user domain
                    383: # @param {string} $csec - section name
                    384: # @param {string} $cgroup - group name
                    385: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    386: # @returns {Array}
1.2       www       387: sub parmval {
1.275     raeburn   388:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    389:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    390:                                                            $cgroup,$courseopt);
1.201     www       391: }
                    392: 
1.561     damieng   393: # Returns an array containing
                    394: # - the most specific level that is defined for that parameter (integer)
                    395: # - an array with the level as index and the parameter value as value (when defined)
                    396: #   (level 1 is the most specific and will have precedence)
                    397: #
                    398: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   399: # @param {string} $symb - resource symb or map src
1.561     damieng   400: # @param {string} $def - the resource's default value for this parameter
                    401: # @param {string} $uname - user name
                    402: # @param {string} $udom - user domain
                    403: # @param {string} $csec - section name
                    404: # @param {string} $cgroup - group name
                    405: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    406: # @returns {Array}
1.201     www       407: sub parmval_by_symb {
1.275     raeburn   408:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       409: 
1.352     albertel  410:     my $useropt;
                    411:     if ($uname ne '' && $udom ne '') {
1.561     damieng   412:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  413:     }
1.200     www       414: 
1.8       www       415:     my $result='';
1.44      albertel  416:     my @outpar=();
1.2       www       417: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    418:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  419:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   420:     
                    421:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    422:     # any change should be reflected there.
                    423:     
1.201     www       424:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   425:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       426:     my $mapparm=$map.'___(all).'.$what;
1.10      www       427: 
1.269     raeburn   428:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    429:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   430:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   431:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    432: 
1.190     albertel  433:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    434:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   435:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  436:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    437: 
                    438:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    439:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   440:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  441:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       442: 
1.11      www       443: 
1.182     albertel  444: # --------------------------------------------------------- first, check course
1.11      www       445: 
1.561     damieng   446: # 18 - General Course
1.200     www       447:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   448:         $outpar[18]=$$courseopt{$courselevel};
                    449:         $result=18;
                    450:     }
                    451: 
1.561     damieng   452: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   453:     if (defined($$courseopt{$courseleveli})) {
                    454:         $outpar[17]=$$courseopt{$courseleveli};
                    455:         $result=17;
1.43      albertel  456:     }
1.11      www       457: 
1.561     damieng   458: # 16 - Map or Folder level in course (non-recursive)
1.200     www       459:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   460:         $outpar[16]=$$courseopt{$courselevelm};
                    461:         $result=16;
1.43      albertel  462:     }
1.11      www       463: 
1.182     albertel  464: # ------------------------------------------------------- second, check default
                    465: 
1.561     damieng   466: # 15 - resource default
1.556     raeburn   467:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  468: 
                    469: # ------------------------------------------------------ third, check map parms
                    470: 
1.556     raeburn   471:     
1.561     damieng   472: # 14 - map default
1.376     albertel  473:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   474:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  475: 
1.561     damieng   476: # 13 - resource level in course
1.200     www       477:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   478:         $outpar[13]=$$courseopt{$courselevelr};
                    479:         $result=13;
1.43      albertel  480:     }
1.11      www       481: 
1.182     albertel  482: # ------------------------------------------------------ fourth, back to course
1.352     albertel  483:     if ($csec ne '') {
1.561     damieng   484: # 12 - General for section
1.200     www       485:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   486:             $outpar[12]=$$courseopt{$seclevel};
                    487:             $result=12;
                    488:         }
1.561     damieng   489: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   490:         if (defined($$courseopt{$secleveli})) {
                    491:             $outpar[11]=$$courseopt{$secleveli};
                    492:             $result=11;
                    493:         }
1.561     damieng   494: # 10 - Map or Folder level for section (non-recursive)
1.200     www       495:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   496:             $outpar[10]=$$courseopt{$seclevelm};
                    497:             $result=10;
                    498:         }
1.561     damieng   499: # 9 - resource level in section
1.200     www       500:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   501:             $outpar[9]=$$courseopt{$seclevelr};
                    502:             $result=9;
                    503:         }
1.43      albertel  504:     }
1.275     raeburn   505: # ------------------------------------------------------ fifth, check course group
1.352     albertel  506:     if ($cgroup ne '') {
1.561     damieng   507: # 8 - General for group
1.269     raeburn   508:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   509:             $outpar[8]=$$courseopt{$grplevel};
                    510:             $result=8;
                    511:         }
1.561     damieng   512: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   513:         if (defined($$courseopt{$grpleveli})) {
                    514:             $outpar[7]=$$courseopt{$grpleveli};
                    515:             $result=7;
1.269     raeburn   516:         }
1.561     damieng   517: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   518:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   519:             $outpar[6]=$$courseopt{$grplevelm};
                    520:             $result=6;
1.269     raeburn   521:         }
1.561     damieng   522: # 5 - resource level in group
1.269     raeburn   523:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   524:             $outpar[5]=$$courseopt{$grplevelr};
                    525:             $result=5;
1.269     raeburn   526:         }
                    527:     }
1.11      www       528: 
1.556     raeburn   529: # ---------------------------------------------------------- sixth, check user
1.11      www       530: 
1.352     albertel  531:     if ($uname ne '') {
1.561     damieng   532: # 4 - General for specific student
                    533:         if (defined($$useropt{$courselevel})) {
                    534:             $outpar[4]=$$useropt{$courselevel};
                    535:             $result=4;
                    536:         }
1.556     raeburn   537: 
1.561     damieng   538: # 3 - Map or Folder level for specific student (recursive)
                    539:         if (defined($$useropt{$courseleveli})) {
                    540:             $outpar[3]=$$useropt{$courseleveli};
                    541:             $result=3;
                    542:         }
1.473     amueller  543: 
1.561     damieng   544: # 2 - Map or Folder level for specific student (non-recursive)
                    545:         if (defined($$useropt{$courselevelm})) {
                    546:             $outpar[2]=$$useropt{$courselevelm};
                    547:             $result=2;
                    548:         }
1.473     amueller  549: 
1.561     damieng   550: # 1 - resource level for specific student
                    551:         if (defined($$useropt{$courselevelr})) {
                    552:             $outpar[1]=$$useropt{$courselevelr};
                    553:             $result=1;
                    554:         }
1.43      albertel  555:     }
1.44      albertel  556:     return ($result,@outpar);
1.2       www       557: }
                    558: 
1.198     www       559: 
                    560: 
1.376     albertel  561: # --- Caches local to lonparmset
                    562: 
1.446     bisitz    563: 
1.561     damieng   564: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  565: sub reset_caches {
                    566:     &resetparmhash();
                    567:     &resetsymbcache();
                    568:     &resetrulescache();
1.203     www       569: }
                    570: 
1.561     damieng   571: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    572: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  573: {
1.561     damieng   574:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    575:     my %parmhash; # the parameter cache
                    576:     # reset map parameter hash
1.376     albertel  577:     sub resetparmhash {
1.560     damieng   578:         undef($parmhashid);
                    579:         undef(%parmhash);
1.376     albertel  580:     }
1.446     bisitz    581: 
1.561     damieng   582:     # dump the _parms.db database into %parmhash
1.376     albertel  583:     sub cacheparmhash {
1.560     damieng   584:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    585:         my %parmhashfile;
                    586:         if (tie(%parmhashfile,'GDBM_File',
                    587:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    588:             %parmhash=%parmhashfile;
                    589:             untie(%parmhashfile);
                    590:             $parmhashid=$env{'request.course.fn'};
                    591:         }
1.201     www       592:     }
1.446     bisitz    593: 
1.561     damieng   594:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  595:     sub parmhash {
1.560     damieng   596:         my ($id) = @_;
                    597:         &cacheparmhash();
                    598:         return $parmhash{$id};
1.376     albertel  599:     }
1.560     damieng   600: }
1.376     albertel  601: 
1.566     damieng   602: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    603: {
1.561     damieng   604:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    605:     my %symbs; # hash id->symb
                    606:     # reset the id->symb cache
1.376     albertel  607:     sub resetsymbcache {
1.560     damieng   608:         undef($symbsid);
                    609:         undef(%symbs);
1.376     albertel  610:     }
1.446     bisitz    611: 
1.566     damieng   612:     # returns the resource symb or map src corresponding to a resource id or map pc
                    613:     # (using lonnavmaps and a cache)
1.376     albertel  614:     sub symbcache {
1.560     damieng   615:         my $id=shift;
                    616:         if ($symbsid ne $env{'request.course.id'}) {
                    617:             undef(%symbs);
                    618:         }
                    619:         if (!$symbs{$id}) {
                    620:             my $navmap = Apache::lonnavmaps::navmap->new();
                    621:             if ($id=~/\./) {
                    622:                 my $resource=$navmap->getById($id);
                    623:                 $symbs{$id}=$resource->symb();
                    624:             } else {
                    625:                 my $resource=$navmap->getByMapPc($id);
                    626:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    627:             }
                    628:             $symbsid=$env{'request.course.id'};
1.473     amueller  629:         }
1.560     damieng   630:         return $symbs{$id};
1.473     amueller  631:     }
1.560     damieng   632: }
1.201     www       633: 
1.561     damieng   634: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    635: {
1.561     damieng   636:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    637:     my %rules; # parameter default actions hash
1.376     albertel  638:     sub resetrulescache {
1.560     damieng   639:         undef($rulesid);
                    640:         undef(%rules);
1.376     albertel  641:     }
1.446     bisitz    642: 
1.561     damieng   643:     # returns the value for a given key in the parameter default action hash
1.376     albertel  644:     sub rulescache {
1.560     damieng   645:         my $id=shift;
                    646:         if ($rulesid ne $env{'request.course.id'}
                    647:             && !defined($rules{$id})) {
                    648:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    649:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    650:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    651:             $rulesid=$env{'request.course.id'};
                    652:         }
                    653:         return $rules{$id};
1.221     www       654:     }
                    655: }
                    656: 
1.416     jms       657: 
1.561     damieng   658: # Returns the values of the parameter type default action
                    659: # "default value when manually setting".
                    660: # If none is defined, ('','','','','') is returned.
                    661: #
                    662: # @param {string} $type - parameter type
                    663: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       664: sub preset_defaults {
                    665:     my $type=shift;
                    666:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   667:         # yes, there is something
                    668:         return (&rulescache($type.'_hours'),
                    669:             &rulescache($type.'_min'),
                    670:             &rulescache($type.'_sec'),
                    671:             &rulescache($type.'_value'));
1.229     www       672:     } else {
1.560     damieng   673:         # nothing there or something else
                    674:         return ('','','','','');
1.229     www       675:     }
                    676: }
                    677: 
1.416     jms       678: 
1.561     damieng   679: # Checks that a date is after enrollment start date and before
                    680: # enrollment end date.
                    681: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    682: # This is used by both overview and table modes.
                    683: #
                    684: # @param {integer} $checkdate - the date to check.
                    685: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       686: sub date_sanity_info {
                    687:    my $checkdate=shift;
                    688:    unless ($checkdate) { return ''; }
                    689:    my $result='';
                    690:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    691:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    692:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    693:          $result.='<div class="LC_warning">'
                    694:                  .&mt('After course enrollment end!')
                    695:                  .'</div>';
1.277     www       696:       }
                    697:    }
                    698:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    699:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    700:          $result.='<div class="LC_warning">'
                    701:                  .&mt('Before course enrollment start!')
                    702:                  .'</div>';
1.277     www       703:       }
                    704:    }
1.413     bisitz    705: # Preparation for additional warnings about dates in the past/future.
                    706: # An improved, more context sensitive version is recommended,
                    707: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    708: #   if ($checkdate<time) {
                    709: #      $result.='<div class="LC_info">'
                    710: #              .'('.&mt('in the past').')'
                    711: #              .'</div>';
                    712: #      }
                    713: #   if ($checkdate>time) {
                    714: #      $result.='<div class="LC_info">'
                    715: #              .'('.&mt('in the future').')'
                    716: #              .'</div>';
                    717: #      }
1.277     www       718:    return $result;
                    719: }
1.561     damieng   720: 
                    721: 
                    722: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       723: #
1.566     damieng   724: # @param {string} $sresid - resource id or map pc
1.565     damieng   725: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   726: # @param {integer} $snum - level
                    727: # @param {string} $nval - new value
                    728: # @param {string} $ntype - new type
                    729: # @param {string} $uname - username
                    730: # @param {string} $udom - userdomain
                    731: # @param {string} $csec - section name
                    732: # @param {string} $cgroup - group name
1.186     www       733: sub storeparm {
1.269     raeburn   734:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   735:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       736: }
                    737: 
1.561     damieng   738: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    739: 
                    740: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    741: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    742: #
1.566     damieng   743: # @param {string} $symb - resource symb or map src
1.565     damieng   744: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   745: # @param {integer} $snum - level
                    746: # @param {string} $nval - new value
                    747: # @param {string} $ntype - new type
                    748: # @param {string} $uname - username
                    749: # @param {string} $udom - userdomain
                    750: # @param {string} $csec - section name
                    751: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    752: # @param {string} $cgroup - group name
1.197     www       753: sub storeparm_by_symb {
1.275     raeburn   754:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       755:     unless ($recflag) {
1.560     damieng   756:         # first time call
                    757:         %recstack=();
                    758:         $recflag=1;
1.226     www       759:     }
1.560     damieng   760:     # store parameter
1.226     www       761:     &storeparm_by_symb_inner
1.473     amueller  762:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   763:     # don't do anything if parameter was reset
1.266     www       764:     unless ($nval) { return; }
1.226     www       765:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   766:     # remember that this was set
1.226     www       767:     $recstack{$parm}=1;
1.560     damieng   768:     # what does this trigger?
1.226     www       769:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   770:         # don't backfire
                    771:         unless ((!$triggered) || ($recstack{$triggered})) {
                    772:             my $action=&rulescache($triggered.'_action');
                    773:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    774:             # set triggered parameter on same level
                    775:             my $newspnam=$prefix.$triggered;
                    776:             my $newvalue='';
                    777:             my $active=1;
                    778:             if ($action=~/^when\_setting/) {
                    779:             # are there restrictions?
                    780:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    781:                     $active=0;
1.565     damieng   782:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   783:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    784:                     }
                    785:                 }
                    786:                 $newvalue=&rulescache($triggered.'_value');
                    787:             } else {
                    788:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    789:                 if ($action=~/^later\_than/) {
                    790:                     $newvalue=$nval+$totalsecs;
                    791:                 } else {
                    792:                     $newvalue=$nval-$totalsecs;
                    793:                 }
                    794:             }
                    795:             if ($active) {
                    796:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    797:                         $uname,$udom,$csec,$recflag,$cgroup);
                    798:             }
                    799:         }
1.226     www       800:     }
                    801:     return '';
                    802: }
                    803: 
1.561     damieng   804: # Adds all given arguments to the course parameter log.
                    805: # @returns {string} - the answer to the lonnet query.
1.293     www       806: sub log_parmset {
1.525     raeburn   807:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       808: }
                    809: 
1.561     damieng   810: # Store a parameter value and type by symb, without using the parameter default actions.
                    811: # Expire related sheets.
                    812: #
1.566     damieng   813: # @param {string} $symb - resource symb or map src
1.561     damieng   814: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    815: # @param {integer} $snum - level
                    816: # @param {string} $nval - new value
                    817: # @param {string} $ntype - new type
                    818: # @param {string} $uname - username
                    819: # @param {string} $udom - userdomain
                    820: # @param {string} $csec - section name
                    821: # @param {string} $cgroup - group name
                    822: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       823: sub storeparm_by_symb_inner {
1.197     www       824: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   825:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       826: # ---------------------------------------------------------- Construct prefixes
1.186     www       827:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    828:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  829:     $map = &Apache::lonnet::deversion($map);
                    830: 
1.197     www       831:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   832:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       833:     my $mapparm=$map.'___(all).'.$spnam;
                    834: 
1.269     raeburn   835:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    836:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   837:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   838:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    839: 
1.190     albertel  840:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    841:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   842:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  843:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    844: 
1.190     albertel  845:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    846:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   847:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  848:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    849: 
1.186     www       850:     my $storeunder='';
1.578     raeburn   851:     my $possreplace='';
1.556     raeburn   852:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   853:     if (($snum==17) || ($snum==3)) { 
                    854:         $storeunder=$courseleveli;
                    855:         $possreplace=$courselevelm; 
                    856:     } 
                    857:     if (($snum==16) || ($snum==2)) { 
                    858:         $storeunder=$courselevelm;
                    859:         $possreplace=$courseleveli;
                    860:     }
1.556     raeburn   861:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    862:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   863:     if ($snum==11) { 
                    864:         $storeunder=$secleveli;
                    865:         $possreplace=$seclevelm; 
                    866:     }
                    867:     if ($snum==10) { 
                    868:         $storeunder=$seclevelm;
                    869:         $possreplace=$secleveli;
                    870:     }
1.556     raeburn   871:     if ($snum==9) { $storeunder=$seclevelr; }
                    872:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   873:     if ($snum==7) { 
                    874:         $storeunder=$grpleveli;
                    875:         $possreplace=$grplevelm;
                    876:     }
                    877:     if ($snum==6) {
                    878:         $storeunder=$grplevelm;
                    879:         $possreplace=$grpleveli;
                    880:     }
1.556     raeburn   881:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   882: 
1.446     bisitz    883: 
1.186     www       884:     my $delete;
                    885:     if ($nval eq '') { $delete=1;}
                    886:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  887:             $storeunder.'.type' => $ntype);
1.186     www       888:     my $reply='';
1.560     damieng   889:     
1.556     raeburn   890:     if ($snum>4) {
1.186     www       891: # ---------------------------------------------------------------- Store Course
                    892: #
1.560     damieng   893:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    894:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    895:         # Expire sheets
                    896:         &Apache::lonnet::expirespread('','','studentcalc');
                    897:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    898:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   899:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   900:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    901:         } else {
                    902:             &Apache::lonnet::expirespread('','','assesscalc');
                    903:         }
                    904:         # Store parameter
                    905:         if ($delete) {
                    906:             $reply=&Apache::lonnet::del
                    907:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    908:                 &log_parmset(\%storecontent,1);
                    909:         } else {
                    910:             $reply=&Apache::lonnet::cput
                    911:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    912:             &log_parmset(\%storecontent);
1.578     raeburn   913:             if ($possreplace) {
                    914:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    915:                 if (ref($resdata) eq 'HASH') {
                    916:                     if (exists($resdata->{$possreplace})) {
                    917:                         if (&Apache::lonnet::del
                    918:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    919:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    920:                         }
                    921:                     }
                    922:                 }
                    923:             }
1.560     damieng   924:         }
                    925:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       926:     } else {
                    927: # ------------------------------------------------------------------ Store User
                    928: #
1.560     damieng   929:         # Expire sheets
                    930:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    931:         if ($snum==1) {
                    932:             &Apache::lonnet::expirespread
                    933:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   934:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   935:             &Apache::lonnet::expirespread
                    936:             ($uname,$udom,'assesscalc',$map);
                    937:         } else {
                    938:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    939:         }
                    940:         # Store parameter
                    941:         if ($delete) {
                    942:             $reply=&Apache::lonnet::del
                    943:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    944:             &log_parmset(\%storecontent,1,$uname,$udom);
                    945:         } else {
                    946:             $reply=&Apache::lonnet::cput
                    947:             ('resourcedata',\%storecontent,$udom,$uname);
                    948:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   949:             if ($possreplace) {
                    950:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    951:                 if (ref($resdata) eq 'HASH') {
                    952:                     if (exists($resdata->{$possreplace})) {
                    953:                         if (&Apache::lonnet::del
                    954:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    955:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    956:                                           $uname,$udom);
                    957:                         }
                    958:                     }
                    959:                 }
                    960:             }
1.560     damieng   961:         }
                    962:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       963:     }
1.446     bisitz    964: 
1.186     www       965:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   966:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       967:     }
                    968:     return '';
                    969: }
                    970: 
1.9       www       971: 
1.561     damieng   972: # Returns HTML with the value of the given parameter,
                    973: # using a readable format for dates, and
                    974: # a warning if there is a problem with a date.
                    975: # Used by table mode.
                    976: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    977: #
                    978: # @param {string} $value - the parameter value
                    979: # @param {string} $type - the parameter type
                    980: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       981: sub valout {
1.600     raeburn   982:     my ($value,$type,$editable)=@_;
1.59      matthew   983:     my $result = '';
                    984:     # Values of zero are valid.
                    985:     if (! $value && $value ne '0') {
1.528     bisitz    986:         if ($editable) {
                    987:             $result =
                    988:                 '<img src="/res/adm/pages/editmap.png"'
                    989:                .' alt="'.&mt('Change').'"'
1.539     raeburn   990:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    991:         } else {
                    992:             $result='&nbsp;';
                    993:         }
1.59      matthew   994:     } else {
1.66      www       995:         if ($type eq 'date_interval') {
1.559     raeburn   996:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    997:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    998:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    999:                 $donebuttontext = $1;
                   1000:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1001:                 $usesdone = 'done';
                   1002:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1003:                 $donebuttontext = &mt('Done');
                   1004:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1005:             }
1.554     raeburn  1006:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1007:             my @timer;
1.66      www      1008:             $year=$year-70;
                   1009:             $mday--;
                   1010:             if ($year) {
1.413     bisitz   1011: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1012:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1013:             }
                   1014:             if ($mon) {
1.413     bisitz   1015: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1016:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1017:             }
                   1018:             if ($mday) {
1.413     bisitz   1019: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1020:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1021:             }
                   1022:             if ($hour) {
1.413     bisitz   1023: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1024:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1025:             }
                   1026:             if ($min) {
1.413     bisitz   1027: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1028:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1029:             }
                   1030:             if ($sec) {
1.413     bisitz   1031: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1032:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1033:             }
1.413     bisitz   1034: #           $result=~s/\s+$//;
                   1035:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1036:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1037:             }
                   1038:             $result.=join(", ",@timer);
1.559     raeburn  1039:             if ($usesdone eq 'done') {
1.558     raeburn  1040:                 if ($secretkey) {
1.559     raeburn  1041:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1042:                 } else {
1.559     raeburn  1043:                     $result .= ' + "'.$donebuttontext.'"';
                   1044:                 }
1.554     raeburn  1045:             }
1.213     www      1046:         } elsif (&isdateparm($type)) {
1.361     albertel 1047:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1048:                 &date_sanity_info($value);
1.59      matthew  1049:         } else {
                   1050:             $result = $value;
1.517     www      1051:             $result=~s/\,/\, /gs;
1.560     damieng  1052:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1053:         }
                   1054:     }
                   1055:     return $result;
1.9       www      1056: }
                   1057: 
1.59      matthew  1058: 
1.561     damieng  1059: # Returns HTML containing a link on a parameter value, for table mode.
                   1060: # The link uses the javascript function 'pjump'.
                   1061: #
                   1062: # @param {string} $type - parameter type
                   1063: # @param {string} $dis - dialog title for editing the parameter value and type
                   1064: # @param {string} $value - parameter value
                   1065: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1066: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1067: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1068: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1069: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1070: sub plink {
1.588     raeburn  1071:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1072:     my $winvalue=$value;
                   1073:     unless ($winvalue) {
1.592     raeburn  1074:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1075:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1076:         } elsif ($type eq 'string_yesno') {
                   1077:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1078:                 $winvalue=$env{'form.recent_string'};
                   1079:             }
1.23      www      1080:         } else {
1.190     albertel 1081:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1082:         }
                   1083:     }
1.229     www      1084:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1085:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1086:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1087:     my $valout = &valout($value,$type,1);
1.429     raeburn  1088:     my $unencmarker = $marker;
1.378     albertel 1089:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1090:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1091:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1092:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1093:     }
1.429     raeburn  1094:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1095:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1096:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1097:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1098:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1099: 
1.5       www      1100: }
                   1101: 
1.561     damieng  1102: # Javascript for table mode.
1.280     albertel 1103: sub page_js {
                   1104: 
1.81      www      1105:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1106:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1107: 
                   1108:     return(<<ENDJS);
                   1109: <script type="text/javascript">
1.454     bisitz   1110: // <![CDATA[
1.44      albertel 1111: 
1.88      matthew  1112:     $pjump_def
1.44      albertel 1113: 
                   1114:     function psub() {
1.591     raeburn  1115:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1116:         if (document.parmform.pres_marker.value!='') {
                   1117:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1118:             var typedef=new Array();
                   1119:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1120:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1121:                 if ((typedef[0]=='date') || 
1.591     raeburn  1122:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1123:                     eval('document.parmform.recent_'+
                   1124:                         document.parmform.pres_type.value+
                   1125:                         '.value=document.parmform.pres_value.value;');
                   1126:                 } else {
                   1127:                     eval('document.parmform.recent_'+typedef[0]+
                   1128:                         '.value=document.parmform.pres_value.value;');
                   1129:                 }
1.44      albertel 1130:             }
                   1131:             document.parmform.submit();
                   1132:         } else {
                   1133:             document.parmform.pres_value.value='';
                   1134:             document.parmform.pres_marker.value='';
                   1135:         }
                   1136:     }
                   1137: 
1.57      albertel 1138:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1139:         var options = "width=" + w + ",height=" + h + ",";
                   1140:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1141:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1142:         var newWin = window.open(url, wdwName, options);
                   1143:         newWin.focus();
                   1144:     }
1.523     raeburn  1145: 
1.454     bisitz   1146: // ]]>
1.523     raeburn  1147: 
1.44      albertel 1148: </script>
1.81      www      1149: $selscript
1.280     albertel 1150: ENDJS
                   1151: 
                   1152: }
1.507     www      1153: 
1.561     damieng  1154: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1155: # for table and overview modes.
1.523     raeburn  1156: sub showhide_js {
                   1157:     return <<"COURSECONTENTSCRIPT";
                   1158: 
                   1159: function showHide_courseContent() {
                   1160:     var parmlevValue=document.getElementById("parmlev").value;
                   1161:     if (parmlevValue == 'general') {
                   1162:         document.getElementById('mapmenu').style.display="none";
                   1163:     } else {
                   1164:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1165:             document.getElementById('mapmenu').style.display ="";
                   1166:         } else {
                   1167:             document.getElementById('mapmenu').style.display="none";
                   1168:         }
                   1169:     }
                   1170:     return;
                   1171: }
                   1172: 
                   1173: COURSECONTENTSCRIPT
                   1174: }
                   1175: 
1.561     damieng  1176: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1177: sub toggleparmtextbox_js {
                   1178:     return <<"ENDSCRIPT";
                   1179: 
                   1180: if (!document.getElementsByClassName) {
                   1181:     function getElementsByClassName(node, classname) {
                   1182:         var a = [];
                   1183:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1184:         var els = node.getElementsByTagName("*");
                   1185:         for(var i=0,j=els.length; i<j; i++)
                   1186:             if(re.test(els[i].className))a.push(els[i]);
                   1187:         return a;
                   1188:     }
                   1189: }
                   1190: 
                   1191: function showHideLenient() {
                   1192:     var lenients;
                   1193:     var setRegExp = /^set_/;
                   1194:     if (document.getElementsByClassName) {
                   1195:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1196:     } else {
                   1197:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1198:     }
                   1199:     if (lenients != 'undefined') {
                   1200:         for (var i=0; i<lenients.length; i++) {
                   1201:             if (lenients[i].checked) {
                   1202:                 if (lenients[i].value == 'weighted') {
                   1203:                     if (setRegExp.test(lenients[i].name)) {
                   1204:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1205:                         toggleParmTextbox(document.parmform,identifier);
                   1206:                     }
                   1207:                 }
                   1208:             }
                   1209:         }
                   1210:     }
                   1211:     return;
                   1212: }
                   1213: 
                   1214: function toggleParmTextbox(form,key) {
                   1215:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1216:     if (divfortext) {
                   1217:         var caller = form.elements['set_'+key];
                   1218:         if (caller.length) {
                   1219:             for (i=0; i<caller.length; i++) {
                   1220:                 if (caller[i].checked) {
                   1221:                     if (caller[i].value == 'weighted') {
                   1222:                         divfortext.style.display = 'inline';
                   1223:                     } else {
                   1224:                         divfortext.style.display = 'none';
                   1225:                     }
                   1226:                 }
                   1227:             }
                   1228:         }
                   1229:     }
                   1230:     return;
                   1231: }
                   1232: 
                   1233: ENDSCRIPT
                   1234: }
                   1235: 
1.561     damieng  1236: # Javascript function validateParms, for overview mode
1.549     raeburn  1237: sub validateparms_js {
                   1238:     return <<'ENDSCRIPT';
                   1239: 
                   1240: function validateParms() {
                   1241:     var textRegExp = /^settext_/;
                   1242:     var tailLenient = /\.lenient$/;
                   1243:     var patternRelWeight = /^\-?[\d.]+$/;
                   1244:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1245:     var ipRegExp = /^setip/;
1.549     raeburn  1246:     var ipallowRegExp = /^setipallow_/;
                   1247:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1248:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1249:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1250:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1251:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1252:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1253:     var dlKeyRegExp = /^deeplink_key_/;
                   1254:     var dlMenusRegExp = /^deeplink_menus_/;
                   1255:     var dlCollsRegExp = /^deeplink_colls_/;
1.613     raeburn  1256:     var dlTargetRegExp = /^deeplink_target_/;
1.616     raeburn  1257:     var dlExitRegExp = /^deeplink_exit_/;
                   1258:     var dlExitTextRegExp = /^deeplink_exittext_/;
1.549     raeburn  1259:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616     raeburn  1260:     var numelements = document.parmform.elements.length;
                   1261:     if ((typeof(numelements) != 'undefined') && (numelements != null)) {
                   1262:         if (numelements) {
                   1263:             for (i=0; i<numelements; i++) {
1.549     raeburn  1264:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1265:                 if (textRegExp.test(name)) {
1.549     raeburn  1266:                     var identifier = name.replace(textRegExp,'');
                   1267:                     if (tailLenient.test(identifier)) {
                   1268:                         if (document.parmform.elements['set_'+identifier].length) {
                   1269:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1270:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1271:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1272:                                         var relweight = document.parmform.elements[i].value;
                   1273:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1274:                                         if (!patternRelWeight.test(relweight)) {
                   1275:                                             relweight = '0.0';
                   1276:                                         }
                   1277:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1278:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1279:                                         } else {
                   1280:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1281:                                         }
                   1282:                                     }
                   1283:                                     break;
                   1284:                                 }
                   1285:                             }
                   1286:                         }
                   1287:                     }
1.597     raeburn  1288:                 } else if (ipRegExp.test(name)) {
                   1289:                     if (ipallowRegExp.test(name)) {
                   1290:                         var identifier = name.replace(ipallowRegExp,'');
                   1291:                         var possallow = document.parmform.elements[i].value;
                   1292:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1293:                         if (patternIP.test(possallow)) {
                   1294:                             if (document.parmform.elements['set_'+identifier].value) {
                   1295:                                 possallow = ','+possallow;
                   1296:                             }
                   1297:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1298:                         }
                   1299:                     } else if (ipdenyRegExp.test(name)) {
                   1300:                         var identifier = name.replace(ipdenyRegExp,'');
                   1301:                         var possdeny = document.parmform.elements[i].value;
                   1302:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1303:                         if (patternIP.test(possdeny)) {
                   1304:                             possdeny = '!'+possdeny;
                   1305:                             if (document.parmform.elements['set_'+identifier].value) {
                   1306:                                 possdeny = ','+possdeny;
                   1307:                             }
                   1308:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1309:                         }
                   1310:                     }
                   1311:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1312:                     if (dlListScopeRegExp.test(name)) {
                   1313:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1314:                         var idx = document.parmform.elements[i].selectedIndex;
                   1315:                         if (idx > 0) { 
                   1316:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1317:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1318:                             if (document.parmform.elements['set_'+identifier].value) {
                   1319:                                 possdeeplink = ','+possdeeplink;
                   1320:                             }
                   1321:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1322:                         }
1.601     raeburn  1323:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1324:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1325:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1326:                             var posslinkurl = document.parmform.elements[i].value;
                   1327:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1328:                             if (document.parmform.elements['set_'+identifier].value) {
                   1329:                                 posslinkurl = ','+posslinkurl;
                   1330:                             }
                   1331:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1332:                         }
1.601     raeburn  1333:                     } else if (dlLtidRegExp.test(name)) {
                   1334:                         var identifier = name.replace(dlLtidRegExp,'');
                   1335:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1336:                             var possltid = document.parmform.elements[i].value;
                   1337:                             possltid = possltid.replace(/\D+/g,'');
                   1338:                             if (possltid.length) {
1.597     raeburn  1339:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1340:                                     possltid = ':'+possltid;
1.597     raeburn  1341:                                 }
1.601     raeburn  1342:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1343:                             } else {
                   1344:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1345:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1346:                                 return false;  
                   1347:                             }
                   1348:                         }
1.601     raeburn  1349:                     } else if (dlLticRegExp.test(name)) {
                   1350:                         var identifier = name.replace(dlLticRegExp,'');
                   1351:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1352:                             var possltic = document.parmform.elements[i].value;
                   1353:                             possltic = possltic.replace(/\D+/g,'');
                   1354:                             if (possltic.length) {
                   1355:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1356:                                     possltic = ':'+possltic;
                   1357:                                 }
                   1358:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1359:                             } else {
                   1360:                                 document.parmform.elements['set_'+identifier].value = '';
                   1361:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1362:                                 return false;
                   1363:                             }
                   1364:                         }
1.597     raeburn  1365:                     } else if (dlKeyRegExp.test(name)) {
                   1366:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1367:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1368:                             var posskey = document.parmform.elements[i].value;
                   1369:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1370:                             var origlength = posskey.length;
                   1371:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1372:                             var newlength = posskey.length;
                   1373:                             if (newlength > 0) {
                   1374:                                 var change = origlength - newlength;
                   1375:                                 if (change) {
                   1376:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1377:                                 }
                   1378:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1379:                                     posskey = ':'+posskey;
                   1380:                                 }
                   1381:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1382:                             } else {
                   1383:                                 document.parmform.elements['set_'+identifier].value = '';
                   1384:                                 if (newlength < origlength) {
                   1385:                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                   1386:                                 } else {
                   1387:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1388:                                 }
                   1389:                                 return false;
                   1390:                             }
                   1391:                         }
                   1392:                     } else if (dlMenusRegExp.test(name)) {
                   1393:                         if (document.parmform.elements[i].checked) {
                   1394:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1395:                             var posslinkmenu = document.parmform.elements[i].value;
                   1396:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1397:                             if (posslinkmenu == 'std') {
                   1398:                                 posslinkmenu = '0';
                   1399:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1400:                                     posslinkmenu = ','+posslinkmenu;
                   1401:                                 }
                   1402:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1403:                             }
                   1404:                         }
                   1405:                     } else if (dlCollsRegExp.test(name)) {
                   1406:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1407:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1408:                             var posslinkmenu = document.parmform.elements[i].value;
                   1409:                             if (document.parmform.elements['set_'+identifier].value) {
                   1410:                                 posslinkmenu = ','+posslinkmenu;
                   1411:                             }
                   1412:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1413:                         }
1.614     raeburn  1414:                     } else if (dlTargetRegExp.test(name)) {
                   1415:                         var identifier =  name.replace(dlTargetRegExp,'');
1.613     raeburn  1416:                         var idx = document.parmform.elements[i].selectedIndex;
                   1417:                         if (idx > 0) {
1.616     raeburn  1418:                             var linktarget = document.parmform.elements[i].options[idx].value
                   1419:                             linktarget = linktarget.replace(/^\s+|\s+$/g,'');
                   1420:                             if (document.parmform.elements['set_'+identifier].value) {
                   1421:                                 linktarget = ','+linktarget;
                   1422:                             }
                   1423:                             document.parmform.elements['set_'+identifier].value += linktarget;
                   1424:                         }
                   1425:                     } else if (dlExitRegExp.test(name)) {
                   1426:                         if (document.parmform.elements[i].checked) {
                   1427:                             var identifier =  name.replace(dlExitRegExp,'');
                   1428:                             var posslinkexit = document.parmform.elements[i].value;
                   1429:                             posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613     raeburn  1430:                             if (document.parmform.elements['set_'+identifier].value) {
1.616     raeburn  1431:                                 posslinkexit = ','+posslinkexit;
                   1432:                             }
                   1433:                             document.parmform.elements['set_'+identifier].value += posslinkexit;
                   1434:                         }
                   1435:                     } else if (dlExitTextRegExp.test(name)) {
                   1436:                         var identifier = name.replace(dlExitTextRegExp,'');
                   1437:                         if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
                   1438:                             (isRadioSet('deeplink_exit_'+identifier,'url'))) {
                   1439:                             var posstext = document.parmform.elements[i].value;
                   1440:                             posstext = posstext.replace(/^\s+|\s+$/g,'');
                   1441:                             var origlength = posstext.length;
                   1442:                             posstext = posstext.replace(/[:;'",]/g,'');
                   1443:                             var newlength = posstext.length;
                   1444:                             if (newlength > 0) {
                   1445:                                 var change = origlength - newlength;
                   1446:                                 if (change) {
                   1447:                                     alert(change+' disallowed character(s) removed from Exit Button text');
                   1448:                                 }
                   1449:                                 if (posstext !== 'Exit Tool') {
                   1450:                                     posstext = ':'+posstext;
                   1451:                                     document.parmform.elements['set_'+identifier].value += posstext;
                   1452:                                 }
                   1453:                             } else {
                   1454:                                 document.parmform.elements['set_'+identifier].value = '';
                   1455:                                 if (newlength < origlength) {
                   1456:                                     alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
                   1457:                                 } else {
                   1458:                                     alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
                   1459:                                 }
                   1460:                                 return false;
1.613     raeburn  1461:                             }
                   1462:                         }
1.549     raeburn  1463:                     }
                   1464:                 }
                   1465:             }
                   1466:         }
                   1467:     }
                   1468:     return true;
                   1469: }
                   1470: 
1.597     raeburn  1471: function isRadioSet(name,expected) {
                   1472:     var menuitems = document.getElementsByName(name);
                   1473:     var radioLength = menuitems.length;
                   1474:     result = false;
                   1475:     if (radioLength  > 1) {
                   1476:         for (var j=0; j<radioLength; j++) {
                   1477:             if (menuitems[j].checked) {
                   1478:                 if (menuitems[j].value == expected) {
                   1479:                     result = true;
                   1480:                     break;
                   1481:                 }
                   1482:             }
                   1483:         }
                   1484:     }
                   1485:     return result;
                   1486: }
                   1487: 
1.549     raeburn  1488: ENDSCRIPT
                   1489: }
                   1490: 
1.561     damieng  1491: # Javascript initialization, for overview mode
1.549     raeburn  1492: sub ipacc_boxes_js  {
                   1493:     my $remove = &mt('Remove');
                   1494:     return <<"END";
                   1495: \$(document).ready(function() {
                   1496:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1497:     var add_button      = \$(".LC_add_ipacc_button");
                   1498:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1499: 
                   1500:     \$(add_button).click(function(e){
                   1501:         e.preventDefault();
                   1502:         var identifier = \$(this).closest("div").attr("id");
                   1503:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1504:         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549     raeburn  1505:     });
                   1506: 
                   1507:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1508:         e.preventDefault(); \$(this).closest("div").remove();
                   1509:     })
                   1510: });
                   1511: 
                   1512: 
                   1513: END
                   1514: }
                   1515: 
1.561     damieng  1516: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1517: sub done_proctor_js {
1.611     raeburn  1518:     my $defaultdone = &mt('Done');
                   1519:     &js_escape(\$defaultdone);
1.558     raeburn  1520:     return <<"END";
                   1521: function toggleSecret(form,radio,key) {
                   1522:     var radios = form[radio+key];
                   1523:     if (radios.length) {
                   1524:         for (var i=0; i<radios.length; i++) {
                   1525:             if (radios[i].checked) {
                   1526:                 if (radios[i].value == '_done_proctor') {
                   1527:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1528:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1529:                     }
                   1530:                 } else {
                   1531:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1532:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1533:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1534:                     }
                   1535:                 }
1.611     raeburn  1536:                 if (document.getElementById('done_'+key+'_buttontext')) {
                   1537:                     if (radios[i].value == '') {
                   1538:                         document.getElementById('done_'+key+'_buttontext').value = '';
                   1539:                     } else {
                   1540:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
                   1541:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
                   1542:                         }
                   1543:                     }
                   1544:                 }
1.558     raeburn  1545:             }
                   1546:         }
                   1547:     }
                   1548: }
                   1549: END
                   1550: 
                   1551: }
                   1552: 
1.588     raeburn  1553: # Javascript function toggle
                   1554: sub deeplink_js {
                   1555:     return <<"END";
                   1556: function toggleDeepLink(form,item,key) {
                   1557:     var radios = form['deeplink_'+item+'_'+key];
                   1558:     if (radios.length) {
                   1559:         var keybox;
                   1560:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1561:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1562:         }
1.601     raeburn  1563:         var divoptions = new Array();
                   1564:         if (item == 'protect') {
                   1565:             divoptions = ['ltic','ltid'];
1.597     raeburn  1566:         } else {
                   1567:             if (item == 'menus') {
1.601     raeburn  1568:                 divoptions = ['colls'];
1.597     raeburn  1569:             }
                   1570:         }
1.601     raeburn  1571:         var seldivs = new Array();
                   1572:         if ((item == 'protect') || (item == 'menus')) {
                   1573:             for (var i=0; i<divoptions.length; i++) {
                   1574:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1575:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1576:                 } else {
                   1577:                     seldivs[i] = '';
                   1578:                 }
                   1579:             }
1.588     raeburn  1580:         }
                   1581:         for (var i=0; i<radios.length; i++) {
                   1582:             if (radios[i].checked) {
1.601     raeburn  1583:                 if ((item == 'protect') || (item == 'menus')) {
                   1584:                     for (var j=0; j<seldivs.length; j++) {
                   1585:                         if (radios[i].value == divoptions[j]) {
                   1586:                             if (seldivs[j] != '') {
                   1587:                                 seldivs[j].style.display = 'inline-block';
                   1588:                             }
                   1589:                             if (item == 'protect') {
                   1590:                                 keybox.type = 'hidden';
                   1591:                                 keybox.value = '';
                   1592:                             }
                   1593:                         } else {
                   1594:                             if (seldivs[j] != '') {
                   1595:                                 seldivs[j].style.display = 'none';
                   1596:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1597:                             }
                   1598:                         }
1.597     raeburn  1599:                     }
1.601     raeburn  1600:                     if (item == 'protect') {
1.597     raeburn  1601:                         if (radios[i].value == 'key') {
                   1602:                             keybox.type = 'text';
                   1603:                         } else {
                   1604:                             keybox.type = 'hidden';
                   1605:                         }
1.588     raeburn  1606:                     }
1.616     raeburn  1607:                 } else if (item == 'exit') {
                   1608:                     if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
                   1609:                         if (radios[i].value == 'no') {
                   1610:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';          
                   1611:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1612:                                 if (document.getElementById('deeplink_exittext_'+key).value != '') {
                   1613:                                     document.getElementById('deeplink_exittext_'+key).value = '';    
                   1614:                                 }
                   1615:                             }
                   1616:                         } else {
                   1617:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
                   1618:                             if (document.getElementById('deeplink_exittext_'+key)) {
                   1619:                                 if (document.getElementById('deeplink_exittext_'+key).value == '') {
                   1620:                                     document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
                   1621:                                 }
                   1622:                             }
                   1623:                         }
                   1624:                     }
1.588     raeburn  1625:                 }
                   1626:             }
                   1627:         }
                   1628:     }
                   1629: }
                   1630: END
                   1631: 
                   1632: }
                   1633: 
1.561     damieng  1634: # Prints HTML page start for table mode.
                   1635: # @param {Apache2::RequestRec} $r - the Apache request
                   1636: # @param {string} $psymb - resource symb
                   1637: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1638: sub startpage {
1.531     raeburn  1639:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1640: 
1.515     raeburn  1641:     my %loaditems = (
                   1642:                       'onload'   => "group_or_section('cgroup')",
                   1643:                     );
                   1644:     if (!$psymb) {
1.523     raeburn  1645:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1646:     }
1.280     albertel 1647: 
1.560     damieng  1648:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1649:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1650:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1651:             text=>"Problem Parameters"});
1.414     droeschl 1652:     } else {
1.560     damieng  1653:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1654:             text=>"Table Mode",
                   1655:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1656:     }
1.523     raeburn  1657:     my $js = &page_js().'
                   1658: <script type="text/javascript">
                   1659: // <![CDATA[
                   1660: '.
                   1661:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1662: // ]]>
                   1663: </script>
                   1664: ';
1.446     bisitz   1665:     my $start_page =
1.523     raeburn  1666:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1667:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1668:     my $breadcrumbs =
1.473     amueller 1669:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1670:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1671:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1672:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1673:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1674:     $r->print(<<ENDHEAD);
1.193     albertel 1675: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1676: <input type="hidden" value="" name="pres_value" />
                   1677: <input type="hidden" value="" name="pres_type" />
                   1678: <input type="hidden" value="" name="pres_marker" />
                   1679: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1680: <input type="hidden" value="$escfilter" name="filter" />
                   1681: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1682: ENDHEAD
                   1683: }
                   1684: 
1.209     www      1685: 
1.561     damieng  1686: # Prints a row for table mode (except for the tr start).
                   1687: # Every time a hash reference is passed, a single entry is used, so print_row
                   1688: # could just use these values, but why make it simple when it can be complicated ?
                   1689: #
                   1690: # @param {Apache2::RequestRec} $r - the Apache request
                   1691: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1692: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1693: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1694: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1695: # @param {string} $rid - resource id
                   1696: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1697: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1698: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1699: # @param {string} $defbgone - user level and other levels background color
                   1700: # @param {string} $defbgtwo - section level background color, also used for part number
                   1701: # @param {string} $defbgthree - group level background color
                   1702: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1703: # @param {string} $uname - user name
                   1704: # @param {string} $udom - user domain
                   1705: # @param {string} $csec - section name
                   1706: # @param {string} $cgroup - group name
                   1707: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1708: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1709: # @param {boolean} $readonly - true if no editing allowed.
                   1710: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1711: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1712: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1713: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1714: sub print_row {
1.201     www      1715:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1716:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1717:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1718:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1719:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1720:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1721:     my $numlinks = 0;
1.553     raeburn  1722: 
1.560     damieng  1723:     # get the values for the parameter in cascading order
                   1724:     # empty levels will remain empty
1.44      albertel 1725:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1726:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1727:     # get the type for the parameters
                   1728:     # problem: these may not be set for all levels
1.66      www      1729:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1730:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1731:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1732:     # cascade down manually
1.182     albertel 1733:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1734:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1735:         if ($typeoutpar[$i]) {
1.66      www      1736:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1737:         } else {
1.66      www      1738:             $typeoutpar[$i]=$cascadetype;
                   1739:         }
                   1740:     }
1.57      albertel 1741:     my $parm=$$display{$which};
                   1742: 
1.203     www      1743:     if ($parmlev eq 'full') {
1.419     bisitz   1744:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1745:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1746:     } else {
1.57      albertel 1747:         $parm=~s|\[.*\]\s||g;
                   1748:     }
1.231     www      1749:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1750:     if ($automatic) {
1.560     damieng  1751:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1752:     }
1.427     bisitz   1753:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1754: 
1.44      albertel 1755:     my $thismarker=$which;
                   1756:     $thismarker=~s/^parameter\_//;
                   1757:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1758:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1759:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1760:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1761:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1762:         if ($result eq '') {
                   1763:             $recurse_check = 1;
                   1764:         } elsif (($uname ne '') && ($result > 3)) {
                   1765:             $recurse_check = 1;
                   1766:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1767:             $recurse_check = 1;
                   1768:         } elsif (($csec ne '') && ($result > 11)) {
                   1769:             $recurse_check = 1;
                   1770:         } elsif ($result > 17) {
                   1771:             $recurse_check = 1;
                   1772:         }
                   1773:         if ($recurse_check) {
                   1774:             my $what = $$part{$which}.'.'.$$name{$which};
                   1775:             my $prefix;
                   1776:             if (($uname ne '') && ($udom ne '')) {
                   1777:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1778:                 $prefix = $env{'request.course.id'};
                   1779:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1780:                 if (ref($recursinfo) eq 'ARRAY') {
                   1781:                     $effparm_rec = 1;
                   1782:                     $effparm_level = &mt('user: [_1]',$uname);
                   1783:                 }
                   1784:             }
                   1785:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1786:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1787:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1788:                 if (ref($recursinfo) eq 'ARRAY') {
                   1789:                     $effparm_rec = 1;
                   1790:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1791:                 }
                   1792:             }
                   1793:             if (($csec ne '') && (!$effparm_rec)) {
                   1794:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1795:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1796:                 if (ref($recursinfo) eq 'ARRAY') {
                   1797:                     $effparm_rec = 1;
                   1798:                     $effparm_level = &mt('section: [_1]',$csec);
                   1799:                 }
                   1800:             }
                   1801:             if (!$effparm_rec) {
                   1802:                 $prefix = $env{'request.course.id'};
                   1803:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1804:                 if (ref($recursinfo) eq 'ARRAY') {
                   1805:                     $effparm_rec = 1;
                   1806:                 }
                   1807:             }
                   1808:         }
                   1809:     }
                   1810:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1811:         $effparm_rec = 1;
                   1812:     }
                   1813:     if ((!$effparm_rec) && 
                   1814:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1815:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1816:         $effparm_rec = 1;
                   1817:     }
1.588     raeburn  1818:     if ($parmname eq 'deeplink') {
1.601     raeburn  1819:         my ($domltistr,$crsltistr);
1.588     raeburn  1820:         my %lti =
                   1821:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1822:                                             'linkprot');
1.601     raeburn  1823:         if (keys(%lti)) {
                   1824:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1825:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1826:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1827:                 }
                   1828:             }
1.601     raeburn  1829:             $domltistr =~ s/,$//;
                   1830:             if ($domltistr) {
                   1831:                 $extra = 'ltid_'.$domltistr;
                   1832:             }
1.588     raeburn  1833:         }
1.601     raeburn  1834:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1835:         if (keys(%courselti)) {
                   1836:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1837:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1838:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1839:                 }
                   1840:             }
                   1841:             $crsltistr =~ s/,$//;
                   1842:             if ($crsltistr) {
                   1843:                 if ($extra) {
                   1844:                     $extra .= '&';
                   1845:                 }
                   1846:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1847:             }
                   1848:         }
1.597     raeburn  1849:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1850:             my @colls;
                   1851:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1852:                 my ($num,$value) = split(/\%/,$item);
                   1853:                 if ($num =~ /^\d+$/) {
                   1854:                     push(@colls,$num);
                   1855:                 }
                   1856:             }
                   1857:             if (@colls) {
                   1858:                 if ($extra) {
                   1859:                     $extra .= '&';
                   1860:                 }
                   1861:                 $extra .= 'menus_'.join(',',@colls);
                   1862:             }
                   1863:         }
1.588     raeburn  1864:     }
1.57      albertel 1865:     if ($parmlev eq 'general') {
                   1866:         if ($uname) {
1.588     raeburn  1867:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1868:         } elsif ($cgroup) {
1.588     raeburn  1869:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1870:         } elsif ($csec) {
1.588     raeburn  1871:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1872:         } else {
1.588     raeburn  1873:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1874:         }
                   1875:     } elsif ($parmlev eq 'map') {
                   1876:         if ($uname) {
1.588     raeburn  1877:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1878:         } elsif ($cgroup) {
1.588     raeburn  1879:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1880:         } elsif ($csec) {
1.588     raeburn  1881:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1882:         } else {
1.588     raeburn  1883:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1884:         }
                   1885:     } else {
1.275     raeburn  1886:         if ($uname) {
                   1887:             if (@{$usersgroups} > 1) {
1.582     raeburn  1888:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1889:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1890:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1891:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1892:                     if (defined($controlgrp)) {
                   1893:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1894:                             $eff_groupparm = $grp_parm;
                   1895:                             undef($result);
                   1896:                             undef($effparm_rec);
                   1897:                             if ($grp_is_rec) {
                   1898:                                  $effparm_rec = 1;
                   1899:                             }
1.275     raeburn  1900:                         }
                   1901:                     }
                   1902:                 }
                   1903:             }
                   1904:         }
1.57      albertel 1905: 
1.588     raeburn  1906:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1907:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1908:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1909:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1910:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1911: 
                   1912:         if ($csec) {
1.588     raeburn  1913:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1914:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1915:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1916:         }
1.269     raeburn  1917: 
                   1918:         if ($cgroup) {
1.588     raeburn  1919:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1920:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1921:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1922:         }
1.446     bisitz   1923: 
1.548     raeburn  1924:         if ($uname) {
1.275     raeburn  1925:             if ($othergrp) {
                   1926:                 $r->print($othergrp);
                   1927:             }
1.588     raeburn  1928:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1929:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1930:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1931:         }
1.57      albertel 1932:     } # end of $parmlev if/else
1.582     raeburn  1933:     if (ref($recursinfo) eq 'ARRAY') {
                   1934:         my $rectitle = &mt('recursive');
                   1935:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1936:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1937:                 $rectitle = &mt('set in: [_1]','"'.
                   1938:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1939:                                                               "'$parmname','$$part{$which}'".');">'.
                   1940:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1941:               
                   1942:                 $numlinks ++;
                   1943:             }
                   1944:         }
                   1945:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1946:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1947:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1948:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1949:                   $effparm_level.'</span></td>');
                   1950:     } else {
                   1951:         if ($result) {
1.593     raeburn  1952:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1953:         }
                   1954:         if ($eff_groupparm) {
                   1955:             $effective_parm = $eff_groupparm;
                   1956:         }
                   1957:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1958:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1959:                                 '</span>':'').'</td>');
                   1960:     }
1.203     www      1961:     if ($parmlev eq 'full') {
1.136     albertel 1962:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1963:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1964:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1965:         if (!defined($sessionvaltype)) {
                   1966:             $sessionvaltype=$$defaulttype{$which};
                   1967:         }
1.419     bisitz   1968:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1969:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1970:                   '</font></td>');
1.136     albertel 1971:     }
1.44      albertel 1972:     $r->print('</tr>');
1.57      albertel 1973:     $r->print("\n");
1.582     raeburn  1974:     if (($numlinks) && (ref($reclinks))) {
                   1975:         $$reclinks = $numlinks;
                   1976:     }
1.44      albertel 1977: }
1.59      matthew  1978: 
1.561     damieng  1979: # Prints a cell for table mode.
                   1980: #
                   1981: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1982: # Also, it would make more sense to pass the display for this cell rather
                   1983: # than the full display hash and the key to use.
                   1984: #
                   1985: # @param {Apache2::RequestRec} $r - the Apache request
                   1986: # @param {integer} $which - level
                   1987: # @param {string} $defbg - cell background color
                   1988: # @param {integer} $result - the most specific level that is defined for that parameter
                   1989: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1990: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1991: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1992: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1993: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1994: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1995: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1996: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1997: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1998: sub print_td {
1.578     raeburn  1999:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  2000:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  2001:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   2002:     $ineffect = 0;
                   2003:     $currval = $$outpar[$which];
                   2004:     $currtype = $$typeoutpar[$which];
                   2005:     $currlevel = $which;
                   2006:     if (($result) && ($result == $which)) {
                   2007:         $ineffect = 1;
                   2008:     } 
                   2009:     if ($ismaplevel) {
                   2010:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   2011:             if (($result) && ($result == $which)) {
                   2012:                 $recursive = 1;
                   2013:             }
                   2014:         } elsif ($$outpar[$which+1] ne '') {
                   2015:             $recursive = 1;
                   2016:             $currlevel = $which+1;
                   2017:             $currval = $$outpar[$currlevel];
                   2018:             $currtype = $$typeoutpar[$currlevel];
                   2019:             if (($result) && ($result == $currlevel)) {
                   2020:                 $ineffect = 1;
                   2021:             }
                   2022:         }
                   2023:     }
                   2024:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   2025:               ';" align="center">');
1.437     raeburn  2026:     my $nolink = 0;
1.568     raeburn  2027:     if ($readonly) {
1.552     raeburn  2028:         $nolink = 1;
1.568     raeburn  2029:     } else { 
1.578     raeburn  2030:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  2031:             $nolink = 1;
1.568     raeburn  2032:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  2033:             $nolink = 1;
1.568     raeburn  2034:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   2035:             if ($noeditgrp) {
                   2036:                 $nolink = 1;
                   2037:             }
                   2038:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  2039:             $nolink = 1;
1.568     raeburn  2040:         } elsif ($mprefix =~ /examcode\&$/) {
                   2041:             unless ($which == 2) {
                   2042:                 $nolink = 1;
                   2043:             }
1.533     raeburn  2044:         }
1.437     raeburn  2045:     }
                   2046:     if ($nolink) {
1.577     raeburn  2047:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  2048:         $r->print(&valout($currval,$currtype));
1.114     www      2049:     } else {
1.578     raeburn  2050:         $r->print(&plink($currtype,
                   2051:                          $$display{$value},$currval,
1.588     raeburn  2052:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   2053:                          $extra));
1.114     www      2054:     }
                   2055:     $r->print('</td>'."\n");
1.57      albertel 2056: }
                   2057: 
1.561     damieng  2058: # Returns HTML and other info for the cell added when a user is selected
                   2059: # and that user is in several groups. This is the cell with the title "Control by other group".
                   2060: #
                   2061: # @param {string} $what - parameter part.'.'.parameter name
                   2062: # @param {string} $rid - resource id
                   2063: # @param {string} $cgroup - group name
                   2064: # @param {string} $defbg - cell background color
                   2065: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2066: # @param {integer} $result - level
                   2067: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  2068: # @returns {Array} - array (parameter value for the other group, HTML for the cell, HTML with the value, name of the other group, true if recursive)
1.580     raeburn  2069: sub check_other_groups {
                   2070:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  2071:     my $courseid = $env{'request.course.id'};
                   2072:     my $output;
                   2073:     my $symb = &symbcache($rid);
                   2074:     my $symbparm=$symb.'.'.$what;
                   2075:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2076:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2077:     my $mapparm=$map.'___(all).'.$what;
                   2078:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2079:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2080:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2081:     my $bgcolor = $defbg;
1.582     raeburn  2082:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2083:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2084:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2085:         if ($result > 3) {
1.419     bisitz   2086:             $bgcolor = '#AAFFAA';
1.275     raeburn  2087:         }
1.593     raeburn  2088:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2089:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2090:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2091:             if ($resultlevel eq 'recursive') {
                   2092:                 $resultlevel = 'map/folder';
                   2093:                 $grp_is_rec = 1;
                   2094:             }
                   2095:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2096:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2097:              
1.275     raeburn  2098:         } else {
                   2099:             $output .= '&nbsp;';
                   2100:         }
                   2101:         $output .= '</td>';
                   2102:     } else {
1.419     bisitz   2103:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2104:     }
1.582     raeburn  2105:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2106: }
                   2107: 
1.561     damieng  2108: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2109: # Used by check_other_groups.
1.561     damieng  2110: #
                   2111: # @param {string} $courseid - the course id
                   2112: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2113: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2114: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2115: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2116: # @param {string} $what - parameter part.'.'.parameter name
                   2117: # @param {hash reference} $courseopt - course parameters hash
                   2118: # @returns {Array} - (parameter value for the group, course parameter hash key for the parameter, name of the group, level name, parameter type)
1.275     raeburn  2119: sub parm_control_group {
1.556     raeburn  2120:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2121:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2122:     my $grpfound = 0;
1.556     raeburn  2123:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2124:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2125:     foreach my $group (@{$usersgroups}) {
                   2126:         if ($grpfound) { last; }
                   2127:         for (my $i=0; $i<@levels; $i++) {
                   2128:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2129:             if (defined($$courseopt{$item})) {
                   2130:                 $coursereply = $$courseopt{$item};
                   2131:                 $resultitem = $item;
                   2132:                 $resultgroup = $group;
                   2133:                 $resultlevel = $levelnames[$i];
                   2134:                 $resulttype = $$courseopt{$item.'.type'};
                   2135:                 $grpfound = 1;
                   2136:                 last;
                   2137:             }
                   2138:         }
                   2139:     }
                   2140:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2141: }
1.201     www      2142: 
1.63      bowersj2 2143: 
                   2144: 
1.562     damieng  2145: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2146: # All the parameters are references and are filled by the sub.
                   2147: #
1.566     damieng  2148: # @param {array reference} $ids - resource and map ids
                   2149: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2150: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2151: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2152: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2153: # @param {hash reference} $allmaps - hash map pc -> map src
                   2154: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2155: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2156: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2157: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2158: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2159: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2160: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2161: sub extractResourceInformation {
                   2162:     my $ids = shift;
                   2163:     my $typep = shift;
                   2164:     my $keyp = shift;
                   2165:     my $allparms = shift;
                   2166:     my $allparts = shift;
                   2167:     my $allmaps = shift;
                   2168:     my $mapp = shift;
                   2169:     my $symbp = shift;
1.82      www      2170:     my $maptitles=shift;
1.196     www      2171:     my $uris=shift;
1.210     www      2172:     my $keyorder=shift;
1.211     www      2173:     my $defkeytype=shift;
1.603     raeburn  2174:     my $pssymb=shift;
1.196     www      2175: 
1.210     www      2176:     my $keyordercnt=100;
1.63      bowersj2 2177: 
1.196     www      2178:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2179:     return unless(ref($navmap));
                   2180:     my @allres;
                   2181:     if ($pssymb ne '') {
                   2182:         my $res = $navmap->getBySymb($pssymb);
                   2183:         if (ref($res)) {
                   2184:             @allres = ($res);
                   2185:         }
                   2186:     }
                   2187:     if (!@allres) { 
                   2188:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2189:     }
1.196     www      2190:     foreach my $resource (@allres) {
1.480     amueller 2191:         my $id=$resource->id();
1.196     www      2192:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2193:         if ($mapid eq '0') { next; }
                   2194:         $$ids[$#$ids+1]=$id;
                   2195:         my $srcf=$resource->src();
                   2196:         $srcf=~/\.(\w+)$/;
                   2197:         $$typep{$id}=$1;
1.584     raeburn  2198:         my $toolsymb;
                   2199:         if ($srcf =~ /ext\.tool$/) {
                   2200:             $toolsymb = $resource->symb();
                   2201:         }
1.480     amueller 2202:         $$keyp{$id}='';
1.196     www      2203:         $$uris{$id}=$srcf;
1.512     foxr     2204: 
1.584     raeburn  2205:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2206:             next if ($key!~/^parameter_/);
1.363     albertel 2207: 
1.209     www      2208: # Hidden parameters
1.584     raeburn  2209:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2210: #
                   2211: # allparms is a hash of parameter names
                   2212: #
1.584     raeburn  2213:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2214:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2215:                 my ($display,$parmdis);
                   2216:                 $display = &standard_parameter_names($name);
                   2217:                 if ($display eq '') {
1.584     raeburn  2218:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2219:                     $parmdis = $display;
                   2220:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2221:                 } else {
                   2222:                     $parmdis = &mt($display);
                   2223:                 }
                   2224:                 $$allparms{$name}=$parmdis;
                   2225:                 if (ref($defkeytype)) {
                   2226:                     $$defkeytype{$name}=
1.584     raeburn  2227:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2228:                 }
                   2229:             }
1.363     albertel 2230: 
1.209     www      2231: #
                   2232: # allparts is a hash of all parts
                   2233: #
1.584     raeburn  2234:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2235:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2236: #
                   2237: # Remember all keys going with this resource
                   2238: #
1.480     amueller 2239:             if ($$keyp{$id}) {
                   2240:                 $$keyp{$id}.=','.$key;
                   2241:             } else {
                   2242:                 $$keyp{$id}=$key;
                   2243:             }   
1.210     www      2244: #
                   2245: # Put in order
1.446     bisitz   2246: #
1.480     amueller 2247:             unless ($$keyorder{$key}) {
                   2248:                 $$keyorder{$key}=$keyordercnt;
                   2249:                 $keyordercnt++;
                   2250:             }
1.473     amueller 2251:         }
                   2252: 
                   2253: 
1.480     amueller 2254:         if (!exists($$mapp{$mapid})) {
                   2255:             $$mapp{$id}=
                   2256:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2257:             $$mapp{$mapid}=$$mapp{$id};
                   2258:             $$allmaps{$mapid}=$$mapp{$id};
                   2259:             if ($mapid eq '1') {
1.532     raeburn  2260:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2261:             } else {
                   2262:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2263:             }
                   2264:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2265:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2266:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2267:                                                      # are commented out in rev. 1.57
1.473     amueller 2268:         } else {
1.480     amueller 2269:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2270:         }
1.480     amueller 2271:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2272:     }
                   2273: }
                   2274: 
1.582     raeburn  2275: sub get_recursive {
                   2276:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2277:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2278:         foreach my $item (@{$recurseup}) {
                   2279:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2280:             if (defined($resdata->{$norecursechk})) {
                   2281:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2282:                     my $type = $resdata->{$norecursechk.'.type'};
                   2283:                     return [$resdata->{$norecursechk},$type,$item];
                   2284:                 } else {
                   2285:                     last;
                   2286:                 }
                   2287:             }
                   2288:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2289:             if (defined($resdata->{$recursechk})) {
                   2290:                 my $type = $resdata->{$recursechk.'.type'};
                   2291:                 return [$resdata->{$recursechk},$type,$item];
                   2292:             }
                   2293:         }
                   2294:     }
                   2295:     return;
                   2296: }
                   2297: 
1.208     www      2298: 
1.562     damieng  2299: # Tells if a parameter type is a date.
                   2300: #
                   2301: # @param {string} type - parameter type
                   2302: # @returns{boolean} - true if it is a date
1.213     www      2303: sub isdateparm {
                   2304:     my $type=shift;
                   2305:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2306: }
                   2307: 
1.589     raeburn  2308: # Determine if parameter type is specialized string type (i.e.,
                   2309: # not just string or string_yesno.  
                   2310: 
                   2311: sub is_specialstring {
                   2312:     my $type=shift;
1.603     raeburn  2313:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2314: }
                   2315: 
1.562     damieng  2316: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2317: #
1.581     raeburn  2318: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2319: sub parmmenu {
1.581     raeburn  2320:     my ($r)=@_;
1.208     www      2321:     $r->print(<<ENDSCRIPT);
                   2322: <script type="text/javascript">
1.454     bisitz   2323: // <![CDATA[
1.208     www      2324:     function checkall(value, checkName) {
1.453     schualex 2325: 
                   2326:         var li = "_li";
                   2327:         var displayOverview = "";
                   2328:         
                   2329:         if (value == false) {
                   2330:             displayOverview = "none"
                   2331:         }
                   2332: 
1.562     damieng  2333:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2334:             ele = document.forms.parmform.elements[i];
                   2335:             if (ele.name == checkName) {
                   2336:                 document.forms.parmform.elements[i].checked=value;
                   2337:             }
                   2338:         }
                   2339:     }
1.210     www      2340: 
                   2341:     function checkthis(thisvalue, checkName) {
1.562     damieng  2342:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2343:             ele = document.forms.parmform.elements[i];
                   2344:             if (ele.name == checkName) {
1.562     damieng  2345:                 if (ele.value == thisvalue) {
                   2346:                     document.forms.parmform.elements[i].checked=true;
                   2347:                 }
1.210     www      2348:             }
                   2349:         }
                   2350:     }
                   2351: 
                   2352:     function checkdates() {
1.562     damieng  2353:         checkthis('duedate','pscat');
                   2354:         checkthis('opendate','pscat');
                   2355:         checkthis('answerdate','pscat');
1.218     www      2356:     }
                   2357: 
                   2358:     function checkdisset() {
1.562     damieng  2359:         checkthis('discussend','pscat');
                   2360:         checkthis('discusshide','pscat');
                   2361:         checkthis('discussvote','pscat');
1.218     www      2362:     }
                   2363: 
                   2364:     function checkcontdates() {
1.562     damieng  2365:         checkthis('contentopen','pscat');
                   2366:         checkthis('contentclose','pscat');
1.218     www      2367:     }
1.446     bisitz   2368: 
1.210     www      2369:     function checkvisi() {
1.562     damieng  2370:         checkthis('hiddenresource','pscat');
                   2371:         checkthis('encrypturl','pscat');
                   2372:         checkthis('problemstatus','pscat');
                   2373:         checkthis('contentopen','pscat');
                   2374:         checkthis('opendate','pscat');
1.210     www      2375:     }
                   2376: 
                   2377:     function checkparts() {
1.562     damieng  2378:         checkthis('hiddenparts','pscat');
                   2379:         checkthis('display','pscat');
                   2380:         checkthis('ordered','pscat');
1.210     www      2381:     }
                   2382: 
                   2383:     function checkstandard() {
                   2384:         checkall(false,'pscat');
1.562     damieng  2385:         checkdates();
                   2386:         checkthis('weight','pscat');
                   2387:         checkthis('maxtries','pscat');
                   2388:         checkthis('type','pscat');
                   2389:         checkthis('problemstatus','pscat');
1.210     www      2390:     }
                   2391: 
1.454     bisitz   2392: // ]]>
1.208     www      2393: </script>
                   2394: ENDSCRIPT
1.453     schualex 2395: 
1.491     bisitz   2396:     $r->print('<hr />');
1.581     raeburn  2397:     &shortCuts($r);
1.491     bisitz   2398:     $r->print('<hr />');
1.453     schualex 2399: }
1.562     damieng  2400: 
                   2401: # Returns parameter categories.
                   2402: #
                   2403: # @returns {hash} - category name -> title in English
1.465     amueller 2404: sub categories {
                   2405:     return ('time_settings' => 'Time Settings',
                   2406:     'grading' => 'Grading',
                   2407:     'tries' => 'Tries',
                   2408:     'problem_appearance' => 'Problem Appearance',
                   2409:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2410:     'hiding' => 'Hiding',
                   2411:     'high_level_randomization' => 'High Level Randomization',
                   2412:     'slots' => 'Slots',
                   2413:     'file_submission' => 'File Submission',
                   2414:     'misc' => 'Miscellaneous' ); 
                   2415: }
                   2416: 
1.562     damieng  2417: # Returns the category for each parameter.
                   2418: #
                   2419: # @returns {hash} - parameter name -> category name
1.465     amueller 2420: sub lookUpTableParameter {
                   2421:  
                   2422:     return ( 
                   2423:         'opendate' => 'time_settings',
                   2424:         'duedate' => 'time_settings',
                   2425:         'answerdate' => 'time_settings',
                   2426:         'interval' => 'time_settings',
                   2427:         'contentopen' => 'time_settings',
                   2428:         'contentclose' => 'time_settings',
                   2429:         'discussend' => 'time_settings',
1.560     damieng  2430:         'printstartdate' => 'time_settings',
                   2431:         'printenddate' => 'time_settings',
1.465     amueller 2432:         'weight' => 'grading',
                   2433:         'handgrade' => 'grading',
                   2434:         'maxtries' => 'tries',
                   2435:         'hinttries' => 'tries',
1.503     raeburn  2436:         'randomizeontries' => 'tries',
1.465     amueller 2437:         'type' => 'problem_appearance',
                   2438:         'problemstatus' => 'problem_appearance',
                   2439:         'display' => 'problem_appearance',
                   2440:         'ordered' => 'problem_appearance',
                   2441:         'numbubbles' => 'problem_appearance',
                   2442:         'tol' => 'behaviour_of_input_fields',
                   2443:         'sig' => 'behaviour_of_input_fields',
                   2444:         'turnoffunit' => 'behaviour_of_input_fields',
                   2445:         'hiddenresource' => 'hiding',
                   2446:         'hiddenparts' => 'hiding',
                   2447:         'discusshide' => 'hiding',
                   2448:         'buttonshide' => 'hiding',
                   2449:         'turnoffeditor' => 'hiding',
                   2450:         'encrypturl' => 'hiding',
1.587     raeburn  2451:         'deeplink' => 'hiding',
1.465     amueller 2452:         'randomorder' => 'high_level_randomization',
                   2453:         'randompick' => 'high_level_randomization',
                   2454:         'available' => 'slots',
                   2455:         'useslots' => 'slots',
                   2456:         'availablestudent' => 'slots',
                   2457:         'uploadedfiletypes' => 'file_submission',
                   2458:         'maxfilesize' => 'file_submission',
                   2459:         'cssfile' => 'misc',
                   2460:         'mapalias' => 'misc',
                   2461:         'acc' => 'misc',
                   2462:         'maxcollaborators' => 'misc',
                   2463:         'scoreformat' => 'misc',
1.514     raeburn  2464:         'lenient' => 'grading',
1.519     raeburn  2465:         'retrypartial' => 'tries',
1.521     raeburn  2466:         'discussvote'  => 'misc',
1.584     raeburn  2467:         'examcode' => 'high_level_randomization',
1.575     raeburn  2468:     );
1.465     amueller 2469: }
                   2470: 
1.562     damieng  2471: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2472: #
                   2473: # @param {string} $name - parameter name
                   2474: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2475: sub whatIsMyCategory {
                   2476:     my $name = shift;
                   2477:     my $catList = shift;
                   2478:     my @list;
                   2479:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2480:     my $cat = $lookUpList{$name};
                   2481:     if (defined($cat)) {
                   2482:         if (!defined($$catList{$cat})){
                   2483:             push @list, ($name);
                   2484:             $$catList{$cat} = \@list;
                   2485:         } else {
                   2486:             push @{${$catList}{$cat}}, ($name);     
                   2487:         }
                   2488:     } else {
                   2489:         if (!defined($$catList{'misc'})){
                   2490:             push @list, ($name);
                   2491:             $$catList{'misc'} = \@list;
                   2492:         } else {
                   2493:             push @{${$catList}{'misc'}}, ($name);     
                   2494:         }
                   2495:     }        
                   2496: }
                   2497: 
1.562     damieng  2498: # Sorts parameter names based on appearance order.
                   2499: #
                   2500: # @param {array reference} name - array reference of parameter names
                   2501: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2502: # @returns {Array} - array of parameter names
1.465     amueller 2503: sub keysindisplayorderCategory {
                   2504:     my ($name,$keyorder)=@_;
                   2505:     return sort {
1.473     amueller 2506:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2507:     } ( @{$name});
                   2508: }
                   2509: 
1.562     damieng  2510: # Returns a hash category name -> order, starting at 1 (integer)
                   2511: #
                   2512: # @returns {hash}
1.467     amueller 2513: sub category_order {
                   2514:     return (
                   2515:         'time_settings' => 1,
                   2516:         'grading' => 2,
                   2517:         'tries' => 3,
                   2518:         'problem_appearance' => 4,
                   2519:         'hiding' => 5,
                   2520:         'behaviour_of_input_fields' => 6,
                   2521:         'high_level_randomization'  => 7,
                   2522:         'slots' => 8,
                   2523:         'file_submission' => 9,
                   2524:         'misc' => 10
                   2525:     );
                   2526: 
                   2527: }
1.453     schualex 2528: 
1.562     damieng  2529: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2530: #
                   2531: # @param {Apache2::RequestRec} $r - the Apache request
                   2532: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2533: # @param {array reference} $pscat - list of selected parameter names
                   2534: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2535: sub parmboxes {
                   2536:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2537:     my %categories = &categories();
1.467     amueller 2538:     my %category_order = &category_order();
1.465     amueller 2539:     my %categoryList = (
                   2540:         'time_settings' => [],
                   2541:         'grading' => [],
                   2542:         'tries' => [],
                   2543:         'problem_appearance' => [],
                   2544:         'behaviour_of_input_fields' => [],
                   2545:         'hiding' => [],
                   2546:         'high_level_randomization' => [],
                   2547:         'slots' => [],
                   2548:         'file_submission' => [],
                   2549:         'misc' => [],
1.489     bisitz   2550:     );
1.510     www      2551: 
1.548     raeburn  2552:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2553:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2554:     }
1.453     schualex 2555:     #part to print the parm-list
1.618   ! raeburn  2556:     $Text::Wrap::columns=60;
        !          2557:     $Text::Wrap::separator='<br />';
1.536     raeburn  2558:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2559:         next if (@{$categoryList{$key}} == 0);
                   2560:         next if ($key eq '');
                   2561:         $r->print('<div class="LC_Box LC_400Box">'
                   2562:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2563:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2564:             next if ($tempkey eq '');
1.536     raeburn  2565:             $r->print('<span class="LC_nobreak">'
                   2566:                      .'<label><input type="checkbox" name="pscat" '
                   2567:                      .'value="'.$tempkey.'" ');
                   2568:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2569:                 $r->print( ' checked="checked"');
                   2570:             }
1.617     raeburn  2571:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? 
                   2572:                              Text::Wrap::wrap('','&nbsp;'x4,$$allparms{$tempkey})
                   2573:                              : $tempkey)
1.536     raeburn  2574:                      .'</label></span><br />'."\n");
1.465     amueller 2575:         }
1.536     raeburn  2576:         $r->print('</div>');
1.465     amueller 2577:     }
1.536     raeburn  2578:     $r->print("\n");
1.453     schualex 2579: }
1.562     damieng  2580: 
                   2581: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2582: #
1.562     damieng  2583: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2584: sub shortCuts {
1.581     raeburn  2585:     my ($r)=@_;
1.453     schualex 2586: 
1.491     bisitz   2587:     # Parameter Selection
                   2588:     $r->print(
                   2589:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2590:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2591:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2592:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2593:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2594:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2595:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2596:        .&Apache::lonhtmlcommon::end_funclist()
                   2597:     );
                   2598: 
                   2599:     # Add Selection for...
                   2600:     $r->print(
                   2601:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2602:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2603:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2604:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2605:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2606:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2607:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2608:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2609:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2610:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2611:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2612:        .&Apache::lonhtmlcommon::end_funclist()
                   2613:     );
1.208     www      2614: }
                   2615: 
1.562     damieng  2616: # Prints HTML to select parts to view (except for the title).
                   2617: # Used by table and overview modes.
                   2618: #
                   2619: # @param {Apache2::RequestRec} $r - the Apache request
                   2620: # @param {hash reference} $allparts - hash parameter part -> part title
                   2621: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2622: sub partmenu {
1.446     bisitz   2623:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2624:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2625:     if ($selsize > 8) {
                   2626:         $selsize = 8;
                   2627:     }
1.446     bisitz   2628: 
1.523     raeburn  2629:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2630:     $r->print('<option value="all"');
1.562     damieng  2631:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2632:     $r->print('>'.&mt('All Parts').'</option>');
                   2633:     my %temphash=();
                   2634:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2635:     foreach my $tempkey (sort {
1.560     damieng  2636:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2637:             } keys(%{$allparts})) {
                   2638:         unless ($tempkey =~ /\./) {
                   2639:             $r->print('<option value="'.$tempkey.'"');
                   2640:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2641:                 $r->print(' selected="selected"');
                   2642:             }
                   2643:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2644:         }
1.208     www      2645:     }
1.446     bisitz   2646:     $r->print('</select>');
1.209     www      2647: }
                   2648: 
1.562     damieng  2649: # Prints HTML to select a user and/or a group.
                   2650: # Used by table mode.
                   2651: #
                   2652: # @param {Apache2::RequestRec} $r - the Apache request
                   2653: # @param {string} $uname - selected user name
                   2654: # @param {string} $id - selected Student/Employee ID
                   2655: # @param {string} $udom - selected user domain
                   2656: # @param {string} $csec - selected section name
                   2657: # @param {string} $cgroup - selected group name
                   2658: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2659: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2660: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2661: sub usermenu {
1.553     raeburn  2662:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2663:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2664:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2665:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2666: function setCourseadv(form,caller) {
                   2667:     if (caller.value == 'st') {
                   2668:         form.courseadv.value = 'none';
                   2669:     } else {
                   2670:         form.courseadv.value = '';
                   2671:     }
                   2672:     return;
                   2673: }
                   2674: ENDJS
1.412     bisitz   2675: 
1.596     raeburn  2676:     my (%chkroles,$stuonly,$courseadv);
                   2677:     if ($env{'form.userroles'} eq 'any') {
                   2678:         $chkroles{'any'} = ' checked="checked"';
                   2679:     } else {
                   2680:         $chkroles{'st'} = ' checked="checked"';
                   2681:         $courseadv = 'none';
                   2682:     }
                   2683:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2684:     if ($crstype eq 'Community') {
                   2685:         $stuonly = &mt('member only');
                   2686:     } else {
                   2687:         $stuonly = &mt('student only');
                   2688:     }
                   2689:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2690:                   &mt("User's role").':&nbsp;'.
                   2691:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2692:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2693:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2694:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2695:     my $sections='';
1.300     albertel 2696:     my %sectionhash = &Apache::loncommon::get_sections();
                   2697: 
1.269     raeburn  2698:     my $groups;
1.553     raeburn  2699:     my %grouphash;
                   2700:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2701:         %grouphash = &Apache::longroup::coursegroups();
                   2702:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2703:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2704:     }
1.299     albertel 2705: 
1.412     bisitz   2706:     my $g_s_header='';
                   2707:     my $g_s_footer='';
1.446     bisitz   2708: 
1.552     raeburn  2709:     my $currsec = $env{'request.course.sec'};
                   2710:     if ($currsec) {
                   2711:         $sections=&mt('Section:').' '.$currsec;
                   2712:         if (%grouphash) {
                   2713:             $sections .= ';'.('&nbsp;' x2);
                   2714:         }
                   2715:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2716:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2717:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2718:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2719:         }
                   2720:         $sections .= '>';
1.548     raeburn  2721:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2722:         $sections.='<option value="'.$section.'" '.
                   2723:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2724:                                                               '</option>';
1.209     www      2725:         }
                   2726:         $sections.='</select>';
1.269     raeburn  2727:     }
1.412     bisitz   2728: 
1.552     raeburn  2729:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2730:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2731:         $sections .= qq|
                   2732: <script type="text/javascript">
1.454     bisitz   2733: // <![CDATA[
1.269     raeburn  2734: function group_or_section(caller) {
                   2735:    if (caller == "cgroup") {
                   2736:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2737:            document.parmform.csec.selectedIndex = 0;
                   2738:        }
                   2739:    } else {
                   2740:        if (document.parmform.csec.selectedIndex != 0) {
                   2741:            document.parmform.cgroup.selectedIndex = 0;
                   2742:        }
                   2743:    }
                   2744: }
1.454     bisitz   2745: // ]]>
1.269     raeburn  2746: </script>
                   2747: |;
1.554     raeburn  2748:     } else {
1.269     raeburn  2749:         $sections .= qq|
                   2750: <script type="text/javascript">
1.454     bisitz   2751: // <![CDATA[
1.269     raeburn  2752: function group_or_section(caller) {
                   2753:     return;
                   2754: }
1.454     bisitz   2755: // ]]>
1.269     raeburn  2756: </script>
                   2757: |;
1.446     bisitz   2758:     }
1.299     albertel 2759: 
                   2760:     if (%grouphash) {
1.597     raeburn  2761:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2762:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2763:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2764:         }
                   2765:         $groups .= '>';
1.548     raeburn  2766:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2767:             $groups.='<option value="'.$grp.'" ';
                   2768:             if ($grp eq $cgroup) {
                   2769:                 unless ((defined($uname)) && ($grp eq '')) {
                   2770:                     $groups .=  'selected="selected" ';
                   2771:                 }
                   2772:             } elsif (!defined($cgroup)) {
                   2773:                 if (@{$usersgroups} == 1) {
                   2774:                     if ($grp eq $$usersgroups[0]) {
                   2775:                         $groups .=  'selected="selected" ';
                   2776:                     }
                   2777:                 }
                   2778:             }
                   2779:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2780:         }
                   2781:         $groups.='</select>';
                   2782:     }
1.412     bisitz   2783: 
1.445     neumanie 2784:     if (%sectionhash || %grouphash) {
1.446     bisitz   2785:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2786:         $r->print($sections.$groups);
1.448     bisitz   2787:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2788:     } else {
                   2789:         $r->print($sections); 
1.445     neumanie 2790:     }
1.446     bisitz   2791: 
                   2792:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2793:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2794:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2795:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2796:                  ,$chooseopt));
1.209     www      2797: }
                   2798: 
1.562     damieng  2799: # Prints HTML to select parameters from a list of all parameters.
                   2800: # Uses parmmenu and parmboxes.
                   2801: # Used by table and overview modes.
1.468     amueller 2802: #
1.562     damieng  2803: # @param {Apache2::RequestRec} $r - the Apache request
                   2804: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2805: # @param {array reference} $pscat - list of selected parameter names
                   2806: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2807: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2808: sub displaymenu {
1.581     raeburn  2809:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2810: 
1.445     neumanie 2811:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2812:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2813: 
1.581     raeburn  2814:     &parmmenu($r);
1.536     raeburn  2815:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2816:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2817:     $r->print(&Apache::loncommon::end_scrollbox());
                   2818: 
                   2819:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2820:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2821:  
1.209     www      2822: }
                   2823: 
1.562     damieng  2824: # Prints HTML to select a map.
                   2825: # Used by table mode and overview mode.
                   2826: #
                   2827: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2828: # @param {hash reference} $allmaps - hash map pc -> map src
                   2829: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2830: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2831: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2832: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2833: sub mapmenu {
1.610     raeburn  2834:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2835:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2836:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2837:     my $tree=[];
                   2838:     my $treeinfo={};
                   2839:     if (defined($navmap)) {
1.499     raeburn  2840:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2841:         my $curRes;
                   2842:         my $depth = 0;
1.468     amueller 2843:         my %parent = ();
                   2844:         my $startcount = 5;
                   2845:         my $lastcontainer = $startcount;
                   2846: # preparing what is to show ...
1.461     neumanie 2847:         while ($curRes = $it->next()) {
                   2848:             if ($curRes == $it->BEGIN_MAP()) {
                   2849:                 $depth++;
1.468     amueller 2850:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2851:             }
                   2852:             if ($curRes == $it->END_MAP()) {
                   2853:                 $depth--;
1.468     amueller 2854:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2855:             }
                   2856:             if (ref($curRes)) {
1.468     amueller 2857:                 my $symb = $curRes->symb();
                   2858:                 my $ressymb = $symb;
1.461     neumanie 2859:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2860:                     my $type = 'sequence';
                   2861:                     if ($curRes->is_page()) {
                   2862:                         $type = 'page';
                   2863:                     }
                   2864:                     my $id= $curRes->id();
1.468     amueller 2865:                     my $srcf = $curRes->src();
                   2866:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2867:                     if(!exists($treeinfo->{$id})) {
                   2868:                         push(@$tree,$id);
1.473     amueller 2869:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2870:                         $treeinfo->{$id} = {
1.461     neumanie 2871:                                     depth => $depth,
                   2872:                                     type  => $type,
1.468     amueller 2873:                                     name  => $resource_name,
                   2874:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2875:                                     };
1.462     neumanie 2876:                     }
1.461     neumanie 2877:                 }
                   2878:             }
                   2879:         }
1.462     neumanie 2880:     }
1.473     amueller 2881: # Show it ...    
1.610     raeburn  2882:     my $rowattr = ' id="mapmenu"';
                   2883:     if ($parmlev eq 'general') {
                   2884:         $rowattr .= ' style="display:none"';
                   2885:     }
                   2886:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2887:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2888:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2889:         my $whitespace =
                   2890:             '<img src="'
                   2891:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2892:            .'" alt="" />';
                   2893: 
1.498     bisitz   2894:         # Info about selectable folders/maps
                   2895:         $r->print(
                   2896:             '<div class="LC_info">'
1.508     www      2897:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2898:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2899:            .'</div>'
                   2900:         );
                   2901: 
1.536     raeburn  2902:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2903:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2904: 
1.498     bisitz   2905:         # Display row: "All Maps or Folders"
                   2906:         $r->print(
1.523     raeburn  2907:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2908:            .'<td>'
                   2909:            .'<label>'
                   2910:            .'<input type="radio" name="pschp"'
1.497     bisitz   2911:         );
                   2912:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2913:         $r->print(
                   2914:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2915:            .&mt('All Maps or Folders')
                   2916:            .'</label>'
                   2917:            .'<hr /></td>'
                   2918:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2919:         );
1.497     bisitz   2920: 
1.532     raeburn  2921:         # Display row: "Main Content"
1.468     amueller 2922:         if (exists($$allmaps{1})) {
1.498     bisitz   2923:             $r->print(
                   2924:                 &Apache::loncommon::start_data_table_row()
                   2925:                .'<td>'
                   2926:                .'<label>'
                   2927:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2928:             );
1.497     bisitz   2929:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2930:             $r->print(
                   2931:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2932:                .$$maptitles{1}
                   2933:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2934:                .'</label>'
                   2935:                .'</td>'
                   2936:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2937:             );
                   2938:         }
1.497     bisitz   2939: 
                   2940:         # Display rows for all course maps and folders
1.468     amueller 2941:         foreach my $id (@{$tree}) {
                   2942:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2943:             # Indentation
1.468     amueller 2944:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2945:             my $indent;
                   2946:             for (my $i = 0; $i < $depth; $i++) {
                   2947:                 $indent.= $whitespace;
                   2948:             }
1.461     neumanie 2949:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2950:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2951:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2952:             }
1.468     amueller 2953:             my $symb_name = $$symbp{$id};
                   2954:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2955:             $symb_name = $tail;
1.498     bisitz   2956:             $r->print(
                   2957:                 &Apache::loncommon::start_data_table_row()
                   2958:                .'<td>'
                   2959:                .'<label>'
1.463     bisitz   2960:             );
1.498     bisitz   2961:             # Only offer radio button for folders/maps which can be parameterized
                   2962:             if ($allmaps_inverted{$symb_name}) {
                   2963:                 $r->print(
                   2964:                     '<input type ="radio" name="pschp"'
                   2965:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2966:                 );
                   2967:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2968:                 $r->print('/>');
                   2969:             } else {
                   2970:                 $r->print($whitespace);
1.461     neumanie 2971:             }
1.498     bisitz   2972:             $r->print(
                   2973:                 $indent.$icon.'&nbsp;'
                   2974:                .$treeinfo->{$id}->{name}
                   2975:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2976:                .'</label>'
                   2977:                .'</td>'
                   2978:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2979:             );
1.461     neumanie 2980:         }
1.497     bisitz   2981: 
1.523     raeburn  2982:         $r->print(&Apache::loncommon::end_data_table().
                   2983:                   '<br style="line-height:2px;" />'.
                   2984:                   &Apache::loncommon::end_scrollbox());
1.209     www      2985:     }
                   2986: }
                   2987: 
1.563     damieng  2988: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2989: # Used by table and overview modes.
                   2990: #
                   2991: # @param {Apache2::RequestRec} $r - the Apache request
                   2992: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2993: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2994: sub levelmenu {
1.446     bisitz   2995:     my ($r,$alllevs,$parmlev)=@_;
                   2996: 
1.548     raeburn  2997:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2998:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2999:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  3000:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   3001:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   3002:         if ($parmlev eq $$alllevs{$lev}) {
                   3003:             $r->print(' selected="selected"');
                   3004:         }
                   3005:         $r->print('>'.&mt($lev).'</option>');
1.208     www      3006:     }
1.446     bisitz   3007:     $r->print("</select>");
1.208     www      3008: }
                   3009: 
1.211     www      3010: 
1.563     damieng  3011: # Returns HTML to select a section (with a select HTML element).
                   3012: # Used by overview mode.
                   3013: #
                   3014: # @param {array reference} $selectedsections - list of selected section ids
                   3015: # @returns {string}
1.211     www      3016: sub sectionmenu {
1.553     raeburn  3017:     my ($selectedsections)=@_;
1.300     albertel 3018:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  3019:     return '' if (!%sectionhash);
1.300     albertel 3020: 
1.552     raeburn  3021:     my (@possibles,$disabled);
                   3022:     if ($env{'request.course.sec'} ne '') {
                   3023:         @possibles = ($env{'request.course.sec'});
                   3024:         $selectedsections = [$env{'request.course.sec'}];
                   3025:         $disabled = ' disabled="disabled"';
                   3026:     } else {
                   3027:         @possibles = ('all',sort(keys(%sectionhash)));
                   3028:     }
1.553     raeburn  3029:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  3030:     foreach my $s (@possibles) {
1.553     raeburn  3031:         $output .= '    <option value="'.$s.'"';
                   3032:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   3033:             $output .= ' selected="selected"';
1.473     amueller 3034:         }
1.553     raeburn  3035:         $output .= '>'."$s</option>\n";
1.300     albertel 3036:     }
1.553     raeburn  3037:     $output .= "</select>\n";
                   3038:     return $output;
1.269     raeburn  3039: }
                   3040: 
1.563     damieng  3041: # Returns HTML to select a group (with a select HTML element).
                   3042: # Used by overview mode.
                   3043: #
                   3044: # @param {array reference} $selectedgroups - list of selected group names
                   3045: # @returns {string}
1.269     raeburn  3046: sub groupmenu {
1.553     raeburn  3047:     my ($selectedgroups)=@_;
                   3048:     my %grouphash;
                   3049:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3050:         %grouphash = &Apache::longroup::coursegroups();
                   3051:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  3052:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  3053:     }
                   3054:     return '' if (!%grouphash);
1.299     albertel 3055: 
1.553     raeburn  3056:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 3057:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  3058:         $output .= '    <option value="'.$group.'"';
                   3059:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   3060:             $output .=  ' selected="selected"';
1.473     amueller 3061:         }
1.553     raeburn  3062:         $output .= '>'."$group</option>\n";
1.211     www      3063:     }
1.553     raeburn  3064:     $output .= "</select>\n";
                   3065:     return $output;
1.211     www      3066: }
                   3067: 
1.563     damieng  3068: # Returns an array with the given parameter split by comma.
                   3069: # Used by assessparms (table mode).
                   3070: #
                   3071: # @param {string} $keyp - the string to split
                   3072: # @returns {Array<string>}
1.210     www      3073: sub keysplit {
                   3074:     my $keyp=shift;
                   3075:     return (split(/\,/,$keyp));
                   3076: }
                   3077: 
1.563     damieng  3078: # Returns the keys in $name, sorted using $keyorder.
                   3079: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3080: # Used by assessparms (table mode) for resource level.
                   3081: #
                   3082: # @param {hash reference} $name - parameter key -> parameter name
                   3083: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3084: # @returns {Array<string>}
1.210     www      3085: sub keysinorder {
                   3086:     my ($name,$keyorder)=@_;
                   3087:     return sort {
1.560     damieng  3088:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3089:     } (keys(%{$name}));
1.210     www      3090: }
                   3091: 
1.563     damieng  3092: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3093: # Used by assessparms (table mode) for map and general levels.
                   3094: #
                   3095: # @param {hash reference} $name - parameter key -> parameter name
                   3096: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3097: # @returns {Array<string>}
1.236     albertel 3098: sub keysinorder_bytype {
                   3099:     my ($name,$keyorder)=@_;
                   3100:     return sort {
1.563     damieng  3101:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3102:         my $tb=(split('_',$b))[-1];
                   3103:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3104:             return ($a cmp $b);
                   3105:         }
                   3106:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3107:     } (keys(%{$name}));
1.236     albertel 3108: }
                   3109: 
1.563     damieng  3110: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3111: # Used by defaultsetter (parameter settings default actions).
                   3112: #
                   3113: # @param {hash reference} $name - hash parameter name -> parameter title
                   3114: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3115: # @returns {Array<string>}
1.211     www      3116: sub keysindisplayorder {
                   3117:     my ($name,$keyorder)=@_;
                   3118:     return sort {
1.560     damieng  3119:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3120:     } (keys(%{$name}));
1.211     www      3121: }
                   3122: 
1.563     damieng  3123: # Prints HTML with a choice to sort results by realm or student first.
                   3124: # Used by overview mode.
                   3125: #
                   3126: # @param {Apache2::RequestRec} $r - the Apache request
                   3127: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3128: # @param {string} $context - newoverview|overview
1.214     www      3129: sub sortmenu {
1.608     raeburn  3130:     my ($r,$sortorder,$context)=@_;
                   3131:     my %text;
                   3132:     if ($context eq 'newoverview') {
                   3133:         %text = &Apache::lonlocal::texthash (
                   3134:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3135:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3136:         );
                   3137:     } else {
                   3138:         %text = &Apache::lonlocal::texthash (
                   3139:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3140:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3141:         );
1.214     www      3142:     }
1.608     raeburn  3143:     my %sortchecked = (
                   3144:        realmstudent => ' checked="checked"',
                   3145:        studentrealm => '',
                   3146:     );
1.214     www      3147:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3148:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3149:         $sortchecked{'realmstudent'} = '';
                   3150:     }
                   3151:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3152:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3153:                   $text{$sorttype}.'</label>');
1.214     www      3154:     }
                   3155: }
                   3156: 
1.563     damieng  3157: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3158: #
                   3159: # @returns {hash}
1.211     www      3160: sub standardkeyorder {
                   3161:     return ('parameter_0_opendate' => 1,
1.473     amueller 3162:         'parameter_0_duedate' => 2,
                   3163:         'parameter_0_answerdate' => 3,
                   3164:         'parameter_0_interval' => 4,
                   3165:         'parameter_0_weight' => 5,
                   3166:         'parameter_0_maxtries' => 6,
                   3167:         'parameter_0_hinttries' => 7,
                   3168:         'parameter_0_contentopen' => 8,
                   3169:         'parameter_0_contentclose' => 9,
                   3170:         'parameter_0_type' => 10,
                   3171:         'parameter_0_problemstatus' => 11,
                   3172:         'parameter_0_hiddenresource' => 12,
                   3173:         'parameter_0_hiddenparts' => 13,
                   3174:         'parameter_0_display' => 14,
                   3175:         'parameter_0_ordered' => 15,
                   3176:         'parameter_0_tol' => 16,
                   3177:         'parameter_0_sig' => 17,
                   3178:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3179:         'parameter_0_discussend' => 19,
                   3180:         'parameter_0_discusshide' => 20,
                   3181:         'parameter_0_discussvote' => 21,
1.560     damieng  3182:         'parameter_0_printstartdate'  =>  22,
                   3183:         'parameter_0_printenddate' =>  23);
1.211     www      3184: }
                   3185: 
1.59      matthew  3186: 
1.560     damieng  3187: # Table mode UI.
1.563     damieng  3188: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3189: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3190: #
                   3191: # Parameters used from the request:
                   3192: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3193: # cgroup - selected group
                   3194: # command - 'set': direct access to table mode for a resource
                   3195: # csec - selected section
                   3196: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3197: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3198: # id - student/employee ID
                   3199: # parmlev - selected level (full|map|general)
                   3200: # part - selected part (unused ?)
                   3201: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3202: # pres_type - &&&-separated parameter types
                   3203: # pres_value - &&&-separated parameter values
                   3204: # prevvisit - '1' if the user has submitted the form before
                   3205: # pscat (multiple values) - selected parameter names
1.566     damieng  3206: # pschp - selected map pc, or 'all'
1.563     damieng  3207: # psprt (multiple values) - list of selected parameter parts
                   3208: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3209: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3210: # symb - resource symb (when a single resource is selected)
                   3211: # udom - selected user domain
                   3212: # uname - selected user name
                   3213: # url - used only with command 'set', the resource url
                   3214: #
                   3215: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3216: # @param $parm_permission - ref to hash of permissions
                   3217: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3218: sub assessparms {
1.1       www      3219: 
1.568     raeburn  3220:     my ($r,$parm_permission) = @_;
1.201     www      3221: 
1.512     foxr     3222: 
                   3223: # -------------------------------------------------------- Variable declaration
1.566     damieng  3224:     my @ids=(); # resource and map ids
                   3225:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3226:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3227:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3228:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3229:     my %uris=(); # hash resource/map id -> resource src
                   3230:     my %maptitles=(); # hash map pc or src -> map title
                   3231:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3232:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3233:     my %alllevs=(); # hash English level title -> value
                   3234: 
                   3235:     my $uname; # selected user name
                   3236:     my $udom; # selected user domain
                   3237:     my $uhome; # server with the user's files, or 'no_host'
                   3238:     my $csec; # selected section name
                   3239:     my $cgroup; # selected group name
                   3240:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3241:     my $numreclinks = 0;
1.446     bisitz   3242: 
1.190     albertel 3243:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3244: 
1.57      albertel 3245:     $alllevs{'Resource Level'}='full';
1.215     www      3246:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3247:     $alllevs{'Course Level'}='general';
                   3248: 
1.563     damieng  3249:     my %allparms; # hash parameter name -> parameter title
                   3250:     my %allparts; # hash parameter part -> part title
1.512     foxr     3251: # ------------------------------------------------------------------------------
                   3252: 
1.210     www      3253: #
                   3254: # Order in which these parameters will be displayed
                   3255: #
1.211     www      3256:     my %keyorder=&standardkeyorder();
                   3257: 
1.512     foxr     3258: #    @ids=();
                   3259: #    %symbp=();       # These seem defined above already.
                   3260: #    %typep=();
1.43      albertel 3261: 
                   3262:     my $message='';
                   3263: 
1.190     albertel 3264:     $csec=$env{'form.csec'};
1.552     raeburn  3265:     if ($env{'request.course.sec'} ne '') {
                   3266:         $csec = $env{'request.course.sec'};    
                   3267:     }
                   3268: 
1.553     raeburn  3269: # Check group privs.
1.269     raeburn  3270:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3271:     my $noeditgrp; 
                   3272:     if ($cgroup ne '') {
                   3273:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3274:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3275:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3276:                 $noeditgrp = 1;
                   3277:             }
                   3278:         }
                   3279:     }
1.188     www      3280: 
1.190     albertel 3281:     if      ($udom=$env{'form.udom'}) {
                   3282:     } elsif ($udom=$env{'request.role.domain'}) {
                   3283:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3284:     } else {
1.473     amueller 3285:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3286:     }
1.468     amueller 3287:     
1.43      albertel 3288: 
1.134     albertel 3289:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3290:     my $pschp=$env{'form.pschp'};
1.506     www      3291: 
                   3292: 
1.134     albertel 3293:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3294:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3295:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3296: 
1.43      albertel 3297:     my $pssymb='';
1.57      albertel 3298:     my $parmlev='';
1.446     bisitz   3299: 
1.190     albertel 3300:     unless ($env{'form.parmlev'}) {
1.57      albertel 3301:         $parmlev = 'map';
                   3302:     } else {
1.190     albertel 3303:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3304:     }
1.26      www      3305: 
1.29      www      3306: # ----------------------------------------------- Was this started from grades?
                   3307: 
1.560     damieng  3308:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3309:             (!$env{'form.dis'})) {
1.473     amueller 3310:         my $url=$env{'form.url'};
                   3311:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3312:         $pssymb=&Apache::lonnet::symbread($url);
                   3313:         if (!@pscat) { @pscat=('all'); }
                   3314:         $pschp='';
1.57      albertel 3315:         $parmlev = 'full';
1.190     albertel 3316:     } elsif ($env{'form.symb'}) {
1.473     amueller 3317:         $pssymb=$env{'form.symb'};
                   3318:         if (!@pscat) { @pscat=('all'); }
                   3319:         $pschp='';
1.57      albertel 3320:         $parmlev = 'full';
1.43      albertel 3321:     } else {
1.473     amueller 3322:         $env{'form.url'}='';
1.43      albertel 3323:     }
                   3324: 
1.190     albertel 3325:     my $id=$env{'form.id'};
1.43      albertel 3326:     if (($id) && ($udom)) {
1.555     raeburn  3327:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3328:         if ($uname) {
                   3329:             $id='';
                   3330:         } else {
                   3331:             $message=
1.540     bisitz   3332:                 '<p class="LC_warning">'.
                   3333:                 &mt('Unknown ID [_1] at domain [_2]',
                   3334:                     "'".$id."'","'".$udom."'").
                   3335:                 '</p>';
1.473     amueller 3336:         }
1.43      albertel 3337:     } else {
1.473     amueller 3338:         $uname=$env{'form.uname'};
1.43      albertel 3339:     }
                   3340:     unless ($udom) { $uname=''; }
                   3341:     $uhome='';
                   3342:     if ($uname) {
1.473     amueller 3343:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3344:         if ($uhome eq 'no_host') {
1.473     amueller 3345:             $message=
1.540     bisitz   3346:                 '<p class="LC_warning">'.
                   3347:                 &mt('Unknown user [_1] at domain [_2]',
                   3348:                     "'".$uname."'","'".$udom."'").
                   3349:                 '</p>';
1.473     amueller 3350:             $uname='';
1.12      www      3351:         } else {
1.473     amueller 3352:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3353:                           $env{'request.course.id'});
                   3354:             if ($csec eq '-1') {
1.596     raeburn  3355:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3356:                 if ($env{'form.userroles'} eq 'any') {
                   3357:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3358:                         $csec = $env{'request.course.sec'};
                   3359:                         $message = '<span class="LC_info">';
                   3360:                         if ($crstype eq 'Community') {
                   3361:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3362:                                             $uname,$udom);
                   3363:                         } else {
                   3364:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3365:                                             $uname,$udom);
                   3366:                         }
                   3367:                         $message .= '</span>';
                   3368:                     } else {
                   3369:                         my @possroles = ('in','ep','ta','cr');
                   3370:                         if ($crstype eq 'Community') {
                   3371:                             unshift(@possroles,'co');
                   3372:                         } else {
                   3373:                             unshift(@possroles,'cc');
                   3374:                         }
                   3375:                         my %not_student_roles =
                   3376:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3377:                                                           \@possroles,[$udom],1,1);
                   3378:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3379:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3380:                         my %sections_by_role;
                   3381:                         foreach my $role (keys(%not_student_roles)) {
                   3382:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3383:                                 my ($rolename,$sec) = ($1,$2);
                   3384:                                 if ($rolename =~ m{^cr/}) {
                   3385:                                     $rolename = 'cr';
                   3386:                                 }
                   3387:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3388:                             }
                   3389:                         }
                   3390:                         my $numroles = scalar(keys(%sections_by_role));
                   3391:                         if ($numroles) {
                   3392:                             foreach my $role (@possroles) {
                   3393:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3394:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3395:                                     $csec = $secs[0];
                   3396:                                     last;
                   3397:                                 }
                   3398:                             }
                   3399:                         }
                   3400:                         if ($csec eq '-1') {
                   3401:                             $message = '<span class="LC_warning">';
                   3402:                             if ($crstype eq 'Community') {
                   3403:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3404:                                                 $uname,$udom);
                   3405:                             } else {
                   3406:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3407:                                                 $uname,$udom);
                   3408:                             }
                   3409:                             $message .= '</span>';
                   3410:                             $uname='';
                   3411:                             if ($env{'request.course.sec'} ne '') {
                   3412:                                 $csec=$env{'request.course.sec'};
                   3413:                             } else {
                   3414:                                 $csec=$env{'form.csec'};
                   3415:                             }
                   3416:                             $cgroup=$env{'form.cgroup'};
                   3417:                         } else {
                   3418:                             $message = '<span class="LC_info">';
                   3419:                             if ($crstype eq 'Community') {
                   3420:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3421:                                          $uname,$udom);
                   3422:                             } else {
                   3423:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3424:                                                 $uname,$udom);
                   3425:                             }
                   3426:                             $message .= '</span>';
                   3427:                         }
                   3428:                     }
1.594     raeburn  3429:                 } else {
1.596     raeburn  3430:                     $message = '<span class="LC_warning">';
                   3431:                     if ($crstype eq 'Community') {
                   3432:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3433:                                          $uname,$udom);
                   3434:                     } else {
                   3435:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3436:                                          $uname,$udom);
                   3437:                     }
                   3438:                     $message .= '</span>';
                   3439:                     $uname='';
                   3440:                     if ($env{'request.course.sec'} ne '') {
                   3441:                         $csec=$env{'request.course.sec'};
                   3442:                     } else {
                   3443:                         $csec=$env{'form.csec'};
                   3444:                     }
                   3445:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3446:                 }
                   3447:             } elsif ($env{'request.course.sec'} ne '') {
                   3448:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3449:                     $message='<span class="LC_warning">'.
1.594     raeburn  3450:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3451:                                   $uname,$udom,$env{'request.course.sec'}).
                   3452:                               '</span>';
                   3453:                     $uname='';
                   3454:                     $csec=$env{'request.course.sec'};
                   3455:                 }
1.269     raeburn  3456:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3457:             }
                   3458:             if ($uname ne '') {
1.473     amueller 3459:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3460:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3461:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3462:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3463:                             .$name{'lastname'}.' '.$name{'generation'}
                   3464:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3465:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3466:                                    $udom,$uname,$env{'request.course.id'});
                   3467:                 if (@usersgroups > 0) {
                   3468:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3469:                         $cgroup = $usersgroups[0];
                   3470:                     }
                   3471:                 } else {
                   3472:                     $cgroup = '';
1.297     raeburn  3473:                 }
1.269     raeburn  3474:             }
1.12      www      3475:         }
1.43      albertel 3476:     }
1.2       www      3477: 
1.43      albertel 3478:     unless ($csec) { $csec=''; }
1.269     raeburn  3479:     unless ($cgroup) { $cgroup=''; }
1.12      www      3480: 
1.14      www      3481: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3482:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3483:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3484:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3485: 
1.582     raeburn  3486:     %allmaps_inverted = reverse(%allmaps);
                   3487: 
1.57      albertel 3488:     $mapp{'0.0'} = '';
                   3489:     $symbp{'0.0'} = '';
1.99      albertel 3490: 
1.14      www      3491: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3492:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3493:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3494:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3495:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3496:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3497:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3498:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3499:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3500:         my $totalstored = 0;
1.605     raeburn  3501:         my $totalskippeduser = 0;
1.546     raeburn  3502:         my $now = time;
1.473     amueller 3503:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3504:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3505:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3506:                 next if ($csec ne $env{'request.course.sec'});
                   3507:             }
1.556     raeburn  3508:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3509:                 next if ($noeditgrp);
1.605     raeburn  3510:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3511:                 if ($uname eq '') {
                   3512:                     $totalskippeduser ++;
                   3513:                     next;
                   3514:                 }
1.557     raeburn  3515:             }
                   3516:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3517:                 $namematch = 'maplevelrecurse';
                   3518:             }
1.556     raeburn  3519:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3520:                 my (@ok_slots,@fail_slots,@del_slots);
                   3521:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3522:                 my ($level,@all) =
                   3523:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3524:                                      $csec,$cgroup,$courseopt);
                   3525:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3526:                     next if ($slot_name eq '');
                   3527:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3528:                         push(@ok_slots,$slot_name);
                   3529: 
                   3530:                     } else {
                   3531:                         push(@fail_slots,$slot_name);
                   3532:                     }
                   3533:                 }
                   3534:                 if (@ok_slots) {
                   3535:                     $values[$i] = join(':',@ok_slots);
                   3536:                 } else {
                   3537:                     $values[$i] = '';
                   3538:                 }
                   3539:                 if ($all[$level] ne '') {
                   3540:                     my @existing = split(/:/,$all[$level]);
                   3541:                     foreach my $slot_name (@existing) {
                   3542:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3543:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3544:                                 push(@del_slots,$slot_name);
                   3545:                             }
                   3546:                         }
                   3547:                     }
                   3548:                 }
1.554     raeburn  3549:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3550:                 $name = $1;
1.533     raeburn  3551:                 my $val = $values[$i];
1.549     raeburn  3552:                 my $valmatch = '';
1.533     raeburn  3553:                 if ($name eq 'examcode') {
1.544     raeburn  3554:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3555:                         $val = 'valid';
                   3556:                     }
1.546     raeburn  3557:                 } elsif ($name eq 'printstartdate') {
                   3558:                     if ($val =~ /^\d+$/) {
                   3559:                         if ($val > $now) {
                   3560:                             $val = 'future';
                   3561:                         }
                   3562:                     } 
                   3563:                 } elsif ($name eq 'printenddate') {
                   3564:                     if ($val =~ /^\d+$/) {
                   3565:                         if ($val < $now) {
                   3566:                             $val = 'past';
                   3567:                         }
                   3568:                     }
1.549     raeburn  3569:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3570:                     my $stringtype = &get_stringtype($name);
                   3571:                     my $stringmatch = &standard_string_matches($stringtype);
                   3572:                     if (ref($stringmatch) eq 'ARRAY') {
                   3573:                         foreach my $item (@{$stringmatch}) {
                   3574:                             if (ref($item) eq 'ARRAY') {
                   3575:                                 my ($regexpname,$pattern) = @{$item};
                   3576:                                 if ($pattern ne '') {
                   3577:                                     if ($val =~ /$pattern/) {
                   3578:                                         $valmatch = $regexpname;
                   3579:                                         $val = '';
                   3580:                                         last;
                   3581:                                     }
                   3582:                                 }
                   3583:                             }
                   3584:                         }
                   3585:                     }
1.554     raeburn  3586:                 } elsif ($name eq 'interval') {
                   3587:                     my $intervaltype = &get_intervaltype($name);
                   3588:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3589:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3590:                         foreach my $item (@{$intervalmatch}) {
                   3591:                             if (ref($item) eq 'ARRAY') {
                   3592:                                 my ($regexpname,$pattern) = @{$item};
                   3593:                                 if ($pattern ne '') {
                   3594:                                     if ($val =~ /$pattern/) {
                   3595:                                         $valmatch = $regexpname;
                   3596:                                         $val = '';
                   3597:                                         last;
                   3598:                                     }
                   3599:                                 }
                   3600:                             }
                   3601:                         }
                   3602:                     }
1.533     raeburn  3603:                 }
1.504     raeburn  3604:                 $needsrelease =
1.557     raeburn  3605:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3606:                 if ($needsrelease) {
1.505     raeburn  3607:                     unless ($got_chostname) {
1.514     raeburn  3608:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3609:                         $got_chostname = 1;
1.546     raeburn  3610:                     } 
1.557     raeburn  3611:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3612:                                                           $needsrelease,
                   3613:                                                           $cmajor,$cminor);
1.500     raeburn  3614:                 }
1.437     raeburn  3615:             }
1.504     raeburn  3616:             if ($needsnewer) {
1.557     raeburn  3617:                 undef($namematch);
                   3618:             } else {
                   3619:                 my $currneeded;
                   3620:                 if ($needsrelease) {
                   3621:                     $currneeded = $needsrelease;
                   3622:                 }
                   3623:                 if ($namematch) {
                   3624:                     $needsrelease =
                   3625:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3626:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3627:                         unless ($got_chostname) {
                   3628:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3629:                             $got_chostname = 1;
                   3630:                         }
                   3631:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3632:                                                               $needsrelease,
                   3633:                                                               $cmajor,$cminor);
                   3634:                     } else {
                   3635:                         undef($namematch);
                   3636:                     }
                   3637:                 }
                   3638:             }
                   3639:             if ($needsnewer) {
                   3640:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3641:                                                 $cminor,$needsrelease);
                   3642:             } else {
                   3643:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3644:                                      $values[$i],
                   3645:                                      $types[$i],
                   3646:                                      $uname,$udom,$csec,$cgroup);
                   3647:                 $totalstored ++;
                   3648:             }
1.473     amueller 3649:         }
1.68      www      3650: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3651:         if ($totalstored) {
                   3652:             $message.='<p class="LC_warning">'
1.605     raeburn  3653:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3654:                      .'<br />'
1.504     raeburn  3655:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3656:                      .&Apache::loncommon::help_open_topic('Caching')
                   3657:                      .'</p>';
1.605     raeburn  3658:         } else {
                   3659:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3660:         }
                   3661:         if ($totalskippeduser) {
                   3662:             $message .= '<p class="LC_warning">';
                   3663:             if ($uhome eq 'no_host') {
                   3664:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3665:                                 $totalskippeduser);
                   3666:             } elsif ($env{'form.userroles'} eq 'any') {
                   3667:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3668:                                 $totalskippeduser);
                   3669:             } else {
                   3670:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3671:                                 $totalskippeduser);
                   3672:             }
                   3673:             $message .= '</p>';
1.504     raeburn  3674:         }
1.68      www      3675:     }
1.584     raeburn  3676: 
1.57      albertel 3677: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3678:     if ($pscat[0] eq "all") {
                   3679:         @pscat = (keys(%allparms));
                   3680:     }
                   3681:     if (!@pscat) {
                   3682:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3683:     };
                   3684:     if ($psprt[0] eq "all" || !@psprt) {
                   3685:         @psprt = (keys(%allparts));
                   3686:     }
1.2       www      3687: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3688: 
1.531     raeburn  3689:     my $crstype = &Apache::loncommon::course_type();
                   3690:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3691: 
1.548     raeburn  3692:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3693:             'date_interval','int','float','string','string_lenient',
                   3694:             'string_examcode','string_deeplink','string_discussvote',
                   3695:             'string_useslots','string_problemstatus','string_ip',
                   3696:             'string_questiontype') {
1.473     amueller 3697:         $r->print('<input type="hidden" value="'.
1.563     damieng  3698:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3699:             '" name="recent_'.$item.'" />');
1.44      albertel 3700:     }
1.446     bisitz   3701: 
1.459     bisitz   3702:     # ----- Start Parameter Selection
                   3703: 
1.606     raeburn  3704:     # Hide parm selection and possibly table?
                   3705:     my ($tablejs,$tabledivsty);
                   3706:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3707:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3708:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3709:         $tabledivsty = ' style="display:none"';
                   3710:     }
1.459     bisitz   3711:     $r->print(<<ENDPARMSELSCRIPT);
                   3712: <script type="text/javascript">
                   3713: // <![CDATA[
                   3714: function parmsel_show() {
1.562     damieng  3715:     document.getElementById('parmsel').style.display = "";
                   3716:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3717:     $tablejs
1.459     bisitz   3718: }
                   3719: // ]]>
                   3720: </script>
                   3721: ENDPARMSELSCRIPT
1.474     amueller 3722:     
1.445     neumanie 3723:     if (!$pssymb) {
1.563     damieng  3724:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3725:         my $parmselhiddenstyle=' style="display:none"';
                   3726:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3727:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3728:         } else  {
                   3729:            $r->print('<div id="parmsel">');
                   3730:         }
                   3731: 
1.491     bisitz   3732:         # Step 1
1.523     raeburn  3733:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3734:         $r->print('
1.474     amueller 3735: <script type="text/javascript">
1.523     raeburn  3736: // <![CDATA['.
                   3737:                  &showhide_js().'
1.474     amueller 3738: // ]]>
                   3739: </script>
1.523     raeburn  3740: ');
                   3741:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3742:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3743:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3744:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3745:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3746:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3747:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3748:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3749:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3750: 
                   3751:         # Step 2
1.523     raeburn  3752:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3753:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3754: 
                   3755:         # Step 3
1.523     raeburn  3756:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3757:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3758:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3759:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3760:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3761: 
                   3762:         # Update Display Button
1.486     www      3763:         $r->print('<p>'
                   3764:              .'<input type="submit" name="dis"'
1.511     www      3765:              .' value="'.&mt('Update Display').'" />'
1.486     www      3766:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3767:              .'</p>');
                   3768:         $r->print('</div>');
1.491     bisitz   3769: 
1.486     www      3770:         # Offer link to display parameter selection again
                   3771:         $r->print('<p id="parmsellink"');
                   3772:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3773:            $r->print($parmselhiddenstyle);
                   3774:         }
                   3775:         $r->print('>'
                   3776:              .'<a href="javascript:parmsel_show()">'
                   3777:              .&mt('Change Parameter Selection')
                   3778:              .'</a>'
                   3779:              .'</p>');
1.44      albertel 3780:     } else {
1.478     amueller 3781:         # parameter screen for a single resource. 
1.486     www      3782:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3783:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3784:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3785:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3786:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3787:                   '<br />');
                   3788:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3789:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3790:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3791:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3792:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3793:         $r->print('<p>'
1.459     bisitz   3794:              .'<input type="submit" name="dis"'
1.511     www      3795:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3796:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3797:              .'</p>');
1.459     bisitz   3798:     }
1.478     amueller 3799:     
1.486     www      3800:     # ----- End Parameter Selection
1.57      albertel 3801: 
1.459     bisitz   3802:     # Display Messages
                   3803:     $r->print('<div>'.$message.'</div>');
1.210     www      3804: 
1.57      albertel 3805: 
                   3806:     my @temp_pscat;
                   3807:     map {
                   3808:         my $cat = $_;
                   3809:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3810:     } @pscat;
                   3811: 
                   3812:     @pscat = @temp_pscat;
                   3813: 
1.548     raeburn  3814: 
1.209     www      3815:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3816: # ----------------------------------------------------------------- Start Table
1.57      albertel 3817:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3818:         my $csuname=$env{'user.name'};
                   3819:         my $csudom=$env{'user.domain'};
1.568     raeburn  3820:         my $readonly = 1;
                   3821:         if ($parm_permission->{'edit'}) {
                   3822:             undef($readonly); 
                   3823:         }
1.606     raeburn  3824:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3825: 
1.203     www      3826:         if ($parmlev eq 'full') {
1.506     www      3827: #
                   3828: # This produces the cascading table output of parameters
                   3829: #
1.578     raeburn  3830:             my $coursespan=$csec?8:5;
                   3831:             my $userspan=3;
1.560     damieng  3832:             if ($cgroup ne '') {
1.578     raeburn  3833:                 $coursespan += 3;
1.560     damieng  3834:             }
1.473     amueller 3835: 
1.560     damieng  3836:             $r->print(&Apache::loncommon::start_data_table());
                   3837:             #
                   3838:             # This produces the headers
                   3839:             #
                   3840:             $r->print('<tr><td colspan="5"></td>');
                   3841:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3842:             if ($uname) {
1.473     amueller 3843:                 if (@usersgroups > 1) {
1.560     damieng  3844:                     $userspan ++;
                   3845:                 }
                   3846:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3847:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3848:             }
                   3849:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3850:                 'pie'    => "Parameter in Effect",
                   3851:                 'csv'    => "Current Session Value",
1.472     amueller 3852:                 'rl'     => "Resource Level",
1.473     amueller 3853:                 'ic'     => 'in Course',
                   3854:                 'aut'    => "Assessment URL and Title",
                   3855:                 'type'   => 'Type',
                   3856:                 'emof'   => "Enclosing Map or Folder",
                   3857:                 'part'   => 'Part',
1.472     amueller 3858:                 'pn'     => 'Parameter Name',
1.473     amueller 3859:                 'def'    => 'default',
                   3860:                 'femof'  => 'from Enclosing Map or Folder',
                   3861:                 'gen'    => 'general',
                   3862:                 'foremf' => 'for Enclosing Map or Folder',
                   3863:                 'fr'     => 'for Resource'
                   3864:             );
1.560     damieng  3865:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3866: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3867: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3868: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3869: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3870: 
1.10      www      3871: ENDTABLETWO
1.560     damieng  3872:             if ($csec) {
1.578     raeburn  3873:                 $r->print('<th colspan="3">'.
1.560     damieng  3874:                 &mt("in Section")." $csec</th>");
                   3875:             }
                   3876:             if ($cgroup) {
1.578     raeburn  3877:                 $r->print('<th colspan="3">'.
1.472     amueller 3878:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3879:             }
                   3880:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3881: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3882: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3883: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3884: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3885: ENDTABLEHEADFOUR
1.57      albertel 3886: 
1.560     damieng  3887:             if ($csec) {
1.578     raeburn  3888:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3889:             }
1.473     amueller 3890: 
1.560     damieng  3891:             if ($cgroup) {
1.578     raeburn  3892:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3893:             }
                   3894: 
                   3895:             if ($uname) {
                   3896:                 if (@usersgroups > 1) {
                   3897:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3898:                 }
1.578     raeburn  3899:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3900:             }
                   3901: 
                   3902:             $r->print('</tr>');
1.506     www      3903: #
                   3904: # Done with the headers
                   3905: # 
1.560     damieng  3906:             my $defbgone='';
                   3907:             my $defbgtwo='';
                   3908:             my $defbgthree = '';
1.57      albertel 3909: 
1.560     damieng  3910:             foreach my $rid (@ids) {
1.57      albertel 3911: 
                   3912:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3913:                 if ((!$pssymb &&
1.560     damieng  3914:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3915:                         ||
                   3916:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3917: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3918:                     if ($defbgone eq '#E0E099') {
                   3919:                         $defbgone='#E0E0DD';
1.57      albertel 3920:                     } else {
1.419     bisitz   3921:                         $defbgone='#E0E099';
1.57      albertel 3922:                     }
1.419     bisitz   3923:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3924:                         $defbgtwo='#FFFFDD';
1.57      albertel 3925:                     } else {
1.473     amueller 3926:                         $defbgtwo='#FFFF99';
1.57      albertel 3927:                     }
1.419     bisitz   3928:                     if ($defbgthree eq '#FFBB99') {
                   3929:                         $defbgthree='#FFBBDD';
1.269     raeburn  3930:                     } else {
1.419     bisitz   3931:                         $defbgthree='#FFBB99';
1.269     raeburn  3932:                     }
                   3933: 
1.57      albertel 3934:                     my $thistitle='';
                   3935:                     my %name=   ();
                   3936:                     undef %name;
                   3937:                     my %part=   ();
                   3938:                     my %display=();
                   3939:                     my %type=   ();
                   3940:                     my %default=();
1.196     www      3941:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3942:                     my $toolsymb;
                   3943:                     if ($uri =~ /ext\.tool$/) {
                   3944:                         $toolsymb = $symbp{$rid};
                   3945:                     }
1.57      albertel 3946: 
1.506     www      3947:                     my $filter=$env{'form.filter'};
1.548     raeburn  3948:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3949:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3950:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3951:     # We may only want certain parameters listed
                   3952:                             if ($filter) {
                   3953:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3954:                             }
                   3955:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3956:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3957: 
1.584     raeburn  3958:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3959:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3960:                                 my $identifier;
                   3961:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3962:                                     $identifier = $1;
                   3963:                                 }
                   3964:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3965:                             } else {
                   3966:                                 $display{$tempkeyp} = $parmdis;
                   3967:                             }
                   3968:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3969:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3970:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3971:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3972:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3973:                         }
                   3974:                     }
1.548     raeburn  3975:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3976:                     if ($totalparms>0) {
1.560     damieng  3977:                         my $firstrow=1;
1.473     amueller 3978:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3979:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3980:                         my @recurseup;
                   3981:                         if (ref($navmap) && $mapp{$rid}) {
                   3982:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3983:                         }
1.419     bisitz   3984:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3985:                              ' rowspan='.$totalparms.
1.419     bisitz   3986:                              '><tt><font size="-1">'.
1.57      albertel 3987:                              join(' / ',split(/\//,$uri)).
                   3988:                              '</font></tt><p><b>'.
1.154     albertel 3989:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3990:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3991:                           &escape($symbp{$rid}).
1.336     albertel 3992:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3993:                              " target=\"_self\">$title");
1.57      albertel 3994: 
                   3995:                         if ($thistitle) {
1.473     amueller 3996:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3997:                         }
                   3998:                         $r->print('</a></b></td>');
1.419     bisitz   3999:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 4000:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   4001:                                       '</td>');
                   4002: 
1.419     bisitz   4003:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 4004:                                       ' rowspan='.$totalparms.
1.238     www      4005:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  4006:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 4007:                             unless ($firstrow) {
                   4008:                                 $r->print('<tr>');
                   4009:                             } else {
                   4010:                                 undef $firstrow;
                   4011:                             }
1.548     raeburn  4012:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 4013:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  4014:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  4015:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   4016:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   4017:                                        \$numreclinks);
1.57      albertel 4018:                         }
                   4019:                     }
                   4020:                 }
                   4021:             } # end foreach ids
1.43      albertel 4022: # -------------------------------------------------- End entry for one resource
1.517     www      4023:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      4024:         } # end of  full
1.57      albertel 4025: #--------------------------------------------------- Entry for parm level map
                   4026:         if ($parmlev eq 'map') {
1.419     bisitz   4027:             my $defbgone = '#E0E099';
                   4028:             my $defbgtwo = '#FFFF99';
                   4029:             my $defbgthree = '#FFBB99';
1.57      albertel 4030: 
                   4031:             my %maplist;
                   4032: 
                   4033:             if ($pschp eq 'all') {
1.446     bisitz   4034:                 %maplist = %allmaps;
1.57      albertel 4035:             } else {
                   4036:                 %maplist = ($pschp => $mapp{$pschp});
                   4037:             }
                   4038: 
                   4039: #-------------------------------------------- for each map, gather information
                   4040:             my $mapid;
1.607     raeburn  4041:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 4042:                 my $maptitle = $maplist{$mapid};
1.57      albertel 4043: 
                   4044: #-----------------------  loop through ids and get all parameter types for map
                   4045: #-----------------------------------------          and associated information
                   4046:                 my %name = ();
                   4047:                 my %part = ();
                   4048:                 my %display = ();
                   4049:                 my %type = ();
                   4050:                 my %default = ();
                   4051:                 my $map = 0;
                   4052: 
1.473     amueller 4053: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   4054: 
1.548     raeburn  4055:                 foreach my $id (@ids) {
                   4056:                     ($map)=($id =~ /([\d]*?)\./);
                   4057:                     my $rid = $id;
1.446     bisitz   4058: 
1.57      albertel 4059: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   4060: 
1.560     damieng  4061:                     if ($map eq $mapid) {
1.473     amueller 4062:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4063:                         my $toolsymb;
                   4064:                         if ($uri =~ /ext\.tool$/) {
                   4065:                             $toolsymb = $symbp{$rid};
                   4066:                         }
1.582     raeburn  4067: 
1.57      albertel 4068: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   4069: 
                   4070: #--------------------------------------------------------------------
                   4071: # @catmarker contains list of all possible parameters including part #s
                   4072: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4073: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4074: # When storing information, store as part 0
                   4075: # When requesting information, request from full part
                   4076: #-------------------------------------------------------------------
1.548     raeburn  4077:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4078:                             my $tempkeyp = $fullkeyp;
                   4079:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4080: 
1.548     raeburn  4081:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4082:                                 $part{$tempkeyp}="0";
1.584     raeburn  4083:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4084:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4085:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4086:                                     my $identifier;
                   4087:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4088:                                         $identifier = $1;
                   4089:                                     }
                   4090:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4091:                                 } else {
                   4092:                                     $display{$tempkeyp} = $parmdis;
                   4093:                                 }
                   4094:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4095:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4096:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4097:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4098:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4099:                               }
                   4100:                         } # end loop through keys
1.560     damieng  4101:                     }
1.57      albertel 4102:                 } # end loop through ids
1.446     bisitz   4103: 
1.57      albertel 4104: #---------------------------------------------------- print header information
1.133     www      4105:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4106:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4107:                 my $tmp="";
1.57      albertel 4108:                 if ($uname) {
1.473     amueller 4109:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4110:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4111:                         &mt('in')." \n";
1.57      albertel 4112:                 } else {
1.401     bisitz   4113:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4114:                 }
1.269     raeburn  4115:                 if ($cgroup) {
1.401     bisitz   4116:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4117:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4118:                     $csec = '';
                   4119:                 } elsif ($csec) {
1.401     bisitz   4120:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4121:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4122:                 }
1.401     bisitz   4123:                 $r->print('<div align="center"><h4>'
                   4124:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4125:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4126:                              ,$tmp
                   4127:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4128:                              )
                   4129:                          ."<br /></h4>\n"
1.422     bisitz   4130:                 );
1.57      albertel 4131: #---------------------------------------------------------------- print table
1.419     bisitz   4132:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4133:                          .&Apache::loncommon::start_data_table_header_row()
                   4134:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4135:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4136:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4137:                          .&Apache::loncommon::end_data_table_header_row()
                   4138:                 );
1.57      albertel 4139: 
1.582     raeburn  4140:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4141:                 my @recurseup;
                   4142:                 if (ref($navmap)) {
                   4143:                      my $mapres = $navmap->getByMapPc($mapid);
                   4144:                      if (ref($mapres)) {
                   4145:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4146:                      }
                   4147:                 }
                   4148: 
                   4149: 
1.548     raeburn  4150:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4151:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4152:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4153:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4154:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4155:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4156:                            \$numreclinks);
1.57      albertel 4157:                 }
1.422     bisitz   4158:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4159:                          .'</div>'
                   4160:                 );
1.57      albertel 4161:             } # end each map
                   4162:         } # end of $parmlev eq map
                   4163: #--------------------------------- Entry for parm level general (Course level)
                   4164:         if ($parmlev eq 'general') {
1.473     amueller 4165:             my $defbgone = '#E0E099';
1.419     bisitz   4166:             my $defbgtwo = '#FFFF99';
                   4167:             my $defbgthree = '#FFBB99';
1.57      albertel 4168: 
                   4169: #-------------------------------------------- for each map, gather information
                   4170:             my $mapid="0.0";
                   4171: #-----------------------  loop through ids and get all parameter types for map
                   4172: #-----------------------------------------          and associated information
                   4173:             my %name = ();
                   4174:             my %part = ();
                   4175:             my %display = ();
                   4176:             my %type = ();
                   4177:             my %default = ();
1.446     bisitz   4178: 
1.548     raeburn  4179:             foreach $id (@ids) {
                   4180:                 my $rid = $id;
1.446     bisitz   4181: 
1.196     www      4182:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4183:                 my $toolsymb;
                   4184:                 if ($uri =~ /ext\.tool$/) {
                   4185:                     $toolsymb = $symbp{$rid};
                   4186:                 }
1.57      albertel 4187: 
                   4188: #--------------------------------------------------------------------
                   4189: # @catmarker contains list of all possible parameters including part #s
                   4190: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4191: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4192: # When storing information, store as part 0
                   4193: # When requesting information, request from full part
                   4194: #-------------------------------------------------------------------
1.548     raeburn  4195:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4196:                     my $tempkeyp = $fullkeyp;
                   4197:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4198:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4199:                         $part{$tempkeyp}="0";
1.584     raeburn  4200:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4201:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4202:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4203:                             my $identifier;
                   4204:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4205:                                 $identifier = $1;
                   4206:                             }
                   4207:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4208:                         } else {
                   4209:                             $display{$tempkeyp} = $parmdis;
                   4210:                         }
                   4211:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4212:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4213:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4214:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4215:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4216:                     }
1.57      albertel 4217:                 } # end loop through keys
                   4218:             } # end loop through ids
1.446     bisitz   4219: 
1.57      albertel 4220: #---------------------------------------------------- print header information
1.473     amueller 4221:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4222:             $r->print(<<ENDMAPONE);
1.419     bisitz   4223: <center>
                   4224: <h4>$setdef
1.135     albertel 4225: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4226: ENDMAPONE
                   4227:             if ($uname) {
1.473     amueller 4228:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4229:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4230:             } else {
1.135     albertel 4231:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4232:             }
1.446     bisitz   4233: 
1.135     albertel 4234:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4235:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4236:             $r->print("</h4>\n");
1.57      albertel 4237: #---------------------------------------------------------------- print table
1.419     bisitz   4238:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4239:                      .&Apache::loncommon::start_data_table_header_row()
                   4240:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4241:                      .'<th>'.&mt('Default Value').'</th>'
                   4242:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4243:                      .&Apache::loncommon::end_data_table_header_row()
                   4244:             );
1.57      albertel 4245: 
1.548     raeburn  4246:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4247:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4248:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4249:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4250:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4251:                            $readonly);
1.57      albertel 4252:             }
1.419     bisitz   4253:             $r->print(&Apache::loncommon::end_data_table()
                   4254:                      .'</p>'
                   4255:                      .'</center>'
                   4256:             );
1.57      albertel 4257:         } # end of $parmlev eq general
1.606     raeburn  4258:         $r->print('</div>');
1.43      albertel 4259:     }
1.507     www      4260:     $r->print('</form>');
1.582     raeburn  4261:     if ($numreclinks) {
                   4262:         $r->print(<<"END");
                   4263: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4264: <input type="hidden" name="pschp" />
                   4265: <input type="hidden" name="pscat" />
                   4266: <input type="hidden" name="psprt" />
                   4267: <input type="hidden" name="hideparmsel" value="hidden" />
                   4268: </form>
                   4269: <script type="text/javascript">
                   4270: function pjumprec(rid,name,part) {
                   4271:     document.forms.recurseform.pschp.value = rid;
                   4272:     document.forms.recurseform.pscat.value = name;
                   4273:     document.forms.recurseform.psprt.value = part;
                   4274:     document.forms.recurseform.submit();
                   4275:     return false;
                   4276: }
                   4277: </script>
                   4278: END
                   4279:     }
1.507     www      4280:     &endSettingsScreen($r);
                   4281:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4282: } # end sub assessparms
1.30      www      4283: 
1.560     damieng  4284: 
                   4285: 
1.120     www      4286: ##################################################
1.560     damieng  4287: # OVERVIEW MODE
1.207     www      4288: ##################################################
1.124     www      4289: 
1.563     damieng  4290: my $tableopen; # boolean, true if HTML table is already opened
                   4291: 
                   4292: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4293: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4294: # @returns {string}
1.124     www      4295: sub tablestart {
1.576     raeburn  4296:     my ($readonly,$is_map) = @_;
1.124     www      4297:     if ($tableopen) {
1.552     raeburn  4298:         return '';
1.124     www      4299:     } else {
1.552     raeburn  4300:         $tableopen=1;
                   4301:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4302:         if ($readonly) {
                   4303:             $output .= '<th>'.&mt('Current value').'</th>';
                   4304:         } else {
1.576     raeburn  4305:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4306:                        '<th>'.&mt('Set to ...').'</th>';
                   4307:             if ($is_map) {
                   4308:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4309:             }
1.552     raeburn  4310:         }
                   4311:         $output .= '</tr>';
                   4312:         return $output;
1.124     www      4313:     }
                   4314: }
                   4315: 
1.563     damieng  4316: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4317: # @returns {string}
1.124     www      4318: sub tableend {
                   4319:     if ($tableopen) {
1.560     damieng  4320:         $tableopen=0;
                   4321:         return &Apache::loncommon::end_data_table();
1.124     www      4322:     } else {
1.560     damieng  4323:         return'';
1.124     www      4324:     }
                   4325: }
                   4326: 
1.563     damieng  4327: # Reads course and user information.
                   4328: # If the context is looking for a scalar, returns the course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db) with added student data from lonnet::get_userresdata (which reads the user's resourcedata.db).
                   4329: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4330: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4331: # @param {string} $crs - course number
                   4332: # @param {string} $dom - course domain
                   4333: # @returns {hash reference|Array}
1.207     www      4334: sub readdata {
                   4335:     my ($crs,$dom)=@_;
                   4336: # Read coursedata
                   4337:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4338: # Read userdata
                   4339: 
                   4340:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4341:     foreach my $user (keys(%$classlist)) {
                   4342:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4343:             my ($tuname,$tudom)=($1,$2);
                   4344:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4345:             foreach my $userkey (keys(%{$useropt})) {
                   4346:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4347:                     my $newkey=$userkey;
1.548     raeburn  4348:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4349:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4350:                 }
                   4351:             }
1.473     amueller 4352:         }
                   4353:     }
1.552     raeburn  4354:     if (wantarray) {
                   4355:         return ($resourcedata,$classlist);
                   4356:     } else {
                   4357:         return $resourcedata;
                   4358:     }
1.207     www      4359: }
                   4360: 
                   4361: 
1.563     damieng  4362: # Stores parameter data, using form parameters directly.
                   4363: #
                   4364: # Uses the following form parameters. The variable part in the names is a resourcedata key (except for a modification for user data).
1.588     raeburn  4365: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4366: # del_* - remove a parameter
                   4367: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4368: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4369: # key_* - date values
                   4370: # days_* - for date intervals
                   4371: # hours_* - for date intervals
                   4372: # minutes_* - for date intervals
                   4373: # seconds_* - for date intervals
                   4374: # done_* - for date intervals
                   4375: # typeof_* - parameter type
                   4376: # 
                   4377: # @param {Apache2::RequestRec} $r - the Apache request
                   4378: # @param {string} $crs - course number
                   4379: # @param {string} $dom - course domain
1.208     www      4380: sub storedata {
                   4381:     my ($r,$crs,$dom)=@_;
1.207     www      4382: # Set userlevel immediately
                   4383: # Do an intermediate store of course level
                   4384:     my $olddata=&readdata($crs,$dom);
1.124     www      4385:     my %newdata=();
                   4386:     undef %newdata;
                   4387:     my @deldata=();
1.576     raeburn  4388:     my @delrec=();
                   4389:     my @delnonrec=();
1.124     www      4390:     undef @deldata;
1.504     raeburn  4391:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4392:     my $now = time;
1.560     damieng  4393:     foreach my $key (keys(%env)) {
                   4394:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4395:             my $cmd=$1;
                   4396:             my $thiskey=$2;
1.576     raeburn  4397:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4398:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4399:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4400:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4401:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4402:                     $altkey = $thiskey;
                   4403:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4404:                     if ($env{'form.rec_'.$thiskey}) {
                   4405:                         $recursive = 1;
                   4406:                     }
                   4407:                 }
                   4408:             }
1.560     damieng  4409:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4410:             if ($tuname) {
1.576     raeburn  4411:                 $tkey=$thiskey;
1.560     damieng  4412:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4413:                 if ($altkey) {
                   4414:                     $tkeynonrec = $tkey; 
                   4415:                     $tkeyrec = $altkey;
                   4416:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4417:                 }
1.560     damieng  4418:             }
                   4419:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4420:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4421:                 if ($cmd eq 'set') {
                   4422:                     $data=$env{$key};
                   4423:                     $valmatch = '';
                   4424:                     $valchk = $data;
                   4425:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4426:                     $text = &mt('Saved modified parameter for');
                   4427:                     if ($typeof eq 'string_questiontype') {
                   4428:                         $name = 'type';
1.588     raeburn  4429:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4430:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4431:                         my $stringmatch = &standard_string_matches($typeof);
                   4432:                         if (ref($stringmatch) eq 'ARRAY') {
                   4433:                             foreach my $item (@{$stringmatch}) {
                   4434:                                 if (ref($item) eq 'ARRAY') {
                   4435:                                     my ($regexpname,$pattern) = @{$item};
                   4436:                                     if ($pattern ne '') {
                   4437:                                         if ($data =~ /$pattern/) {
                   4438:                                             $valmatch = $regexpname;
                   4439:                                             $valchk = '';
                   4440:                                             last;
                   4441:                                         }
1.560     damieng  4442:                                     }
1.549     raeburn  4443:                                 }
                   4444:                             }
                   4445:                         }
1.563     damieng  4446:                     } elsif ($typeof eq 'string_discussvote') {
                   4447:                         $name = 'discussvote';
                   4448:                     } elsif ($typeof eq 'string_examcode') {
                   4449:                         $name = 'examcode';
                   4450:                         if (&Apache::lonnet::validCODE($data)) {
                   4451:                             $valchk = 'valid';
                   4452:                         }
                   4453:                     } elsif ($typeof eq 'string_yesno') {
                   4454:                         if ($thiskey =~ /\.retrypartial$/) {
                   4455:                             $name = 'retrypartial';
                   4456:                         }
1.549     raeburn  4457:                     }
1.563     damieng  4458:                 } elsif ($cmd eq 'datepointer') {
                   4459:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4460:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4461:                     $text = &mt('Saved modified date for');
                   4462:                     if ($typeof eq 'date_start') {
                   4463:                         if ($thiskey =~ /\.printstartdate$/) {
                   4464:                             $name = 'printstartdate';
                   4465:                             if (($data) && ($data > $now)) {
                   4466:                                 $valchk = 'future';
                   4467:                             }
1.560     damieng  4468:                         }
1.563     damieng  4469:                     } elsif ($typeof eq 'date_end') {
                   4470:                         if ($thiskey =~ /\.printenddate$/) {
                   4471:                             $name = 'printenddate';
                   4472:                             if (($data) && ($data < $now)) {
                   4473:                                 $valchk = 'past';
                   4474:                             }
1.560     damieng  4475:                         }
1.504     raeburn  4476:                     }
1.563     damieng  4477:                 } elsif ($cmd eq 'dateinterval') {
                   4478:                     $data=&get_date_interval_from_form($thiskey);
                   4479:                     if ($thiskey =~ /\.interval$/) {
                   4480:                         $name = 'interval';
                   4481:                         my $intervaltype = &get_intervaltype($name);
                   4482:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4483:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4484:                             foreach my $item (@{$intervalmatch}) {
                   4485:                                 if (ref($item) eq 'ARRAY') {
                   4486:                                     my ($regexpname,$pattern) = @{$item};
                   4487:                                     if ($pattern ne '') {
                   4488:                                         if ($data =~ /$pattern/) {
                   4489:                                             $valmatch = $regexpname;
                   4490:                                             $valchk = '';
                   4491:                                             last;
                   4492:                                         }
1.560     damieng  4493:                                     }
1.554     raeburn  4494:                                 }
                   4495:                             }
                   4496:                         }
                   4497:                     }
1.563     damieng  4498:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4499:                     $text = &mt('Saved modified date for');
1.554     raeburn  4500:                 }
1.576     raeburn  4501:                 if ($recursive) {
1.563     damieng  4502:                     $namematch = 'maplevelrecurse';
1.560     damieng  4503:                 }
1.563     damieng  4504:                 if (($name ne '') || ($namematch ne '')) {
                   4505:                     my ($needsrelease,$needsnewer);
                   4506:                     if ($name ne '') {
                   4507:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4508:                         if ($needsrelease) {
                   4509:                             unless ($got_chostname) {
1.563     damieng  4510:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4511:                                 $got_chostname = 1;
                   4512:                             }
1.563     damieng  4513:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4514:                                                                 $needsrelease,
                   4515:                                                                 $cmajor,$cminor);
                   4516:                         }
                   4517:                     }
                   4518:                     if ($namematch ne '') {
                   4519:                         if ($needsnewer) {
                   4520:                             undef($namematch);
1.560     damieng  4521:                         } else {
1.563     damieng  4522:                             my $currneeded;
                   4523:                             if ($needsrelease) {
                   4524:                                 $currneeded = $needsrelease;
                   4525:                             }
                   4526:                             $needsrelease =
                   4527:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4528:                             if (($needsrelease) &&
                   4529:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4530:                                 unless ($got_chostname) {
                   4531:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4532:                                     $got_chostname = 1;
                   4533:                                 }
                   4534:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4535:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4536:                             } else {
                   4537:                                 undef($namematch);
                   4538:                             }
1.560     damieng  4539:                         }
1.557     raeburn  4540:                     }
1.563     damieng  4541:                     if ($needsnewer) {
                   4542:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4543:                                                             $chostname,$cmajor,
                   4544:                                                             $cminor,$needsrelease));
                   4545:                         next;
                   4546:                     }
1.504     raeburn  4547:                 }
1.576     raeburn  4548:                 my ($reconlychg,$haschange,$storekey);
                   4549:                 if ($tuname) {
                   4550:                     my $ustorekey;
                   4551:                     if ($altkey) {
                   4552:                         if ($recursive) {
                   4553:                             if (exists($$olddata{$thiskey})) {
                   4554:                                 if ($$olddata{$thiskey} eq $data) {
                   4555:                                     $reconlychg = 1;
                   4556:                                 }
                   4557:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4558:                             }
                   4559:                             if (exists($$olddata{$altkey})) {
                   4560:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4561:                                     $haschange = 1;
                   4562:                                 }
                   4563:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4564:                                 $haschange = 1;
                   4565:                             }
                   4566:                             $ustorekey = $tkeyrec;
                   4567:                         } else {
                   4568:                             if (exists($$olddata{$altkey})) {
                   4569:                                 if ($$olddata{$altkey} eq $data) {
                   4570:                                     $reconlychg = 1;
                   4571:                                 }
                   4572:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4573:                             }
                   4574:                             if (exists($$olddata{$thiskey})) {
                   4575:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4576:                                     $haschange = 1;
                   4577:                                 }
                   4578:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4579:                                 $haschange = 1;
                   4580:                             }
                   4581:                             $ustorekey = $tkeynonrec;
                   4582:                         }
                   4583:                     } else {
                   4584:                         if (exists($$olddata{$tkey})) {
                   4585:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4586:                                 $haschange = 1;
                   4587:                             }
                   4588:                             $ustorekey = $tkey;
                   4589:                         }
                   4590:                     }
                   4591:                     if ($haschange || $reconlychg)  {
                   4592:                         unless ($env{'form.del_'.$thiskey}) {
                   4593:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4594:                                                                      $ustorekey.'.type' => $typeof},
                   4595:                                                                      $tudom,$tuname) eq 'ok') {
                   4596:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4597:                                 $r->print('<br />'.$text.' '.
                   4598:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4599:                             } else {
                   4600:                                 $r->print('<div class="LC_error">'.
                   4601:                                           &mt('Error saving parameters').'</div>');
                   4602:                             }
                   4603:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4604:                         }
                   4605:                     }
                   4606:                 } else {
                   4607:                     if ($altkey) {
                   4608:                         if ($recursive) {
                   4609:                             if (exists($$olddata{$thiskey})) {
                   4610:                                 if ($$olddata{$thiskey} eq $data) {
                   4611:                                     $reconlychg = 1;
                   4612:                                 }
                   4613:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4614:                             }
                   4615:                             if (exists($$olddata{$altkey})) {
                   4616:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4617:                                     $haschange = 1;
                   4618:                                 }
                   4619:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4620:                                 $haschange = 1;
                   4621:                             }
                   4622:                             $storekey = $altkey;
1.563     damieng  4623:                         } else {
1.576     raeburn  4624:                             if (exists($$olddata{$altkey})) {
                   4625:                                 if ($$olddata{$altkey} eq $data) {
                   4626:                                     $reconlychg = 1;
                   4627:                                 }
                   4628:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4629:                             } 
                   4630:                             if (exists($$olddata{$thiskey})) {
                   4631:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4632:                                     $haschange = 1;
                   4633:                                 }
                   4634:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4635:                                 $haschange = 1;
                   4636:                             }
                   4637:                             $storekey = $thiskey;
1.563     damieng  4638:                         }
1.560     damieng  4639:                     } else {
1.576     raeburn  4640:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4641:                             $haschange = 1;
                   4642:                             $storekey = $thiskey;
                   4643:                         }
                   4644:                     }
                   4645:                 }
                   4646:                 if ($reconlychg || $haschange) {
                   4647:                     unless ($env{'form.del_'.$thiskey}) {
                   4648:                         $newdata{$storekey}=$data;
                   4649:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4650:                     }
                   4651:                 }
                   4652:             } elsif ($cmd eq 'del') {
                   4653:                 if ($tuname) {
1.576     raeburn  4654:                     my $error;
                   4655:                     if ($altkey) {  
                   4656:                         if (exists($$olddata{$altkey})) {
                   4657:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4658:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4659:                                 if ($recursive) {
                   4660:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4661:                                 }
                   4662:                             } elsif ($recursive) {
                   4663:                                 $error = 1;
                   4664:                             }
                   4665:                         }
                   4666:                         if (exists($$olddata{$thiskey})) {
                   4667:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4668:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4669:                                 unless ($recursive) {
                   4670:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4671:                                 }
                   4672:                             } elsif (!$recursive) {
                   4673:                                 $error = 1;
                   4674:                             }
                   4675:                         }
1.560     damieng  4676:                     } else {
1.576     raeburn  4677:                         if (exists($$olddata{$thiskey})) {
                   4678:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4679:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4680:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4681:                             } else {
                   4682:                                 $error = 1;
                   4683:                             }
                   4684:                         }
                   4685:                     }
                   4686:                     if ($error) { 
1.560     damieng  4687:                         $r->print('<div class="LC_error">'.
                   4688:                             &mt('Error deleting parameters').'</div>');
                   4689:                     }
                   4690:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4691:                 } else {
1.576     raeburn  4692:                     if ($altkey) {
                   4693:                         if (exists($$olddata{$altkey})) {
                   4694:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4695:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4696:                             }
                   4697:                         }
                   4698:                         if (exists($$olddata{$thiskey})) {
                   4699:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4700:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4701:                             }
                   4702:                         }
                   4703:                     } elsif (exists($$olddata{$thiskey})) {
                   4704:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4705:                     }
1.560     damieng  4706:                 }
1.473     amueller 4707:             }
                   4708:         }
                   4709:     }
1.207     www      4710: # Store all course level
1.144     www      4711:     my $delentries=$#deldata+1;
1.576     raeburn  4712:     my @alldels;
                   4713:     if (@delrec) {
                   4714:         push(@alldels,@delrec);
                   4715:     }
                   4716:     if (@delnonrec) {
                   4717:         push(@alldels,@delnonrec);
                   4718:     }
                   4719:     if (@deldata) {
                   4720:         push(@alldels,@deldata);
                   4721:     }
1.548     raeburn  4722:     my @newdatakeys=keys(%newdata);
1.144     www      4723:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4724:     my ($delresult,$devalidate);
                   4725:     if (@alldels) {
                   4726:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4727:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4728:             &log_parmset(\%loghash,1);
1.576     raeburn  4729:             if ($delentries) {
                   4730:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4731:             }
                   4732:         } elsif ($delentries) {
1.560     damieng  4733:             $r->print('<div class="LC_error">'.
                   4734:                 &mt('Error deleting parameters').'</div>');
                   4735:         }
1.576     raeburn  4736:         $devalidate = 1; 
1.144     www      4737:     }
                   4738:     if ($putentries) {
1.560     damieng  4739:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4740:                     &log_parmset(\%newdata,0);
                   4741:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4742:         } else {
                   4743:             $r->print('<div class="LC_error">'.
                   4744:                 &mt('Error saving parameters').'</div>');
                   4745:         }
1.576     raeburn  4746:         $devalidate = 1; 
                   4747:     }
                   4748:     if ($devalidate) {
1.560     damieng  4749:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4750:     }
1.208     www      4751: }
1.207     www      4752: 
1.563     damieng  4753: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4754: #
                   4755: # @param {string} $key - the key
                   4756: # @returns {Array}
1.208     www      4757: sub extractuser {
                   4758:     my $key=shift;
1.350     albertel 4759:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4760: }
1.206     www      4761: 
1.563     damieng  4762: # Parses a parameter key and returns the components.
                   4763: #
                   4764: # @param {string} $key - 
                   4765: # @param {hash reference} $listdata - 
                   4766: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4767: sub parse_listdata_key {
                   4768:     my ($key,$listdata) = @_;
                   4769:     # split into student/section affected, and
                   4770:     # the realm (folder/resource part and parameter
1.446     bisitz   4771:     my ($student,$realm) =
1.473     amueller 4772:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4773:     # if course wide student would be undefined
                   4774:     if (!defined($student)) {
1.560     damieng  4775:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4776:     }
                   4777:     # strip off the .type if it's not the Question type parameter
                   4778:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4779:         $realm=~s/\.type//;
1.381     albertel 4780:     }
                   4781:     # split into resource+part and parameter name
1.388     albertel 4782:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4783:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4784:     return ($student,$res,$part,$parm);
                   4785: }
                   4786: 
1.563     damieng  4787: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4788: #
                   4789: # @param {Apache2::RequestRec} $r - the Apache request
                   4790: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4791: # @param {hash reference} $listdata - data created in secgroup_lister, course id.[section id].part.name -> 1 or course id.[section id].part.name.type -> parameter type
                   4792: # @param {string} $sortorder - realmstudent|studentrealm
                   4793: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4794: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4795: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4796: # @param {string} $parmlev - full|map
                   4797: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4798: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4799: # @returns{integer} - number of $listdata parameters processed
1.208     www      4800: sub listdata {
1.608     raeburn  4801:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4802:     
1.207     www      4803: # Start list output
1.206     www      4804: 
1.122     www      4805:     my $oldsection='';
                   4806:     my $oldrealm='';
                   4807:     my $oldpart='';
1.123     www      4808:     my $pointer=0;
1.124     www      4809:     $tableopen=0;
1.145     www      4810:     my $foundkeys=0;
1.248     albertel 4811:     my %keyorder=&standardkeyorder();
1.594     raeburn  4812:     my $readonlyall = $readonly;
1.381     albertel 4813: 
1.552     raeburn  4814:     my ($secidx,%grouphash);
                   4815:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4816:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4817:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4818:             %grouphash = &Apache::longroup::coursegroups();
                   4819:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4820:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4821:         }
1.552     raeburn  4822:     }
                   4823: 
1.576     raeburn  4824:     foreach my $key (sort {
1.560     damieng  4825:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4826:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4827:         my ($aid,$bid);
                   4828:         if ($caller eq 'newoverview') {
                   4829:             if (ref($hash_for_realm) eq 'HASH') {
                   4830:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4831:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4832:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4833:                     $aid = $hash_for_realm->{$aurl};
                   4834:                     $bid = $hash_for_realm->{$burl};
                   4835:                 } elsif ($parmlev eq 'full') {
                   4836:                     $aid = $hash_for_realm->{$ares};
                   4837:                     $bid = $hash_for_realm->{$bres};
                   4838:                 }
                   4839:             }
                   4840:         }
1.381     albertel 4841: 
1.560     damieng  4842:         # get the numerical order for the param
                   4843:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4844:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4845: 
1.560     damieng  4846:         my $result=0;
1.381     albertel 4847: 
1.560     damieng  4848:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4849:             if ($ares     ne $bres    ) {
1.608     raeburn  4850:                 if ($caller eq 'newoverview') {
                   4851:                     if (ref($hash_for_realm) eq 'HASH') {
                   4852:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4853:                             $result = ($aid <=> $bid);
                   4854:                         } elsif ($parmlev eq 'full') {
                   4855:                             $result = ($aid <=> $bid);
                   4856:                         } else {
                   4857:                             $result = ($ares cmp $bres);
                   4858:                         }
                   4859:                     } else {
                   4860:                         $result = ($ares cmp $bres);
                   4861:                     }
                   4862:                 } else {
                   4863:                     $result = ($ares cmp $bres);
                   4864:                 }
1.446     bisitz   4865:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4866:                 $result = ($astudent cmp $bstudent);
                   4867:             } elsif ($apart    ne $bpart   ) {
                   4868:                 $result = ($apart    cmp $bpart);
                   4869:             }
                   4870:         } else {
                   4871:             if      ($astudent ne $bstudent) {
                   4872:                 $result = ($astudent cmp $bstudent);
                   4873:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4874:                 if ($caller eq 'newoverview') {
                   4875:                     if (ref($hash_for_realm) eq 'HASH') {
                   4876:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4877:                             $result = ($aid <=> $bid);
                   4878:                         } elsif ($parmlev eq 'full') {
                   4879:                             $result = ($aid <=> $bid);
                   4880:                         } else {
                   4881:                             $result = ($ares cmp $bres);
                   4882:                         }
                   4883:                     } else {
                   4884:                         $result = ($ares cmp $bres);
                   4885:                     }
                   4886:                 } else {
                   4887:                     $result = ($ares cmp $bres);
                   4888:                 }
1.560     damieng  4889:             } elsif ($apart    ne $bpart   ) {
                   4890:                 $result = ($apart    cmp $bpart);
                   4891:             }
1.473     amueller 4892:         }
1.446     bisitz   4893: 
1.560     damieng  4894:         if (!$result) {
1.381     albertel 4895:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4896:                 $result = ($aparm <=> $bparm);
1.381     albertel 4897:             } elsif (defined($aparm)) {
1.560     damieng  4898:                 $result = -1;
1.381     albertel 4899:             } elsif (defined($bparm)) {
1.560     damieng  4900:                 $result = 1;
                   4901:             }
1.473     amueller 4902:         }
1.381     albertel 4903: 
1.560     damieng  4904:         $result;
                   4905:         
1.576     raeburn  4906:     } keys(%{$listdata})) { # foreach my $key
                   4907:         my $thiskey = $key;
1.560     damieng  4908:         if ($$listdata{$thiskey.'.type'}) {
                   4909:             my $thistype=$$listdata{$thiskey.'.type'};
                   4910:             if ($$resourcedata{$thiskey.'.type'}) {
                   4911:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4912:             }
                   4913:             my ($middle,$part,$name)=
1.572     damieng  4914:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4915:             my $section=&mt('All Students');
1.594     raeburn  4916:             $readonly = $readonlyall;
1.599     raeburn  4917:             my $userscope;
1.576     raeburn  4918:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4919:             if ($middle=~/^\[(.*)\]/) {
                   4920:                 my $issection=$1;
                   4921:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4922:                     my ($stuname,$studom) = ($1,$2);
                   4923:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4924:                         if (ref($classlist) eq 'HASH') {
                   4925:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4926:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4927:                             }
                   4928:                         }
                   4929:                     }
                   4930:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4931:                     $userscope = 1;
1.560     damieng  4932:                 } else {
                   4933:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4934:                         if (exists($grouphash{$issection})) {
                   4935:                             $section=&mt('Group').': '.$issection;
                   4936:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4937:                             $section = &mt('Section').': '.$issection;
                   4938:                         } else {
                   4939:                             next; 
1.552     raeburn  4940:                         }
1.560     damieng  4941:                     } else {
                   4942:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4943:                     }
                   4944:                 }
1.560     damieng  4945:                 $middle=~s/^\[(.*)\]//;
                   4946:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4947:                 $readonly = 1;
                   4948:             }
                   4949:             $middle=~s/\.+$//;
                   4950:             $middle=~s/^\.+//;
                   4951:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4952:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4953:             if ($caller eq 'overview') {
                   4954:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4955:                     $mapurl = $1;
                   4956:                     $maplevel = $2;
                   4957:                     $is_map = 1;
                   4958:                 }
                   4959:             } elsif ($caller eq 'newoverview') {
                   4960:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4961:                     $mapurl = $1;
                   4962:                     $maplevel = $2;
                   4963:                     $is_map = 1;
                   4964:                 }
                   4965:             }
                   4966:             if ($is_map) {
1.560     damieng  4967:                 my $leveltitle = &mt('Folder/Map');
1.615     raeburn  4968:                 my $title = &Apache::lonnet::gettitle($mapurl);
1.608     raeburn  4969:                 if (ref($hash_for_realm) eq 'HASH') {
                   4970:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4971:                         $title = &mt('Main Content');
                   4972:                     }
                   4973:                 }
1.576     raeburn  4974:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4975:                     if ($caller eq 'newoverview') {
                   4976:                         my $altkey = $thiskey;
                   4977:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4978:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4979:                             $is_recursive = 1;
                   4980:                             if ($$resourcedata{$altkey.'.type'}) {
                   4981:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4982:                             }
                   4983:                             $showval = $$resourcedata{$altkey};
                   4984:                         }
                   4985:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4986:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4987:                         $is_recursive = 1;
                   4988:                     }
1.560     damieng  4989:                 }
1.608     raeburn  4990:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4991:             } elsif ($middle) {
                   4992:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4993:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4994:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4995:                     ': '.&Apache::lonnet::gettitle($middle).
                   4996:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4997:                     $id.')</span></span>';
                   4998:             }
                   4999:             if ($sortorder eq 'realmstudent') {
                   5000:                 if ($realm ne $oldrealm) {
                   5001:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   5002:                     $oldrealm=$realm;
                   5003:                     $oldsection='';
                   5004:                 }
                   5005:                 if ($section ne $oldsection) {
                   5006:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   5007:                     $oldsection=$section;
                   5008:                     $oldpart='';
                   5009:                 }
1.552     raeburn  5010:             } else {
1.560     damieng  5011:                 if ($section ne $oldsection) {
                   5012:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   5013:                     $oldsection=$section;
                   5014:                     $oldrealm='';
                   5015:                 }
                   5016:                 if ($realm ne $oldrealm) {
                   5017:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   5018:                     $oldrealm=$realm;
                   5019:                     $oldpart='';
1.552     raeburn  5020:                 }
                   5021:             }
1.560     damieng  5022:             if ($part ne $oldpart) {
                   5023:                 $r->print(&tableend().
                   5024:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   5025:                 $oldpart=$part;
1.556     raeburn  5026:             }
1.560     damieng  5027:     #
                   5028:     # Ready to print
                   5029:     #
1.470     raeburn  5030:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  5031:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  5032:                 &Apache::loncommon::start_data_table_row().
                   5033:                 '<td><b>'.&mt($parmitem).
                   5034:                 '</b></td>');
                   5035:             unless ($readonly) {
1.599     raeburn  5036:                 my $disabled;
                   5037:                 if (($name eq 'availablestudent') &&
                   5038:                     (($showval eq '') || ($userscope))) {
                   5039:                     $disabled = ' disabled="disabled"';
                   5040:                 }
1.560     damieng  5041:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  5042:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  5043:             }
                   5044:             $r->print('<td>');
                   5045:             $foundkeys++;
                   5046:             if (&isdateparm($thistype)) {
                   5047:                 my $jskey='key_'.$pointer;
                   5048:                 my $state;
                   5049:                 $pointer++;
                   5050:                 if ($readonly) {
                   5051:                     $state = 'disabled';
                   5052:                 }
                   5053:                 $r->print(
                   5054:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   5055:                                                         $jskey,
1.576     raeburn  5056:                                                         $showval,
1.560     damieng  5057:                                                         '',1,$state));
                   5058:                 unless  ($readonly) {
                   5059:                     $r->print(
                   5060:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  5061:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  5062:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  5063:     &date_sanity_info($showval)
1.560     damieng  5064:                     );
                   5065:                 }
                   5066:             } elsif ($thistype eq 'date_interval') {
                   5067:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  5068:                           $showval,$readonly));
1.560     damieng  5069:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  5070:                 if ($name eq 'availablestudent') {
                   5071:                     $readonly = 1;
                   5072:                 }
1.560     damieng  5073:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  5074:                           $showval,$name,$readonly));
1.560     damieng  5075:             } else {
1.576     raeburn  5076:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5077:             }
1.560     damieng  5078:             unless ($readonly) {
                   5079:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5080:                         $thistype.'" />');
1.552     raeburn  5081:             }
1.576     raeburn  5082:             $r->print('</td>');
                   5083:             if ($is_map) {
                   5084:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5085:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5086:                 } else {
                   5087:                     my ($disabled,$recon,$recoff);
                   5088:                     if ($readonly) {
                   5089:                         $disabled = ' disabled="disabled"';
                   5090:                     }
                   5091:                     if ($is_recursive) {
                   5092:                         $recon = ' checked="checked"';
                   5093:                     } else {
                   5094:                         $recoff = ' checked="checked"';
                   5095:                     }
                   5096:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5097:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5098:                 }
                   5099:             }
                   5100:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5101:         }
1.121     www      5102:     }
1.208     www      5103:     return $foundkeys;
                   5104: }
                   5105: 
1.563     damieng  5106: # Returns a string representing the interval, directly using form data matching the given key.
                   5107: # The returned string may also include information related to proctored exams.
                   5108: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5109: #
                   5110: # @param {string} $key - suffix for form fields related to the interval
                   5111: # @returns {string}
1.385     albertel 5112: sub get_date_interval_from_form {
                   5113:     my ($key) = @_;
                   5114:     my $seconds = 0;
1.611     raeburn  5115:     my $numnotnull = 0;
1.385     albertel 5116:     foreach my $which (['days', 86400],
1.473     amueller 5117:                ['hours', 3600],
                   5118:                ['minutes', 60],
                   5119:                ['seconds',  1]) {
1.560     damieng  5120:         my ($name, $factor) = @{ $which };
                   5121:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611     raeburn  5122:             unless ($env{'form.'.$name.'_'.$key} eq '') {
                   5123:                 $numnotnull ++;
                   5124:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5125:             }
1.560     damieng  5126:         }
1.473     amueller 5127:     }
1.560     damieng  5128:     if (($key =~ /\.interval$/) &&
                   5129:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5130:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5131:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5132:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5133:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5134:                 $seconds .= '_proctor';
                   5135:             }
                   5136:         } else {
                   5137:             $seconds .= $env{'form.done_'.$key}; 
                   5138:         }
                   5139:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5140:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5141:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5142:         }
1.554     raeburn  5143:     }
1.611     raeburn  5144:     return if (!$numnotnull);
1.385     albertel 5145:     return $seconds;
                   5146: }
                   5147: 
                   5148: 
1.563     damieng  5149: # Returns HTML to enter a text value for a parameter.
                   5150: #
                   5151: # @param {string} $thiskey - parameter key
                   5152: # @param {string} $showval - the current value
                   5153: # @param {boolean} $readonly - true if the field should not be made editable
                   5154: # @returns {string}
1.383     albertel 5155: sub default_selector {
1.552     raeburn  5156:     my ($thiskey, $showval, $readonly) = @_;
                   5157:     my $disabled;
                   5158:     if ($readonly) {
                   5159:         $disabled = ' disabled="disabled"';
                   5160:     }
                   5161:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5162: }
                   5163: 
1.563     damieng  5164: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5165: #
                   5166: # @param {string} $thiskey - parameter key
                   5167: # @param {string} $showval - the current value
                   5168: # @param {boolean} $readonly - true if the fields should not be made editable
                   5169: # @returns {string}
1.549     raeburn  5170: sub string_ip_selector {
1.552     raeburn  5171:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5172:     my %access = (
                   5173:                    allow => [],
                   5174:                    deny  => [],
                   5175:                  );
                   5176:     if ($showval ne '') {
                   5177:         my @current;
                   5178:         if ($showval =~ /,/) {
                   5179:             @current = split(/,/,$showval);
                   5180:         } else {
                   5181:             @current = ($showval);
                   5182:         }
                   5183:         foreach my $item (@current) {
                   5184:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5185:                 push(@{$access{'deny'}},$1);
                   5186:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5187:                 push(@{$access{'allow'}},$item);
                   5188:             }
                   5189:         }
                   5190:     }
                   5191:     if (!@{$access{'allow'}}) {
                   5192:         @{$access{'allow'}} = ('');
                   5193:     }
                   5194:     if (!@{$access{'deny'}}) {
                   5195:         @{$access{'deny'}} = ('');
                   5196:     }
1.552     raeburn  5197:     my ($disabled,$addmore);
1.567     raeburn  5198:     if ($readonly) {
1.552     raeburn  5199:         $disabled=' disabled="disabled"';
                   5200:     } else {
                   5201:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5202:     }
1.549     raeburn  5203:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5204: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5205:     foreach my $acctype ('allow','deny') {
                   5206:         $output .= '
                   5207: <td valign="top">
                   5208: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5209:   <div class="LC_string_ipacc_inner">'."\n";
                   5210:         my $num = 0;
                   5211:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5212:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5213:             if ($num > 0) {
                   5214:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5215:             }
                   5216:             $output .= '</div>'."\n";
                   5217:             $num ++;
                   5218:         }
                   5219:         $output .= '
1.552     raeburn  5220:   </div>'.$addmore.'
1.549     raeburn  5221: </div>
                   5222: </td>';
                   5223:    }
                   5224:    $output .= '
                   5225: </tr>
                   5226: </table>'."\n";
                   5227:     return $output;
                   5228: }
                   5229: 
1.588     raeburn  5230: sub string_deeplink_selector {
                   5231:     my ($thiskey, $showval, $readonly) = @_;
1.616     raeburn  5232:     my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
                   5233:         %selectnull,%domlti,%crslti,@possmenus,%components);
                   5234:     @tables = ('upper','lower');
                   5235:     %components = (
                   5236:                     upper => ['state','others','listing','scope'],
                   5237:                     lower => ['protect','menus','target','exit'],
                   5238:                   );   
1.588     raeburn  5239:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5240:                   state   => 'Access status',
                   5241:                   others  => 'Hide other resources',
1.588     raeburn  5242:                   listing => 'In Contents and/or Gradebook',
                   5243:                   scope   => 'Access scope for link',
1.601     raeburn  5244:                   protect => 'Link protection',
1.597     raeburn  5245:                   menus   => 'Menu Items Displayed',
1.613     raeburn  5246:                   target  => 'Embedded?',
1.616     raeburn  5247:                   exit    => 'Exit Tool Button?',
1.588     raeburn  5248:               );
                   5249:     %options = (
1.601     raeburn  5250:                    state   => ['only','off','both'],
                   5251:                    others  => ['hide','unhide'],
1.588     raeburn  5252:                    listing => ['full','absent','grades','details','datestatus'],
                   5253:                    scope   => ['res','map','rec'],
1.601     raeburn  5254:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5255:                    menus   => ['std','colls'],
1.613     raeburn  5256:                    target  => ['_self','_top'],
1.616     raeburn  5257:                    exit    => ['no','yes','url'],
1.588     raeburn  5258:                );
                   5259:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5260:                     only       => 'deep only',
                   5261:                     off        => 'deeplink off',
                   5262:                     both       => 'regular + deep',
                   5263:                     hide       => 'Hidden',
                   5264:                     unhide     => 'Unhidden',
1.588     raeburn  5265:                     full       => 'Listed (linked) in both',
                   5266:                     absent     => 'Not listed',
                   5267:                     grades     => 'Listed in grades only',
                   5268:                     details    => 'Listed (unlinked) in both',
                   5269:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5270:                     res        => 'resource only',
                   5271:                     map        => 'enclosing map/folder',
                   5272:                     rec        => 'recursive map/folder',
1.601     raeburn  5273:                     none       => 'not in use',
                   5274:                     key        => 'key access',
                   5275:                     ltic       => 'LTI access (course)',
                   5276:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5277:                     std        => 'Standard (all menus)',
                   5278:                     colls      => 'Numbered collection',
1.614     raeburn  5279:                     _self      => 'Embedded',
1.613     raeburn  5280:                     _top       => 'Not embedded',
1.616     raeburn  5281:                     no         => 'Not in use',
                   5282:                     yes        => 'In use, no URL redirect',
                   5283:                     url        => 'In use, redirect to URL',  
1.597     raeburn  5284:                   );
                   5285:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5286:                     ltic => 'Select Launcher',
                   5287:                     ltid => 'Select Launcher', 
1.597     raeburn  5288:                     colls => 'Select',
1.588     raeburn  5289:                   );
                   5290:     if ($showval =~ /,/) {
1.597     raeburn  5291:         %values=();
1.588     raeburn  5292:         @current = split(/,/,$showval);
1.601     raeburn  5293:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5294:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5295:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5296:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5297:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5298:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613     raeburn  5299:         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616     raeburn  5300:         ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588     raeburn  5301:     } else {
1.601     raeburn  5302:         $defaults{'state'} = 'off',
                   5303:         $defaults{'others'} = 'unhide',
1.588     raeburn  5304:         $defaults{'listing'} = 'full';
                   5305:         $defaults{'scope'} = 'res';
1.601     raeburn  5306:         $defaults{'protect'} = 'none';
1.597     raeburn  5307:         $defaults{'menus'} = '0';
1.613     raeburn  5308:         $defaults{'target'} = '_top';
1.616     raeburn  5309:         $defaults{'exit'} = 'yes';
1.588     raeburn  5310:     }
                   5311:     my $disabled;
                   5312:     if ($readonly) {
                   5313:         $disabled=' disabled="disabled"';
                   5314:     }
1.601     raeburn  5315:     my %courselti =
                   5316:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5317:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5318:     foreach my $item (keys(%courselti)) {
                   5319:         if (ref($courselti{$item}) eq 'HASH') {
                   5320:             $crslti{$item} = $courselti{$item}{'name'};
                   5321:         }
                   5322:     }
                   5323:     my %lti =
1.588     raeburn  5324:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5325:                                         'linkprot');
1.588     raeburn  5326:     foreach my $item (keys(%lti)) {
1.604     raeburn  5327:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5328:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5329:         }
                   5330:     }
1.597     raeburn  5331:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5332:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5333:             my ($num,$value) = split(/\%/,$item);
                   5334:             if ($num =~ /^\d+$/) {
                   5335:                 push(@possmenus,$num);
                   5336:             }
                   5337:         }
                   5338:     }
                   5339: 
1.616     raeburn  5340:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
                   5341:     foreach my $table ('upper','lower') {
                   5342:         next unless (ref($components{$table}) eq 'ARRAY');
                   5343:         $output .= '<table width="100%"><tr>';
                   5344:         foreach my $item (@{$components{$table}}) {
                   5345:             $output .= '<th>'.$titles{$item}.'</th>';
                   5346:         }
                   5347:         $output .= '</tr><tr>';
                   5348:         foreach my $item (@{$components{$table}}) {
                   5349:             $output .= '<td>';
                   5350:             if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
                   5351:                 my $selected = $values{$item};
                   5352:                 foreach my $option (@{$options{$item}}) {
                   5353:                     if ($item eq 'protect') { 
                   5354:                         if ($option eq 'ltid') {
                   5355:                             next unless (keys(%domlti));
                   5356:                         } elsif ($option eq 'ltic') {
                   5357:                             next unless (keys(%crslti));
                   5358:                         }
                   5359:                     } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5360:                         next unless (@possmenus);
                   5361:                     }
                   5362:                     my $checked;
                   5363:                     if ($item eq 'menus') {
                   5364:                         if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5365:                             (grep(/^\Q$selected\E$/,@possmenus))) {
                   5366:                             if ($option eq 'colls') {
                   5367:                                 $checked = ' checked="checked"';
                   5368:                             }
                   5369:                         } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597     raeburn  5370:                             $checked = ' checked="checked"';
                   5371:                         }
1.616     raeburn  5372:                     } elsif ($selected =~ /^\Q$option\E/) {
1.597     raeburn  5373:                         $checked = ' checked="checked"';
                   5374:                     }
1.616     raeburn  5375:                     my $onclick;
                   5376:                     unless ($readonly) {
                   5377:                         my $esc_key = &js_escape($thiskey);
                   5378:                         $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5379:                     }
                   5380:                     $output .= '<span class="LC_nobreak"><label>'.
                   5381:                                '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5382:                                $optiontext{$option}.'</label>';
                   5383:                     if (($item eq 'protect') && ($option eq 'key')) {
                   5384:                         my $visibility="hidden";
                   5385:                         my $currkey;
                   5386:                         if ($checked) {
                   5387:                             $visibility = "text";
                   5388:                             $currkey = (split(/\:/,$values{$item}))[1];
                   5389:                         }
                   5390:                         $output .= '&nbsp;'.
                   5391:                                    '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
                   5392:                     } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
                   5393:                         my $display="none";
                   5394:                         my ($current,$blankcheck,@possibles);
                   5395:                         if ($checked) {
                   5396:                             $display = 'inline-block';
                   5397:                             if (($option eq 'ltic') || ($option eq 'ltid'))  {
                   5398:                                 $current = (split(/\:/,$selected))[1];
                   5399:                             } else {
                   5400:                                 $current = $selected;
                   5401:                             }
1.597     raeburn  5402:                         } else {
1.616     raeburn  5403:                             $blankcheck = ' selected="selected"';
1.597     raeburn  5404:                         }
1.601     raeburn  5405:                         if ($option eq 'ltid') {
1.616     raeburn  5406:                             @possibles = keys(%domlti);
1.601     raeburn  5407:                         } elsif ($option eq 'ltic') {
1.616     raeburn  5408:                             @possibles = keys(%crslti); 
                   5409:                         } else {
                   5410:                             @possibles = @possmenus;
                   5411:                         }
                   5412:                         $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5413:                                    ' style="display: '.$display.'">&nbsp;<select name="'.
                   5414:                                    'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5415:                         if (@possibles > 1) {
                   5416:                             $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5417:                                        '</option>'."\n";
                   5418:                         }
                   5419:                         foreach my $poss (sort { $a <=> $b } @possibles) {
                   5420:                             my $selected;
                   5421:                             if (($poss == $current) || (scalar(@possibles) ==1)) {
                   5422:                                 $selected = ' selected="selected"';
                   5423:                             }
                   5424:                             my $shown = $poss;
                   5425:                             if ($option eq 'ltid') {
                   5426:                                 $shown = $domlti{$poss};
                   5427:                             } elsif ($option eq 'ltic') {
                   5428:                                 $shown = $crslti{$poss};
                   5429:                             }
                   5430:                             $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
                   5431:                         }
                   5432:                         $output .= '</select></div>';
                   5433:                     }
                   5434:                     $output .= '</span> ';
                   5435:                 }
                   5436:                 if ($item eq 'exit') {
                   5437:                     my $exitsty = 'none';
                   5438:                     my $displayval;
                   5439:                     if ($values{$item} =~ /^(yes|url)/) { 
                   5440:                         $exitsty = 'inline-block';
                   5441:                         my $currval = (split(/\:/,$values{$item}))[1];
                   5442:                         if ($currval eq '') {
                   5443:                             $displayval = 'Exit Tool';
                   5444:                         } else {
                   5445:                             $displayval = $currval;
1.597     raeburn  5446:                         }
1.588     raeburn  5447:                     }
1.616     raeburn  5448:                     $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
                   5449:                                ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
                   5450:                                '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
                   5451:                                ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
                   5452:                                ' size="10"'.$disabled.' /></div>';
1.588     raeburn  5453:                 }
1.616     raeburn  5454:             } else {
                   5455:                 my $selected = $values{$item};
                   5456:                 my $defsel;
                   5457:                 if ($selected eq '') {
                   5458:                     $defsel = ' selected="selected"';
                   5459:                 }
                   5460:                 $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5461:                            '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5462:                 foreach my $option (@{$options{$item}}) {
                   5463:                     $output .= '<option value="'.$option.'"';
                   5464:                     if ($option eq $selected) {
                   5465:                         $output .= ' selected="selected"';
                   5466:                     }
                   5467:                     $output .= '>'.$optiontext{$option}.'</option>';
1.588     raeburn  5468:                 }
1.616     raeburn  5469:                 $output .= '</select>';
1.588     raeburn  5470:             }
1.616     raeburn  5471:             $output .= '</td>';
                   5472:         }
                   5473:         $output .= '</tr></table>'."\n";
                   5474:         if ($table eq 'upper') {
                   5475:             $output .= '<br />';
1.588     raeburn  5476:         }
                   5477:     }
                   5478:     return $output;
                   5479: }
                   5480: 
1.560     damieng  5481: 
                   5482: { # block using some constants related to parameter types (overview mode)
                   5483: 
1.446     bisitz   5484: my %strings =
1.383     albertel 5485:     (
                   5486:      'string_yesno'
                   5487:              => [[ 'yes', 'Yes' ],
1.560     damieng  5488:                  [ 'no', 'No' ]],
1.383     albertel 5489:      'string_problemstatus'
                   5490:              => [[ 'yes', 'Yes' ],
1.473     amueller 5491:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5492:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5493:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5494:      'string_questiontype'
                   5495:              => [[ 'problem', 'Standard Problem'],
                   5496:                  [ 'survey', 'Survey'],
                   5497:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5498:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5499:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5500:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5501:                  [ 'practice', 'Practice'],
                   5502:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5503:      'string_lenient'
                   5504:              => [['yes', 'Yes' ],
                   5505:                  [ 'no', 'No' ],
1.549     raeburn  5506:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5507:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5508:      'string_discussvote'
                   5509:              => [['yes','Yes'],
                   5510:                  ['notended','Yes, unless discussion ended'],
                   5511:                  ['no','No']],
1.549     raeburn  5512:      'string_ip'
                   5513:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5514:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5515:      'string_deeplink'
1.616     raeburn  5516:              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.587     raeburn  5517:     );
                   5518:    
1.383     albertel 5519: 
1.549     raeburn  5520: my %stringmatches = (
                   5521:          'string_lenient'
                   5522:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5523:          'string_ip'
                   5524:               => [['_allowfrom_','[^\!]+'],
                   5525:                   ['_denyfrom_','\!']],
1.588     raeburn  5526:          'string_deeplink'
1.616     raeburn  5527:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.549     raeburn  5528:     );
                   5529: 
                   5530: my %stringtypes = (
                   5531:                     type         => 'string_questiontype',
                   5532:                     lenient      => 'string_lenient',
                   5533:                     retrypartial => 'string_yesno',
                   5534:                     discussvote  => 'string_discussvote',
                   5535:                     examcode     => 'string_examcode',
                   5536:                     acc          => 'string_ip',
1.587     raeburn  5537:                     deeplink     => 'string_deeplink',
1.549     raeburn  5538:                   );
                   5539: 
1.563     damieng  5540: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5541: # Used by courseprefs.
                   5542: #
                   5543: # @param {string} $string_type - a parameter type for strings
                   5544: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5545: sub standard_string_options {
                   5546:     my ($string_type) = @_;
                   5547:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5548:         return $strings{$string_type};
                   5549:     }
                   5550:     return;
                   5551: }
1.383     albertel 5552: 
1.563     damieng  5553: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5554: #
                   5555: # @param {string} $string_type - a parameter type for strings
                   5556: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5557: sub standard_string_matches {
                   5558:     my ($string_type) = @_;
                   5559:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5560:         return $stringmatches{$string_type};
                   5561:     }
                   5562:     return;
                   5563: }
                   5564: 
1.563     damieng  5565: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5566: #
                   5567: # @param {string} $name - parameter name
                   5568: # @returns {string}
1.549     raeburn  5569: sub get_stringtype {
                   5570:     my ($name) = @_;
                   5571:     if (exists($stringtypes{$name})) {
                   5572:         return $stringtypes{$name};
                   5573:     }
                   5574:     return;
                   5575: }
                   5576: 
1.563     damieng  5577: # Returns HTML to edit a string parameter.
                   5578: #
                   5579: # @param {string} $thistype - parameter type
                   5580: # @param {string} $thiskey - parameter key
                   5581: # @param {string} $showval - parameter current value
                   5582: # @param {string} $name - parameter name
                   5583: # @param {boolean} $readonly - true if the values should not be made editable
                   5584: # @returns {string}
1.383     albertel 5585: sub string_selector {
1.552     raeburn  5586:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5587: 
1.383     albertel 5588:     if (!exists($strings{$thistype})) {
1.552     raeburn  5589:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5590:     }
                   5591: 
1.504     raeburn  5592:     my %skiptype;
1.514     raeburn  5593:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5594:             ($thistype eq 'string_lenient') ||
                   5595:             ($thistype eq 'string_discussvote') ||
                   5596:             ($thistype eq 'string_ip') ||
1.588     raeburn  5597:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5598:             ($name eq 'retrypartial')) {
1.504     raeburn  5599:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5600:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5601:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5602:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5603:             my $parmmatch;
                   5604:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5605:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5606:                     if (ref($item) eq 'ARRAY') {
                   5607:                         if ($parmval eq $item->[0]) {
                   5608:                             $parmmatch = $parmval;
                   5609:                             $parmval = '';
                   5610:                             last;
                   5611:                         }
                   5612:                     }
                   5613:                 }
                   5614:             }
                   5615:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5616:             if ($needsrelease) {
                   5617:                 unless ($got_chostname) {
1.514     raeburn  5618:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5619:                     $got_chostname = 1;
                   5620:                 }
1.557     raeburn  5621:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5622:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5623:                 if ($needsnewer) {
1.549     raeburn  5624:                     if ($parmmatch ne '') {
                   5625:                         $skiptype{$parmmatch} = 1;
                   5626:                     } elsif ($parmval ne '') {
                   5627:                         $skiptype{$parmval} = 1;
                   5628:                     }
1.504     raeburn  5629:                 }
                   5630:             }
                   5631:         }
                   5632:     }
1.549     raeburn  5633: 
                   5634:     if ($thistype eq 'string_ip') {
1.552     raeburn  5635:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5636:     } elsif ($thistype eq 'string_deeplink') {
                   5637:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5638:     }
1.504     raeburn  5639: 
1.552     raeburn  5640:     my ($result,$disabled);
                   5641: 
                   5642:     if ($readonly) {
                   5643:         $disabled = ' disabled="disabled"';
                   5644:     }
1.504     raeburn  5645:     my $numinrow = 3;
                   5646:     if ($thistype eq 'string_problemstatus') {
                   5647:         $numinrow = 2;
                   5648:     } elsif ($thistype eq 'string_questiontype') {
                   5649:         if (keys(%skiptype) > 0) {
                   5650:              $numinrow = 4;
                   5651:         }
                   5652:     }
                   5653:     my $rem;
                   5654:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5655:         my $i=0;
                   5656:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5657:             next unless (ref($possibilities) eq 'ARRAY');
                   5658:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5659:             next if ($skiptype{$name});
1.504     raeburn  5660:             $rem = $i%($numinrow);
                   5661:             if ($rem == 0) {
                   5662:                 if ($i > 0) {
                   5663:                     $result .= '</tr>';
                   5664:                 }
                   5665:                 $result .= '<tr>';
                   5666:             }
1.549     raeburn  5667:             my $colspan;
                   5668:             if ($i == @{ $strings{$thistype} }-1) {
                   5669:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5670:                 if ($rem) {
                   5671:                     my $colsleft = $numinrow - $rem;
                   5672:                     if ($colsleft) {
                   5673:                         $colspan = $colsleft+1;
                   5674:                         $colspan = ' colspan="'.$colspan.'"';
                   5675:                     }
                   5676:                 }
                   5677:             }
                   5678:             my ($add,$onchange,$css_class);
                   5679:             if ($thistype eq 'string_lenient') {
                   5680:                 if ($name eq 'weighted') {
                   5681:                     my $display;
                   5682:                     my %relatives = &Apache::lonlocal::texthash(
                   5683:                                         corrchkd     => 'Correct (checked)',
                   5684:                                         corrunchkd   => 'Correct (unchecked)',
                   5685:                                         incorrchkd   => 'Incorrect (checked)',
                   5686:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5687:                     );
                   5688:                     my %textval = (
                   5689:                                     corrchkd     => '1.0',
                   5690:                                     corrunchkd   => '1.0',
                   5691:                                     incorrchkd   => '0.0',
                   5692:                                     incorrunchkd => '0.0',
                   5693:                     );
                   5694:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5695:                         $textval{'corrchkd'} = $1;
                   5696:                         $textval{'corrunchkd'} = $2;
                   5697:                         $textval{'incorrchkd'} = $3;
                   5698:                         $textval{'incorrunchkd'} = $4;
                   5699:                         $display = 'inline';
                   5700:                         $showval = $name;
                   5701:                     } else {
                   5702:                         $display = 'none';
                   5703:                     }
                   5704:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5705:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5706:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5707:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5708:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5709:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5710:                                 '</td></tr>';
                   5711:                     }
                   5712:                     $add .= '</table></div>'."\n";
                   5713:                 }
                   5714:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5715:                 $css_class = ' class="LC_lenient_radio"';
                   5716:             }
                   5717:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5718:                        '<span class="LC_nobreak"><label>'.
                   5719:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5720:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5721:             if ($showval eq $name) {
                   5722:                 $result .= ' checked="checked"';
                   5723:             }
1.549     raeburn  5724:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5725:             $i++;
                   5726:         }
                   5727:         $result .= '</tr>';
1.473     amueller 5728:     }
1.504     raeburn  5729:     if ($result) {
                   5730:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5731:     }
                   5732:     return $result;
                   5733: }
                   5734: 
1.554     raeburn  5735: my %intervals =
                   5736:     (
                   5737:      'date_interval'
                   5738:              => [[ 'done', 'Yes' ],
1.558     raeburn  5739:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5740:                  [ '', 'No' ]],
                   5741:     );
                   5742: 
                   5743: my %intervalmatches = (
                   5744:          'date_interval'
1.559     raeburn  5745:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5746:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5747:     );
                   5748: 
                   5749: my %intervaltypes = (
                   5750:                       interval => 'date_interval',
                   5751:     );
                   5752: 
1.563     damieng  5753: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5754: #
                   5755: # @param {string} $interval_type - a parameter type for intervals
                   5756: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5757: sub standard_interval_matches {
                   5758:     my ($interval_type) = @_;
                   5759:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5760:         return $intervalmatches{$interval_type};
                   5761:     }
                   5762:     return;
                   5763: }
                   5764: 
1.563     damieng  5765: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5766: #
                   5767: # @param {string} $name - parameter name
                   5768: # @returns {string}
1.554     raeburn  5769: sub get_intervaltype {
                   5770:     my ($name) = @_;
                   5771:     if (exists($intervaltypes{$name})) {
                   5772:         return $intervaltypes{$name};
                   5773:     }
                   5774:     return;
                   5775: }
                   5776: 
1.563     damieng  5777: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5778: # Used by courseprefs.
                   5779: #
                   5780: # @param {string} $interval_type - a parameter type for intervals
                   5781: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5782: sub standard_interval_options {
                   5783:     my ($interval_type) = @_;
                   5784:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5785:         return $intervals{$interval_type};
                   5786:     }
                   5787:     return;
                   5788: }
                   5789: 
1.563     damieng  5790: # Returns HTML to edit a date interval parameter.
                   5791: #
                   5792: # @param {string} $thiskey - parameter key
                   5793: # @param {string} $name - parameter name
                   5794: # @param {string} $showval - parameter current value
                   5795: # @param {boolean} $readonly - true if the values should not be made editable
                   5796: # @returns {string}
1.554     raeburn  5797: sub date_interval_selector {
                   5798:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5799:     my ($result,%skipval);
                   5800:     if ($name eq 'interval') {
                   5801:         my $intervaltype = &get_intervaltype($name);
                   5802:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5803:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5804:             next unless (ref($possibilities) eq 'ARRAY');
                   5805:             my ($parmval, $description) = @{ $possibilities };
                   5806:             my $parmmatch;
                   5807:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5808:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5809:                     if (ref($item) eq 'ARRAY') {
                   5810:                         if ($parmval eq $item->[0]) {
                   5811:                             $parmmatch = $parmval;
                   5812:                             $parmval = '';
                   5813:                             last;
                   5814:                         }
                   5815:                     }
                   5816:                 }
                   5817:             }
                   5818:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5819:             if ($needsrelease) {
                   5820:                 unless ($got_chostname) {
                   5821:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5822:                     $got_chostname = 1;
                   5823:                 }
1.557     raeburn  5824:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5825:                                                        $needsrelease,$cmajor,$cminor);
                   5826:                 if ($needsnewer) {
                   5827:                     if ($parmmatch ne '') {
                   5828:                         $skipval{$parmmatch} = 1;
                   5829:                     } elsif ($parmval ne '') {
                   5830:                         $skipval{$parmval} = 1;
                   5831:                     }
                   5832:                 }
                   5833:             }
                   5834:         }
                   5835:     }
                   5836: 
                   5837:     my $currval = $showval;
                   5838:     foreach my $which (['days', 86400, 31],
                   5839:                ['hours', 3600, 23],
                   5840:                ['minutes', 60, 59],
                   5841:                ['seconds',  1, 59]) {
1.560     damieng  5842:         my ($name, $factor, $max) = @{ $which };
                   5843:         my $amount = int($showval/$factor);
                   5844:         $showval  %= $factor;
                   5845:         my %select = ((map {$_ => $_} (0..$max)),
                   5846:                 'select_form_order' => [0..$max]);
1.611     raeburn  5847:         if ($currval eq '') {
                   5848:             unshift(@{$select{'select_form_order'}},'');
                   5849:             $select{''} = '';
                   5850:             $amount = '';
                   5851:         }
1.560     damieng  5852:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5853:                             \%select,'',$readonly);
                   5854:         $result .= ' '.&mt($name);
1.554     raeburn  5855:     }
                   5856:     if ($name eq 'interval') {
                   5857:         unless ($skipval{'done'}) {
                   5858:             my $checkedon = '';
1.611     raeburn  5859:             my $checkedoff = '';
1.558     raeburn  5860:             my $checkedproc = '';
                   5861:             my $currproctorkey = '';
                   5862:             my $currprocdisplay = 'hidden';
1.559     raeburn  5863:             my $currdonetext = &mt('Done');
                   5864:             if ($currval =~ /^(?:\d+)_done$/) {
                   5865:                 $checkedon = ' checked="checked"';
                   5866:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5867:                 $currdonetext = $1;
1.554     raeburn  5868:                 $checkedon = ' checked="checked"';
1.558     raeburn  5869:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5870:                 $currproctorkey = $1;
                   5871:                 $checkedproc = ' checked="checked"';
                   5872:                 $currprocdisplay = 'text';
1.559     raeburn  5873:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5874:                 $currdonetext = $1;
                   5875:                 $currproctorkey = $2;
                   5876:                 $checkedproc = ' checked="checked"';
                   5877:                 $currprocdisplay = 'text';
1.611     raeburn  5878:             } elsif ($currval ne '') {
                   5879:                 $checkedoff = ' checked="checked"';
                   5880:             } else {
                   5881:                 $currdonetext = '';
1.554     raeburn  5882:             }
1.558     raeburn  5883:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5884:             my $disabled;
                   5885:             if ($readonly) {
                   5886:                 $disabled = ' disabled="disabled"';
                   5887:             }
1.558     raeburn  5888:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5889:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5890:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5891:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5892:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5893:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5894:                        &mt('Yes, with proctor key').'</label>'.
                   5895:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5896:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5897:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611     raeburn  5898:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                   5899:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5900:         }
                   5901:     }
                   5902:     unless ($readonly) {
                   5903:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5904:     }
                   5905:     return $result;
                   5906: }
                   5907: 
1.563     damieng  5908: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5909: #
                   5910: # @param {string} $name - parameter name
                   5911: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5912: # @param {string} $value - parameter value
                   5913: # @param {string} $chostname - course server name
                   5914: # @param {integer} $cmajor - major version number
                   5915: # @param {integer} $cminor - minor version number
                   5916: # @param {string} $needsrelease - release version needed (major.minor)
                   5917: # @returns {string}
1.549     raeburn  5918: sub oldversion_warning {
1.557     raeburn  5919:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5920:     my $standard_name = &standard_parameter_names($name);
                   5921:     if ($namematch) {
                   5922:         my $level = &standard_parameter_levels($namematch);
                   5923:         my $msg = '';
                   5924:         if ($level) {
                   5925:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5926:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5927:         } else {
                   5928:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5929:                       $standard_name,'<b>','</b>');
                   5930:         }
                   5931:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5932:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5933:                    $cmajor.'.'.$cminor,$chostname,
                   5934:                    $needsrelease).
                   5935:                    '</p>';
                   5936:     }
1.549     raeburn  5937:     my $desc;
                   5938:     my $stringtype = &get_stringtype($name);
                   5939:     if ($stringtype ne '') {
                   5940:         if ($name eq 'examcode') {
                   5941:             $desc = $value;
                   5942:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5943:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5944:                 next unless (ref($possibilities) eq 'ARRAY');
                   5945:                 my ($parmval, $description) = @{ $possibilities };
                   5946:                 my $parmmatch;
                   5947:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5948:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5949:                         if (ref($item) eq 'ARRAY') {
                   5950:                             my ($regexpname,$pattern) = @{$item};
                   5951:                             if ($parmval eq $regexpname) {
                   5952:                                 if ($value =~ /$pattern/) {
                   5953:                                     $desc = $description; 
                   5954:                                     $parmmatch = 1;
                   5955:                                     last;
                   5956:                                 }
                   5957:                             }
                   5958:                         }
                   5959:                     }
                   5960:                     last if ($parmmatch);
                   5961:                 } elsif ($parmval eq $value) {
                   5962:                     $desc = $description;
                   5963:                     last;
                   5964:                 }
                   5965:             }
                   5966:         }
                   5967:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5968:         my $now = time;
                   5969:         if ($value =~ /^\d+$/) {
                   5970:             if ($name eq 'printstartdate') {
                   5971:                 if ($value > $now) {
                   5972:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5973:                 }
                   5974:             } elsif ($name eq 'printenddate') {
                   5975:                 if ($value < $now) {
                   5976:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5977:                 }
                   5978:             }
                   5979:         }
                   5980:     }
                   5981:     return '<p class="LC_warning">'.
1.557     raeburn  5982:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5983:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5984:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5985:        $cmajor.'.'.$cminor,$chostname,
                   5986:        $needsrelease).
                   5987:        '</p>';
1.549     raeburn  5988: }
                   5989: 
1.560     damieng  5990: } # end of block using some constants related to parameter types
                   5991: 
1.549     raeburn  5992: 
1.563     damieng  5993: 
                   5994: # Shifts all start and end dates in the current course by $shift.
1.389     www      5995: #
1.563     damieng  5996: # @param {integer} $shift - time to shift, in seconds
                   5997: # @returns {string} - error name or 'ok'
1.389     www      5998: sub dateshift {
1.594     raeburn  5999:     my ($shift,$numchanges)=@_;
1.389     www      6000:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6001:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6002:     my $sec = $env{'request.course.sec'};
1.595     raeburn  6003:     my $secgrpregex;
                   6004:     if ($sec ne '') {
                   6005:         my @groups;
                   6006:         if ($env{'request.course.groups'} ne '') {
                   6007:             @groups = split(/:/,$env{'request.course.groups'});
                   6008:         }
                   6009:         if (@groups) {
                   6010:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   6011:         } else {
                   6012:             $secgrpregex = $sec;
                   6013:         }
                   6014:     }
1.389     www      6015:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   6016: # ugly retro fix for broken version of types
1.548     raeburn  6017:     foreach my $key (keys(%data)) {
1.389     www      6018:         if ($key=~/\wtype$/) {
                   6019:             my $newkey=$key;
                   6020:             $newkey=~s/type$/\.type/;
                   6021:             $data{$newkey}=$data{$key};
                   6022:             delete $data{$key};
                   6023:         }
                   6024:     }
1.391     www      6025:     my %storecontent=();
1.389     www      6026: # go through all parameters and look for dates
1.548     raeburn  6027:     foreach my $key (keys(%data)) {
1.389     www      6028:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  6029:           if ($sec ne '') {
1.595     raeburn  6030:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  6031:           }
1.389     www      6032:           my $newdate=$data{$key}+$shift;
1.594     raeburn  6033:           $$numchanges ++;
1.391     www      6034:           $storecontent{$key}=$newdate;
1.389     www      6035:        }
                   6036:     }
1.391     www      6037:     my $reply=&Apache::lonnet::cput
                   6038:                 ('resourcedata',\%storecontent,$dom,$crs);
                   6039:     if ($reply eq 'ok') {
                   6040:        &log_parmset(\%storecontent);
                   6041:     }
                   6042:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   6043:     return $reply;
1.389     www      6044: }
                   6045: 
1.563     damieng  6046: # Overview mode UI to edit course parameters.
                   6047: #
                   6048: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6049: sub newoverview {
1.568     raeburn  6050:     my ($r,$parm_permission) = @_;
1.280     albertel 6051: 
1.208     www      6052:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6053:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6054:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6055:     my $readonly = 1;
                   6056:     if ($parm_permission->{'edit'}) {
                   6057:         undef($readonly);
                   6058:     }
1.414     droeschl 6059:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6060:         text=>"Overview Mode"});
1.523     raeburn  6061: 
                   6062:     my %loaditems = (
1.549     raeburn  6063:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  6064:                     );
                   6065:     my $js = '
                   6066: <script type="text/javascript">
                   6067: // <![CDATA[
                   6068: '.
                   6069:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   6070:             &showhide_js()."\n".
1.549     raeburn  6071:             &toggleparmtextbox_js()."\n".
                   6072:             &validateparms_js()."\n".
                   6073:             &ipacc_boxes_js()."\n".
1.558     raeburn  6074:             &done_proctor_js()."\n".
1.588     raeburn  6075:             &deeplink_js()."\n".
1.523     raeburn  6076: '// ]]>
                   6077: </script>
                   6078: ';
1.549     raeburn  6079: 
1.523     raeburn  6080:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   6081:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 6082:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6083:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6084:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      6085:     $r->print(<<ENDOVER);
1.549     raeburn  6086: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      6087: ENDOVER
1.211     www      6088:     my @ids=();
                   6089:     my %typep=();
                   6090:     my %keyp=();
                   6091:     my %allparms=();
                   6092:     my %allparts=();
                   6093:     my %allmaps=();
                   6094:     my %mapp=();
                   6095:     my %symbp=();
                   6096:     my %maptitles=();
                   6097:     my %uris=();
                   6098:     my %keyorder=&standardkeyorder();
                   6099:     my %defkeytype=();
                   6100: 
                   6101:     my %alllevs=();
                   6102:     $alllevs{'Resource Level'}='full';
1.215     www      6103:     $alllevs{'Map/Folder Level'}='map';
1.211     www      6104:     $alllevs{'Course Level'}='general';
                   6105: 
                   6106:     my $csec=$env{'form.csec'};
1.269     raeburn  6107:     my $cgroup=$env{'form.cgroup'};
1.211     www      6108: 
                   6109:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   6110:     my $pschp=$env{'form.pschp'};
1.506     www      6111: 
1.211     www      6112:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      6113:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      6114: 
1.446     bisitz   6115:     my @selected_sections =
1.473     amueller 6116:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6117:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6118:     foreach my $sec (@selected_sections) {
                   6119:         if ($sec eq 'all') {
1.211     www      6120:             @selected_sections = ('all');
                   6121:         }
                   6122:     }
1.552     raeburn  6123:     if ($env{'request.course.sec'} ne '') {
                   6124:         @selected_sections = ($env{'request.course.sec'});
                   6125:     }
1.269     raeburn  6126:     my @selected_groups =
                   6127:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6128: 
                   6129:     my $pssymb='';
                   6130:     my $parmlev='';
1.446     bisitz   6131: 
1.211     www      6132:     unless ($env{'form.parmlev'}) {
                   6133:         $parmlev = 'map';
                   6134:     } else {
                   6135:         $parmlev = $env{'form.parmlev'};
                   6136:     }
                   6137: 
1.446     bisitz   6138:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6139:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6140:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6141: 
1.374     albertel 6142:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6143:         @psprt = keys(%allparts);
1.374     albertel 6144:     }
1.211     www      6145: # Menu to select levels, etc
                   6146: 
1.456     bisitz   6147:     $r->print('<div class="LC_Box">');
1.445     neumanie 6148:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6149:     $r->print('<div>');
1.523     raeburn  6150:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6151:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6152:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6153:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6154:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6155:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6156:     $r->print('</div></div>');
1.446     bisitz   6157: 
1.456     bisitz   6158:     $r->print('<div class="LC_Box">');
1.452     bisitz   6159:     $r->print('<div>');
1.581     raeburn  6160:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6161:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6162:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6163:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6164:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6165:     $r->print('<table>'.
1.553     raeburn  6166:               '<tr><th>'.&mt('Parts').'</th>');
                   6167:     if ($sectionselector) {
                   6168:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6169:     }
                   6170:     if ($groupselector) {
                   6171:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6172:     }
                   6173:     $r->print('</tr><tr><td>');
1.211     www      6174:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6175:     $r->print('</td>');
                   6176:     if ($sectionselector) { 
                   6177:         $r->print('<td>'.$sectionselector.'</td>');
                   6178:     }
                   6179:     if ($groupselector) {
                   6180:         $r->print('<td>'.$groupselector.'</td>');
                   6181:     }
                   6182:     $r->print('</tr></table>');
1.447     bisitz   6183:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6184:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6185:     $r->print('</div></div>');
                   6186: 
1.456     bisitz   6187:     $r->print('<div class="LC_Box">');
1.452     bisitz   6188:     $r->print('<div>');
1.214     www      6189:     my $sortorder=$env{'form.sortorder'};
                   6190:     unless ($sortorder) { $sortorder='realmstudent'; }
1.612     raeburn  6191:     &sortmenu($r,$sortorder,'newoverview');
1.445     neumanie 6192:     $r->print('</div></div>');
1.446     bisitz   6193: 
1.214     www      6194:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6195: 
1.211     www      6196: # Build the list data hash from the specified parms
                   6197: 
                   6198:     my $listdata;
                   6199:     %{$listdata}=();
                   6200: 
                   6201:     foreach my $cat (@pscat) {
1.269     raeburn  6202:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6203:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6204:     }
                   6205: 
1.212     www      6206:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6207: 
1.481     amueller 6208:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6209: 
                   6210: # Read modified data
                   6211: 
1.481     amueller 6212:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6213: 
                   6214: # List data
                   6215: 
1.608     raeburn  6216:         my $hash_for_realm;
                   6217:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6218:             %{$hash_for_realm} = reverse(%allmaps);
                   6219:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6220:             for (my $i=0; $i<@ids; $i++) {
                   6221:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6222:             }
                   6223:         }
                   6224:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6225:     }
                   6226:     $r->print(&tableend());
                   6227:     unless ($readonly) {
                   6228:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6229:     }
1.568     raeburn  6230:     $r->print('</form>');
1.507     www      6231:     &endSettingsScreen($r);
                   6232:     $r->print(&Apache::loncommon::end_page());
1.208     www      6233: }
                   6234: 
1.563     damieng  6235: # Fills $listdata with parameter information.
                   6236: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6237: # The non-type value is always 1.
                   6238: #
                   6239: # @param {string} $cat - parameter name
1.566     damieng  6240: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6241: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6242: # @param {hash reference} $listdata - the parameter data that will be modified
                   6243: # @param {array reference} $psprt - selected parts
                   6244: # @param {array reference} $selections - selected sections
                   6245: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6246: # @param {hash reference} $allmaps - hash map pc -> map src
                   6247: # @param {array reference} $ids - resource and map ids
                   6248: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6249: sub secgroup_lister {
                   6250:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6251:     foreach my $item (@{$selections}) {
                   6252:         foreach my $part (@{$psprt}) {
                   6253:             my $rootparmkey=$env{'request.course.id'};
                   6254:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6255:                 $rootparmkey.='.['.$item.']';
                   6256:             }
                   6257:             if ($parmlev eq 'general') {
                   6258: # course-level parameter
                   6259:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6260:                 $$listdata{$newparmkey}=1;
                   6261:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6262:             } elsif ($parmlev eq 'map') {
                   6263: # map-level parameter
1.548     raeburn  6264:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6265:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6266:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6267:                     $$listdata{$newparmkey}=1;
                   6268:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6269:                 }
                   6270:             } else {
                   6271: # resource-level parameter
                   6272:                 foreach my $rid (@{$ids}) {
                   6273:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6274:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6275:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6276:                     $$listdata{$newparmkey}=1;
                   6277:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6278:                 }
                   6279:             }
                   6280:         }
                   6281:     }
                   6282: }
                   6283: 
1.563     damieng  6284: # UI to edit parameter settings starting with a list of all existing parameters.
                   6285: # (called by setoverview action)
                   6286: #
                   6287: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6288: sub overview {
1.568     raeburn  6289:     my ($r,$parm_permission) = @_;
1.208     www      6290:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6291:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6292:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6293:     my $readonly = 1;
                   6294:     if ($parm_permission->{'edit'}) {
                   6295:         undef($readonly);
                   6296:     }
1.549     raeburn  6297:     my $js = '<script type="text/javascript">'."\n".
                   6298:              '// <![CDATA['."\n".
                   6299:              &toggleparmtextbox_js()."\n".
                   6300:              &validateparms_js()."\n".
                   6301:              &ipacc_boxes_js()."\n".
1.558     raeburn  6302:              &done_proctor_js()."\n".
1.588     raeburn  6303:              &deeplink_js()."\n".
1.549     raeburn  6304:              '// ]]>'."\n".
                   6305:              '</script>'."\n";
1.414     droeschl 6306:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6307:     text=>"Overview Mode"});
1.549     raeburn  6308:     my %loaditems = (
                   6309:                       'onload'   => "showHideLenient();",
                   6310:                     );
                   6311: 
                   6312:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6313:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6314:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6315:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6316:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6317: 
1.208     www      6318: # Store modified
                   6319: 
1.568     raeburn  6320:     unless ($readonly) {
                   6321:         &storedata($r,$crs,$dom);
                   6322:     }
1.208     www      6323: 
                   6324: # Read modified data
                   6325: 
1.552     raeburn  6326:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6327: 
1.214     www      6328: 
                   6329:     my $sortorder=$env{'form.sortorder'};
                   6330:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6331:     &sortmenu($r,$sortorder,'overview');
1.214     www      6332: 
1.568     raeburn  6333:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6334: 
                   6335:     if ($readonly) {
                   6336:         $r->print('<p>'.$submitbutton.'</p>');
                   6337:     }
                   6338: 
1.208     www      6339: # List data
                   6340: 
1.568     raeburn  6341:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6342:     $r->print(&tableend().'<p>');
                   6343:     if ($foundkeys) {
                   6344:         unless ($readonly) {
                   6345:             $r->print('<p>'.$submitbutton.'</p>');
                   6346:         }
                   6347:     } else {
                   6348:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6349:     }
                   6350:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6351: }
1.121     www      6352: 
1.560     damieng  6353: # Unused sub.
1.563     damieng  6354: #
                   6355: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6356: sub clean_parameters {
                   6357:     my ($r) = @_;
                   6358:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6359:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6360: 
1.414     droeschl 6361:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6362:         text=>"Clean Parameters"});
1.333     albertel 6363:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6364:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6365:     $r->print(<<ENDOVER);
                   6366: $start_page
                   6367: $breadcrumbs
                   6368: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6369: ENDOVER
                   6370: # Store modified
                   6371: 
                   6372:     &storedata($r,$crs,$dom);
                   6373: 
                   6374: # Read modified data
                   6375: 
                   6376:     my $resourcedata=&readdata($crs,$dom);
                   6377: 
                   6378: # List data
                   6379: 
                   6380:     $r->print('<h3>'.
1.473     amueller 6381:           &mt('These parameters refer to resources that do not exist.').
                   6382:           '</h3>'.
                   6383:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6384:           '<br />');
1.333     albertel 6385:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6386:           '<tr>'.
                   6387:           '<th>'.&mt('Delete').'</th>'.
                   6388:           '<th>'.&mt('Parameter').'</th>'.
                   6389:           '</tr>');
1.333     albertel 6390:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6391:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6392:             && $thiskey=~/\.type$/);
                   6393:         my %data = &parse_key($thiskey);
                   6394:         if (1) { #exists($data{'realm_exists'})
                   6395:             #&& !$data{'realm_exists'}) {
                   6396:             $r->print(&Apache::loncommon::start_data_table_row().
                   6397:                 '<tr>'.
                   6398:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6399: 
                   6400:             $r->print('<td>');
                   6401:             my $display_value = $resourcedata->{$thiskey};
                   6402:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6403:             $display_value =
                   6404:                 &Apache::lonlocal::locallocaltime($display_value);
                   6405:             }
1.470     raeburn  6406:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6407:             $parmitem = &mt($parmitem);
1.560     damieng  6408:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6409:                 $parmitem,$resourcedata->{$thiskey}));
                   6410:             $r->print('<br />');
                   6411:             if ($data{'scope_type'} eq 'all') {
                   6412:                 $r->print(&mt('All users'));
                   6413:             } elsif ($data{'scope_type'} eq 'user') {
                   6414:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6415:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6416:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6417:             }
                   6418:             $r->print('<br />');
                   6419:             if ($data{'realm_type'} eq 'all') {
                   6420:                 $r->print(&mt('All Resources'));
                   6421:             } elsif ($data{'realm_type'} eq 'folder') {
                   6422:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6423:             } elsif ($data{'realm_type'} eq 'symb') {
                   6424:             my ($map,$resid,$url) =
                   6425:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6426:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6427:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6428:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6429:             }
                   6430:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6431:             $r->print('</td></tr>');
                   6432: 
1.473     amueller 6433:         }
1.333     albertel 6434:     }
                   6435:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6436:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6437:           '</p></form>');
                   6438:     &endSettingsScreen($r);
                   6439:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6440: }
                   6441: 
1.563     damieng  6442: # UI to shift all dates (called by dateshift1 action).
                   6443: # Used by overview mode.
                   6444: #
                   6445: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6446: sub date_shift_one {
                   6447:     my ($r) = @_;
                   6448:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6449:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6450:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6451:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6452:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6453:         text=>"Shifting Dates"});
1.594     raeburn  6454:     my $submit_text = &mt('Shift all dates accordingly');
                   6455:     if ($sec ne '') {
1.595     raeburn  6456:         my @groups;
                   6457:         if ($env{'request.course.groups'} ne '') {
                   6458:             @groups = split(/:/,$env{'request.course.groups'});
                   6459:         }
                   6460:         if (@groups) {
                   6461:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6462:         } else {
                   6463:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6464:         }
1.594     raeburn  6465:     }
1.390     www      6466:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6467:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6468:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6469:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6470:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6471:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6472:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6473:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6474:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6475:                                                         'timeshifted',
                   6476:                                                         $env{'form.timebase'},,
                   6477:                                                         '').
                   6478:               '</td></tr></table>'.
                   6479:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6480:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6481:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6482:     &endSettingsScreen($r);
1.390     www      6483:     $r->print(&Apache::loncommon::end_page());
                   6484: }
                   6485: 
1.563     damieng  6486: # UI to shift all dates (second form).
                   6487: #
                   6488: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6489: sub date_shift_two {
                   6490:     my ($r) = @_;
                   6491:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6492:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6493:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6494:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6495:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6496:         text=>"Shifting Dates"});
1.390     www      6497:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6498:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6499:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6500:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6501:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6502:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6503:     if ($sec ne '') {
1.595     raeburn  6504:         my @groups;
                   6505:         if ($env{'request.course.groups'} ne '') {
                   6506:             @groups = split(/:/,$env{'request.course.groups'});
                   6507:         }
                   6508:         if (@groups) {
                   6509:             $r->print('<p>'.
                   6510:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6511:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6512:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6513:                       '</p>');
                   6514:         } else {
                   6515:             $r->print('<p>'.
                   6516:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6517:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6518:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6519:                       '</p>');
                   6520:         }
1.594     raeburn  6521:     } else {
                   6522:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6523:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6524:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6525:                   '</p>');
                   6526:     }
1.390     www      6527:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6528:     my $numchanges = 0;
                   6529:     my $result = &dateshift($delta,\$numchanges);
                   6530:     if ($result eq 'ok') {
                   6531:         $r->print(
                   6532:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6533:                                                     $numchanges)));
                   6534:     } elsif ($result eq 'con_delayed') {
                   6535:         $r->print(
                   6536:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6537:                                                         $numchanges)));
                   6538:     } else {
                   6539:         $r->print(
                   6540:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6541:     }
1.543     bisitz   6542:     $r->print(
                   6543:         '<br /><br />'.
                   6544:         &Apache::lonhtmlcommon::actionbox(
                   6545:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6546:     &endSettingsScreen($r);
1.390     www      6547:     $r->print(&Apache::loncommon::end_page());
                   6548: }
                   6549: 
1.563     damieng  6550: # Returns the different components of a resourcedata key.
                   6551: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6552: #       realm_exists, parameter_part, parameter_name.
                   6553: # Was used by clean_parameters (which is unused).
                   6554: #
                   6555: # @param {string} $key - the parameter key
                   6556: # @returns {hash}
1.333     albertel 6557: sub parse_key {
                   6558:     my ($key) = @_;
                   6559:     my %data;
                   6560:     my ($middle,$part,$name)=
1.572     damieng  6561:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6562:     $data{'scope_type'} = 'all';
                   6563:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6564:         $data{'scope'} = $1;
                   6565:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6566:             $data{'scope_type'} = 'user';
                   6567:             $data{'scope'} = [$1,$2];
                   6568:         } else {
1.581     raeburn  6569:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6570:         }
                   6571:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6572:     }
                   6573:     $middle=~s/\.+$//;
                   6574:     $middle=~s/^\.+//;
                   6575:     $data{'realm_type'}='all';
                   6576:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6577:         $data{'realm'} = $1;
                   6578:         $data{'realm_type'} = 'folder';
                   6579:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6580:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6581:     } elsif ($middle) {
1.560     damieng  6582:         $data{'realm'} = $middle;
                   6583:         $data{'realm_type'} = 'symb';
                   6584:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6585:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6586:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6587:     }
1.446     bisitz   6588: 
1.333     albertel 6589:     $data{'parameter_part'} = $part;
                   6590:     $data{'parameter_name'} = $name;
                   6591: 
                   6592:     return %data;
                   6593: }
                   6594: 
1.239     raeburn  6595: 
1.563     damieng  6596: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6597: sub header {
1.507     www      6598:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6599: }
1.193     albertel 6600: 
                   6601: 
                   6602: 
1.560     damieng  6603: ##################################################
                   6604: # MAIN MENU
                   6605: ##################################################
                   6606: 
1.563     damieng  6607: # Content and problem settings main menu.
                   6608: #
                   6609: # @param {Apache2::RequestRec} $r - the Apache request
                   6610: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6611: sub print_main_menu {
                   6612:     my ($r,$parm_permission)=@_;
                   6613:     #
1.414     droeschl 6614:     $r->print(&header());
1.507     www      6615:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6616:     my $crstype = &Apache::loncommon::course_type();
                   6617:     my $lc_crstype = lc($crstype);
                   6618: 
                   6619:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6620:     $r->print(<<ENDMAINFORMHEAD);
                   6621: <form method="post" enctype="multipart/form-data"
                   6622:       action="/adm/parmset" name="studentform">
                   6623: ENDMAINFORMHEAD
                   6624: #
1.195     albertel 6625:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6626:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6627:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6628:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6629:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6630:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6631:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6632:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6633:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6634:                                         '/'.$env{'request.course.sec'});
                   6635:     }
1.568     raeburn  6636:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6637:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6638:                                         '/'.$env{'request.course.sec'});
                   6639:     }
                   6640:     my (%linktext,%linktitle,%url);
                   6641:     if ($parm_permission->{'edit'}) {
                   6642:         %linktext = (
                   6643:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6644:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6645:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6646:                     );
                   6647:         %linktitle = (
                   6648:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6649:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6650:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6651:                      );
                   6652:     } else {
                   6653:         %linktext = (
                   6654:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6655:                      settable        => 'View Resource Parameters - Table Mode',
                   6656:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6657:                    );
                   6658:         %linktitle = (
                   6659:                      newoverview     => 'Display resource parameters in overview mode.',
                   6660:                      settable        => 'Display resource parameters in table mode.',
                   6661:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6662:                      );
                   6663:     }
                   6664:     if ($mgr) {
                   6665:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6666:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6667:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6668:     } elsif ($vgr) {
                   6669:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6670:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6671:         $url{'resettimes'} = '/adm/accesstimes';
                   6672:     }
1.193     albertel 6673:     my @menu =
1.507     www      6674:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6675:         items => [
                   6676:           { linktext => 'Portfolio Metadata',
                   6677:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6678:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6679:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6680:             icon =>'contact-new.png'   ,
                   6681:             },
1.568     raeburn  6682:           { linktext => $linktext{'resettimes'},
                   6683:             url => $url{'resettimes'},
                   6684:             permission => ($vgr || $mgr),
                   6685:             linktitle => $linktitle{'resettimes'},
                   6686:             icon => 'start-here.png',
1.473     amueller 6687:             },
1.520     raeburn  6688:           { linktext => 'Blocking Communication/Resource Access',
                   6689:             url => '/adm/setblock',
1.568     raeburn  6690:             permission => ($vcb || $dcm),
1.520     raeburn  6691:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6692:             icon => 'comblock.png',
                   6693:             },
1.473     amueller 6694:           { linktext => 'Set Parameter Setting Default Actions',
                   6695:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6696:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6697:             linktitle =>'Set default actions for parameters.'  ,
                   6698:             icon => 'folder-new.png'  ,
                   6699:             }]},
                   6700:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6701:         items => [
                   6702:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6703:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6704:             permission => $parm_permission->{'helper'},
1.473     amueller 6705:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6706:             icon => 'dialog-information.png'  ,
                   6707:             #help => 'Parameter_Helper',
                   6708:             },
1.568     raeburn  6709:           { linktext => $linktext{'newoverview'},
1.473     amueller 6710:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6711:             permission => $parm_permission->{'newoverview'},
                   6712:             linktitle => $linktitle{'newoverview'},
                   6713:             icon => 'edit-find.png',
1.473     amueller 6714:             #help => 'Parameter_Overview',
                   6715:             },
1.568     raeburn  6716:           { linktext => $linktext{'settable'},
1.473     amueller 6717:             url => '/adm/parmset?action=settable',
1.568     raeburn  6718:             permission => $parm_permission->{'settable'},
                   6719:             linktitle => $linktitle{'settable'},
                   6720:             icon => 'edit-copy.png',
1.473     amueller 6721:             #help => 'Table_Mode',
                   6722:             }]},
1.417     droeschl 6723:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6724:          items => [
1.570     raeburn  6725:           { linktext => $linktext{'setoverview'},
1.473     amueller 6726:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6727:             permission => $parm_permission->{'setoverview'},
                   6728:             linktitle => $linktitle{'setoverview'},
                   6729:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6730:             #help => 'Parameter_Overview',
                   6731:             },
                   6732:           { linktext => 'Change Log',
                   6733:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6734:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6735:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6736:             icon => 'document-properties.png',
1.473     amueller 6737:             }]}
1.193     albertel 6738:           );
1.414     droeschl 6739:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6740:     $r->print('</form>');
1.507     www      6741:     &endSettingsScreen($r);
1.539     raeburn  6742:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6743:     return;
                   6744: }
1.414     droeschl 6745: 
1.416     jms      6746: 
                   6747: 
1.560     damieng  6748: ##################################################
                   6749: # PORTFOLIO METADATA
                   6750: ##################################################
                   6751: 
1.563     damieng  6752: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6753: # It looks like field titles are not localized.
                   6754: #
                   6755: # @param {Apache2::RequestRec} $r - the Apache request
                   6756: # @param {string} $field_name - metadata field name
                   6757: # @param {string} $field_text - metadata field title, in English unless manually added
                   6758: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6759: sub output_row {
1.347     banghart 6760:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6761:     my $output;
1.263     banghart 6762:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6763:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6764:     if (!defined($options)) {
1.254     banghart 6765:         $options = 'active,stuadd';
1.261     banghart 6766:         $values = '';
1.252     banghart 6767:     }
1.337     banghart 6768:     if (!($options =~ /deleted/)) {
                   6769:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6770:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6771:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6772: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6773:         if ($added_flag) {
                   6774:             push @options,['deleted', 'Delete Metadata Field'];
                   6775:         }
1.351     banghart 6776:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6777:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6778:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6779:         foreach my $opt (@options) {
1.560     damieng  6780:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6781:             $output .= &Apache::loncommon::continue_data_table_row();
                   6782:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6783:                     <input type="checkbox" name="'.
                   6784:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6785:                     &mt($opt->[1]).'</label></td>';
                   6786:             $output .= &Apache::loncommon::end_data_table_row();
                   6787:         }
1.351     banghart 6788:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6789:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6790:         $output .= &Apache::loncommon::end_data_table_row();
                   6791:         my $multiple_checked;
                   6792:         my $single_checked;
                   6793:         if ($options =~ m/onlyone/) {
1.422     bisitz   6794:             $multiple_checked = '';
1.423     bisitz   6795:             $single_checked = ' checked="checked"';
1.351     banghart 6796:         } else {
1.423     bisitz   6797:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6798:             $single_checked = '';
1.351     banghart 6799:         }
1.560     damieng  6800:         $output .= &Apache::loncommon::continue_data_table_row();
                   6801:         $output .= '<td>'.('&nbsp;' x 10).'
                   6802:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6803:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6804:         $output .= &Apache::loncommon::end_data_table_row();
                   6805:         $output .= &Apache::loncommon::continue_data_table_row();
                   6806:         $output .= '<td>'.('&nbsp;' x 10).'
                   6807:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6808:                     '.&mt('Student may select only one choice from list').'</td>';
                   6809:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6810:     }
                   6811:     return ($output);
                   6812: }
1.416     jms      6813: 
                   6814: 
1.560     damieng  6815: # UI to order portfolio metadata fields.
1.563     damieng  6816: # Currently useless because addmetafield does not work.
                   6817: #
                   6818: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6819: sub order_meta_fields {
                   6820:     my ($r)=@_;
                   6821:     my $idx = 1;
                   6822:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6823:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6824:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6825:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6826:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6827:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6828:         text=>"Add Metadata Field"});
1.560     damieng  6829:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6830:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6831:         text=>"Restrict Metadata"},
                   6832:         {text=>"Order Metadata"});
1.345     banghart 6833:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6834:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6835:     if ($env{'form.storeorder'}) {
                   6836:         my $newpos = $env{'form.newpos'} - 1;
                   6837:         my $currentpos = $env{'form.currentpos'} - 1;
                   6838:         my @neworder = ();
1.548     raeburn  6839:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6840:         my $i;
1.341     banghart 6841:         if ($newpos > $currentpos) {
1.340     banghart 6842:         # moving stuff up
                   6843:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6844:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6845:             }
                   6846:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6847:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6848:             }
                   6849:             $neworder[$newpos]=$oldorder[$currentpos];
                   6850:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6851:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6852:             }
                   6853:         } else {
                   6854:         # moving stuff down
1.473     amueller 6855:             for ($i=0;$i<$newpos;$i++) {
                   6856:                 $neworder[$i]=$oldorder[$i];
                   6857:             }
                   6858:             $neworder[$newpos]=$oldorder[$currentpos];
                   6859:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6860:                 $neworder[$i]=$oldorder[$i-1];
                   6861:             }
                   6862:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6863:                 $neworder[$i]=$oldorder[$i];
                   6864:             }
1.340     banghart 6865:         }
1.560     damieng  6866:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6867:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6868:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6869:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6870:     }
1.357     raeburn  6871:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6872:     my $ordered_fields;
1.548     raeburn  6873:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6874:     if (!@fields_in_order) {
                   6875:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6876:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6877:             push @fields_in_order, $key;
1.341     banghart 6878:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6879:         }
1.341     banghart 6880:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6881:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6882:     }
1.340     banghart 6883:     $r->print('<table>');
                   6884:     my $num_fields = scalar(@fields_in_order);
                   6885:     foreach my $key (@fields_in_order) {
                   6886:         $r->print('<tr><td>');
                   6887:         $r->print('<form method="post" action="">');
1.537     bisitz   6888:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6889:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6890:             if ($i eq $idx) {
                   6891:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6892:             } else {
                   6893:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6894:             }
                   6895:         }
                   6896:         $r->print('</select></td><td>');
                   6897:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6898:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6899:         $r->print('</form>');
                   6900:         $r->print($$fields{$key}.'</td></tr>');
                   6901:         $idx ++;
                   6902:     }
                   6903:     $r->print('</table>');
1.507     www      6904:     &endSettingsScreen($r);
1.340     banghart 6905:     return 'ok';
                   6906: }
1.416     jms      6907: 
                   6908: 
1.563     damieng  6909: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6910: # @returns {string}
1.359     banghart 6911: sub continue {
                   6912:     my $output;
                   6913:     $output .= '<form action="" method="post">';
                   6914:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6915:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6916:     return ($output);
                   6917: }
1.416     jms      6918: 
                   6919: 
1.563     damieng  6920: # UI to add a metadata field.
                   6921: # Currenly does not work because of an HTML error (the field is not visible).
                   6922: #
                   6923: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6924: sub addmetafield {
                   6925:     my ($r)=@_;
1.414     droeschl 6926:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6927:         text=>"Add Metadata Field"});
1.334     banghart 6928:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6929:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6930:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6931:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6932:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6933:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6934:     if (exists($env{'form.undelete'})) {
1.358     banghart 6935:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6936:         foreach my $meta_field(@meta_fields) {
                   6937:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6938:             $options =~ s/deleted//;
                   6939:             $options =~ s/,,/,/;
                   6940:             my $put_result = &Apache::lonnet::put('environment',
                   6941:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6942: 
1.586     raeburn  6943:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6944:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6945:                           '</strong>',$put_result).
                   6946:                       '<br />');
1.339     banghart 6947:         }
1.359     banghart 6948:         $r->print(&continue());
1.339     banghart 6949:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6950:         my $meta_field = $env{'form.fieldname'};
                   6951:         my $display_field = $env{'form.fieldname'};
                   6952:         $meta_field =~ s/\W/_/g;
1.338     banghart 6953:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6954:         my $put_result = &Apache::lonnet::put('environment',
                   6955:                             {'metadata.'.$meta_field.'.values'=>"",
                   6956:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6957:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6958:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6959:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6960:                   '<br />');
1.359     banghart 6961:         $r->print(&continue());
1.335     banghart 6962:     } else {
1.357     raeburn  6963:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6964:         if ($fields) {
1.586     raeburn  6965:             $r->print(&mt('You may undelete previously deleted fields.').
                   6966:                       '<br />'.
                   6967:                       &mt('Check those you wish to undelete and click Undelete.').
                   6968:                       '<br />');
1.339     banghart 6969:             $r->print('<form method="post" action="">');
                   6970:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6971:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6972:             }
1.586     raeburn  6973:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6974:             $r->print('</form>');
                   6975:         }
1.586     raeburn  6976:         $r->print('<hr />'.
                   6977:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6978:                       '<strong>','</strong>').
1.581     raeburn  6979:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6980:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6981:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6982:         $r->print('</form>');
1.334     banghart 6983:     }
1.507     www      6984:     &endSettingsScreen($r);
1.334     banghart 6985: }
1.416     jms      6986: 
                   6987: 
                   6988: 
1.560     damieng  6989: # Display or save portfolio metadata.
1.563     damieng  6990: #
                   6991: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6992: sub setrestrictmeta {
1.240     banghart 6993:     my ($r)=@_;
1.242     banghart 6994:     my $next_meta;
1.244     banghart 6995:     my $output;
1.245     banghart 6996:     my $item_num;
1.246     banghart 6997:     my $put_result;
1.414     droeschl 6998:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6999:         text=>"Restrict Metadata"});
1.280     albertel 7000:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 7001:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 7002:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7003:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  7004:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   7005:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 7006:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 7007:     my $save_field = '';
1.586     raeburn  7008:     my %lt = &Apache::lonlocal::texthash(
                   7009:                                            addm => 'Add Metadata Field',
                   7010:                                            ordm => 'Order Metadata Fields',
                   7011:                                            save => 'Save',
                   7012:                                         );
1.259     banghart 7013:     if ($env{'form.restrictmeta'}) {
1.254     banghart 7014:         foreach my $field (sort(keys(%env))) {
1.252     banghart 7015:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 7016:                 my $options;
1.252     banghart 7017:                 my $meta_field = $1;
                   7018:                 my $meta_key = $2;
1.253     banghart 7019:                 if ($save_field ne $meta_field) {
1.252     banghart 7020:                     $save_field = $meta_field;
1.473     amueller 7021:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   7022:                         $options.='stuadd,';
                   7023:                     }
                   7024:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   7025:                         $options.='choices,';
                   7026:                     }
                   7027:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   7028:                         $options.='onlyone,';
                   7029:                     }
                   7030:                     if ($env{'form.'.$meta_field.'_active'}) {
                   7031:                         $options.='active,';
                   7032:                     }
                   7033:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   7034:                         $options.='deleted,';
                   7035:                     }
1.259     banghart 7036:                     my $name = $save_field;
1.560     damieng  7037:                     $put_result = &Apache::lonnet::put('environment',
                   7038:                         {'metadata.'.$meta_field.'.options'=>$options,
                   7039:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   7040:                         },$dom,$crs);
1.252     banghart 7041:                 }
                   7042:             }
                   7043:         }
                   7044:     }
1.296     albertel 7045:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 7046:                        {'freshen_cache' => 1});
1.335     banghart 7047:     # Get the default metadata fields
1.258     albertel 7048:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 7049:     # Now get possible added metadata fields
1.357     raeburn  7050:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 7051:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 7052:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 7053:         if ($field ne 'courserestricted') {
1.586     raeburn  7054:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  7055:         }
1.255     banghart 7056:     }
1.351     banghart 7057:     my $buttons = (<<ENDButtons);
1.586     raeburn  7058:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 7059:         </form><br />
                   7060:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  7061:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 7062:         </form>
                   7063:         <br />
                   7064:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  7065:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 7066: ENDButtons
1.337     banghart 7067:     my $added_flag = 1;
1.335     banghart 7068:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  7069:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 7070:     }
1.347     banghart 7071:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   7072:     $r->print(<<ENDenv);
1.259     banghart 7073:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 7074:         $output
1.351     banghart 7075:         $buttons
1.340     banghart 7076:         </form>
1.244     banghart 7077: ENDenv
1.507     www      7078:     &endSettingsScreen($r);
1.280     albertel 7079:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 7080:     return 'ok';
                   7081: }
1.416     jms      7082: 
                   7083: 
1.563     damieng  7084: # Returns metadata fields that have been manually added.
                   7085: #
                   7086: # @param {string} $cid - course id
                   7087: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 7088: sub get_added_meta_fieldnames {
1.357     raeburn  7089:     my ($cid) = @_;
1.335     banghart 7090:     my %fields;
                   7091:     foreach my $key(%env) {
1.357     raeburn  7092:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 7093:             my $field_name = $1;
                   7094:             my ($display_field_name) = $env{$key};
                   7095:             $fields{$field_name} = $display_field_name;
                   7096:         }
                   7097:     }
                   7098:     return \%fields;
                   7099: }
1.416     jms      7100: 
                   7101: 
1.563     damieng  7102: # Returns metadata fields that have been manually added and deleted.
                   7103: #
                   7104: # @param {string} $cid - course id
                   7105: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 7106: sub get_deleted_meta_fieldnames {
1.357     raeburn  7107:     my ($cid) = @_;
1.339     banghart 7108:     my %fields;
                   7109:     foreach my $key(%env) {
1.357     raeburn  7110:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 7111:             my $field_name = $1;
                   7112:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   7113:                 my ($display_field_name) = $env{$key};
                   7114:                 $fields{$field_name} = $display_field_name;
                   7115:             }
                   7116:         }
                   7117:     }
                   7118:     return \%fields;
                   7119: }
1.560     damieng  7120: 
                   7121: 
                   7122: ##################################################
                   7123: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7124: ##################################################
                   7125: 
                   7126: # UI to change parameter setting default actions
1.563     damieng  7127: #
                   7128: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7129: sub defaultsetter {
1.280     albertel 7130:     my ($r) = @_;
                   7131: 
1.414     droeschl 7132:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7133:         text=>"Set Defaults"});
1.531     raeburn  7134:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7135:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7136:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7137:     my $start_page =
1.531     raeburn  7138:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7139:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7140:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7141:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7142:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7143: 
1.221     www      7144:     my @ids=();
                   7145:     my %typep=();
                   7146:     my %keyp=();
                   7147:     my %allparms=();
                   7148:     my %allparts=();
                   7149:     my %allmaps=();
                   7150:     my %mapp=();
                   7151:     my %symbp=();
                   7152:     my %maptitles=();
                   7153:     my %uris=();
                   7154:     my %keyorder=&standardkeyorder();
                   7155:     my %defkeytype=();
                   7156: 
1.446     bisitz   7157:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7158:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7159:                 \%keyorder,\%defkeytype);
1.224     www      7160:     if ($env{'form.storerules'}) {
1.560     damieng  7161:         my %newrules=();
                   7162:         my @delrules=();
                   7163:         my %triggers=();
                   7164:         foreach my $key (keys(%env)) {
1.225     albertel 7165:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7166:                 my $tempkey=$1;
                   7167:                 my $action=$env{$key};
1.226     www      7168:                 if ($action) {
1.560     damieng  7169:                     $newrules{$tempkey.'_action'}=$action;
                   7170:                     if ($action ne 'default') {
                   7171:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7172:                         $triggers{$whichparm}.=$tempkey.':';
                   7173:                     }
                   7174:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7175:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7176:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7177:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7178:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7179:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7180:                     } else {
                   7181:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7182:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7183:                     }
                   7184:                 } else {
                   7185:                     push(@delrules,$tempkey.'_action');
                   7186:                     push(@delrules,$tempkey.'_type');
                   7187:                     push(@delrules,$tempkey.'_hours');
                   7188:                     push(@delrules,$tempkey.'_min');
                   7189:                     push(@delrules,$tempkey.'_sec');
                   7190:                     push(@delrules,$tempkey.'_value');
                   7191:                 }
1.473     amueller 7192:             }
                   7193:         }
1.560     damieng  7194:         foreach my $key (keys(%allparms)) {
                   7195:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7196:         }
1.560     damieng  7197:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7198:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7199:         &resetrulescache();
1.224     www      7200:     }
1.227     www      7201:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7202:                        'hours' => 'Hours',
                   7203:                        'min' => 'Minutes',
                   7204:                        'sec' => 'Seconds',
                   7205:                        'yes' => 'Yes',
                   7206:                        'no' => 'No');
1.222     www      7207:     my @standardoptions=('','default');
                   7208:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7209:     my @dateoptions=('','default');
                   7210:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7211:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7212:         unless ($tempkey) { next; }
                   7213:         push @standardoptions,'when_setting_'.$tempkey;
                   7214:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7215:         if (&isdateparm($defkeytype{$tempkey})) {
                   7216:             push @dateoptions,'later_than_'.$tempkey;
                   7217:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7218:             push @dateoptions,'earlier_than_'.$tempkey;
                   7219:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7220:         }
1.222     www      7221:     }
1.563     damieng  7222:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7223:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7224:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7225:           &Apache::loncommon::start_data_table_header_row().
                   7226:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7227:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7228:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7229:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7230:         unless ($tempkey) { next; }
                   7231:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7232:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7233:         my $action=&rulescache($tempkey.'_action');
                   7234:         $r->print('<select name="'.$tempkey.'_action">');
                   7235:         if (&isdateparm($defkeytype{$tempkey})) {
                   7236:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7237:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7238:             $r->print("\n<option value='$dateoptions[$i]'".
                   7239:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7240:                 ">$datedisplay[$i]</option>");
                   7241:             }
                   7242:         } else {
                   7243:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7244:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7245:             $r->print("\n<option value='$standardoptions[$i]'".
                   7246:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7247:                 ">$standarddisplay[$i]</option>");
                   7248:             }
1.473     amueller 7249:         }
1.560     damieng  7250:         $r->print('</select>');
                   7251:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7252:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7253:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7254:         }
1.560     damieng  7255:         $r->print("\n</td><td>\n");
1.222     www      7256: 
1.221     www      7257:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7258:             my $days=&rulescache($tempkey.'_days');
                   7259:             my $hours=&rulescache($tempkey.'_hours');
                   7260:             my $min=&rulescache($tempkey.'_min');
                   7261:             my $sec=&rulescache($tempkey.'_sec');
                   7262:             $r->print(<<ENDINPUTDATE);
                   7263:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7264:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7265:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7266:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7267: ENDINPUTDATE
1.560     damieng  7268:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7269:                 my $yeschecked='';
                   7270:                 my $nochecked='';
                   7271:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7272:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7273: 
                   7274:             $r->print(<<ENDYESNO);
                   7275:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7276:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7277: ENDYESNO
1.221     www      7278:         } else {
1.560     damieng  7279:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7280:         }
1.318     albertel 7281:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7282:     }
1.318     albertel 7283:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7284:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7285:           &mt('Save').'" /></form>'."\n");
                   7286:     &endSettingsScreen($r);
                   7287:     $r->print(&Apache::loncommon::end_page());
1.220     www      7288:     return;
                   7289: }
1.193     albertel 7290: 
1.560     damieng  7291: ##################################################
                   7292: # PARAMETER CHANGES LOG
                   7293: ##################################################
                   7294: 
1.563     damieng  7295: # Returns some info for a parameter log entry.
                   7296: # Returned entries:
                   7297: # $realm - HTML title for the parameter level and resource
                   7298: # $section - parameter section
                   7299: # $name - parameter name
                   7300: # $part - parameter part
                   7301: # $what - $part.'.'.$name
                   7302: # $middle - resource symb ?
                   7303: # $uname - user name (same as given)
                   7304: # $udom - user domain (same as given)
                   7305: # $issection - section or group name
                   7306: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7307: #
                   7308: # @param {string} $key - parameter log key
                   7309: # @param {string} $uname - user name
                   7310: # @param {string} $udom - user domain
                   7311: # @param {boolean} $typeflag - .type log entry
                   7312: # @returns {Array}
1.290     www      7313: sub components {
1.581     raeburn  7314:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7315: 
                   7316:     if ($typeflag) {
1.560     damieng  7317:         $key=~s/\.type$//;
1.290     www      7318:     }
1.330     albertel 7319: 
                   7320:     my ($middle,$part,$name)=
1.572     damieng  7321:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7322:     my $issection;
1.330     albertel 7323: 
1.290     www      7324:     my $section=&mt('All Students');
                   7325:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7326:         $issection=$1;
                   7327:         $section=&mt('Group/Section').': '.$issection;
                   7328:         $middle=~s/^\[(.*)\]//;
1.290     www      7329:     }
                   7330:     $middle=~s/\.+$//;
                   7331:     $middle=~s/^\.+//;
1.291     www      7332:     if ($uname) {
1.560     damieng  7333:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7334:         $issection='';
1.291     www      7335:     }
1.316     albertel 7336:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7337:     my $realmdescription=&mt('all resources');
1.556     raeburn  7338:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7339:         my $mapurl = $1;
                   7340:         my $maplevel = $2;
                   7341:         my $leveltitle = &mt('Folder/Map');
                   7342:         if ($maplevel eq 'rec') {
                   7343:             $leveltitle = &mt('Recursive');
                   7344:         }
1.560     damieng  7345:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7346:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7347:             $mapurl.')</span></span>';
                   7348:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7349:     } elsif ($middle) {
                   7350:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7351:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7352:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7353:             ' in '.$map.' id: '.$id.')</span></span>';
                   7354:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7355:     }
1.291     www      7356:     my $what=$part.'.'.$name;
1.330     albertel 7357:     return ($realm,$section,$name,$part,
1.473     amueller 7358:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7359: }
1.293     www      7360: 
1.563     damieng  7361: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7362: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7363: 
1.563     damieng  7364: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7365: sub load_parameter_names {
1.583     raeburn  7366:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7367:     while (my $configline=<$config>) {
1.560     damieng  7368:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7369:         chomp($configline);
                   7370:         my ($short,$plain)=split(/:/,$configline);
                   7371:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7372:         if ($type eq 'display') {
                   7373:             $standard_parms{$name} = $plain;
1.469     raeburn  7374:         } elsif ($type eq 'type') {
1.560     damieng  7375:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7376:         }
1.328     albertel 7377:     }
                   7378:     close($config);
                   7379:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7380:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7381:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7382: }
                   7383: 
1.563     damieng  7384: # Returns a parameter title for standard parameters, the name for others.
                   7385: #
                   7386: # @param {string} $name - parameter name
                   7387: # @returns {string}
1.292     www      7388: sub standard_parameter_names {
                   7389:     my ($name)=@_;
1.328     albertel 7390:     if (!%standard_parms) {
1.560     damieng  7391:         &load_parameter_names();
1.328     albertel 7392:     }
1.292     www      7393:     if ($standard_parms{$name}) {
1.560     damieng  7394:         return $standard_parms{$name};
1.446     bisitz   7395:     } else {
1.560     damieng  7396:         return $name;
1.292     www      7397:     }
                   7398: }
1.290     www      7399: 
1.563     damieng  7400: # Returns a parameter type for standard parameters, undef for others.
                   7401: #
                   7402: # @param {string} $name - parameter name
                   7403: # @returns {string}
1.469     raeburn  7404: sub standard_parameter_types {
                   7405:     my ($name)=@_;
                   7406:     if (!%standard_parms_types) {
                   7407:         &load_parameter_names();
                   7408:     }
                   7409:     if ($standard_parms_types{$name}) {
                   7410:         return $standard_parms_types{$name};
                   7411:     }
                   7412:     return;
                   7413: }
1.309     www      7414: 
1.563     damieng  7415: # Returns a parameter level title (not localized) from the parameter level name.
                   7416: #
                   7417: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7418: # @returns {string}
1.557     raeburn  7419: sub standard_parameter_levels {
                   7420:     my ($name)=@_;
                   7421:     my %levels = (
                   7422:                     'resourcelevel'   => 'a single resource',
                   7423:                     'maplevel'        => 'the enclosing map/folder', 
                   7424:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7425:                     'courselevel'     => 'the general (course) level',
                   7426:                  );
                   7427:     if ($levels{$name}) {
                   7428:         return $levels{$name};
                   7429:     }
                   7430:     return;
                   7431: }
                   7432: 
1.560     damieng  7433: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7434: #
                   7435: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7436: sub parm_change_log {
1.568     raeburn  7437:     my ($r,$parm_permission)=@_;
1.531     raeburn  7438:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7439:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7440:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7441:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7442:     text=>"Parameter Change Log"});
1.522     raeburn  7443:     my $js = '<script type="text/javascript">'."\n".
                   7444:              '// <![CDATA['."\n".
                   7445:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7446:              '// ]]>'."\n".
                   7447:              '</script>'."\n";
                   7448:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7449:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7450:     &startSettingsScreen($r,'parmset',$crstype);
                   7451:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7452: 
1.301     www      7453:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7454: 
1.522     raeburn  7455:     $r->print('<div class="LC_left_float">'.
                   7456:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7457:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7458:                      method="post" name="parameterlog">');
1.446     bisitz   7459: 
1.311     albertel 7460:     my %saveable_parameters = ('show' => 'scalar',);
                   7461:     &Apache::loncommon::store_course_settings('parameter_log',
                   7462:                                               \%saveable_parameters);
                   7463:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7464:                                                 \%saveable_parameters);
1.522     raeburn  7465:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7466:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7467:               '</form></fieldset></div><br clear="all" />');
1.301     www      7468: 
1.568     raeburn  7469:     my $readonly = 1;
                   7470:     if ($parm_permission->{'edit'}) {
                   7471:         undef($readonly);
                   7472:     }
1.531     raeburn  7473:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7474:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7475:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7476:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7477:     unless ($readonly) {
                   7478:         $r->print('<th>'.&mt('Announce').'</th>');
                   7479:     }
                   7480:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7481:     my $shown=0;
1.349     www      7482:     my $folder='';
                   7483:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7484:         my $last='';
                   7485:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7486:                 &GDBM_READER(),0640)) {
                   7487:             $last=$hash{'last_known'};
                   7488:             untie(%hash);
                   7489:         }
                   7490:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7491:     }
1.595     raeburn  7492:     my $numgroups = 0;
                   7493:     my @groups;
                   7494:     if ($env{'request.course.groups'} ne '') {
                   7495:         @groups = split(/:/,$env{'request.course.groups'});
                   7496:         $numgroups = scalar(@groups);
                   7497:     }
1.560     damieng  7498:     foreach my $id (sort {
                   7499:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7500:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7501:                 }
                   7502:                 my $aid = (split('00000',$a))[-1];
                   7503:                 my $bid = (split('00000',$b))[-1];
                   7504:                 return $bid<=>$aid;
1.473     amueller 7505:             } (keys(%parmlog))) {
1.294     www      7506:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7507:         my $count = 0;
                   7508:         my $time =
                   7509:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7510:         my $plainname =
                   7511:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7512:                         $parmlog{$id}{'exe_udom'});
                   7513:         my $about_me_link =
                   7514:             &Apache::loncommon::aboutmewrapper($plainname,
                   7515:                             $parmlog{$id}{'exe_uname'},
                   7516:                             $parmlog{$id}{'exe_udom'});
                   7517:         my $send_msg_link='';
1.568     raeburn  7518:         if ((!$readonly) && 
                   7519:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7520:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7521:             $send_msg_link ='<br />'.
                   7522:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7523:                             $parmlog{$id}{'exe_uname'},
                   7524:                             $parmlog{$id}{'exe_udom'});
                   7525:         }
                   7526:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7527:         my $makenewrow=0;
                   7528:         my %istype=();
                   7529:         my $output;
                   7530:         foreach my $changed (reverse(sort(@changes))) {
                   7531:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7532:             my $typeflag = ($changed =~/\.type$/ &&
                   7533:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7534:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7535:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7536:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7537:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7538:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7539:                 if ($uname ne '') {
                   7540:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7541:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7542:                 }
                   7543:             }
                   7544:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7545:                 if ($folder) {
                   7546:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7547:                 }
                   7548:             }
                   7549:             if ($typeflag) {
                   7550:                 $istype{$parmname}=$value;
                   7551:                 if (!$env{'form.includetypes'}) { next; }
                   7552:             }
                   7553:             $count++;
                   7554:             if ($makenewrow) {
                   7555:                 $output .= $row_start;
                   7556:             } else {
                   7557:                 $makenewrow=1;
                   7558:             }
1.470     raeburn  7559:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7560:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7561:                 &mt($parmitem).'</td><td>'.
                   7562:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7563:             my $stillactive=0;
                   7564:             if ($parmlog{$id}{'delflag'}) {
                   7565:                 $output .= &mt('Deleted');
                   7566:             } else {
                   7567:                 if ($typeflag) {
1.470     raeburn  7568:                     my $parmitem = &standard_parameter_names($value); 
                   7569:                     $parmitem = &mt($parmitem);
1.560     damieng  7570:                     $output .= &mt('Type: [_1]',$parmitem);
                   7571:                 } else {
1.584     raeburn  7572:                     my $toolsymb;
                   7573:                     if ($middle =~ /ext\.tool$/) {
                   7574:                         $toolsymb = $middle;
                   7575:                     }
1.560     damieng  7576:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7577:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7578:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7579:                     my $showvalue = $value;
                   7580:                     if ($istype{$parmname} eq '') {
                   7581:                         my $type = &standard_parameter_types($parmname);
                   7582:                         if ($type ne '') {
                   7583:                             if (&isdateparm($type)) {
                   7584:                                 $showvalue =
                   7585:                                     &Apache::lonlocal::locallocaltime($value);
                   7586:                             }
                   7587:                         }
                   7588:                     } else {
1.560     damieng  7589:                         if (&isdateparm($istype{$parmname})) {
                   7590:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7591:                         }
1.469     raeburn  7592:                     }
                   7593:                     $output .= $showvalue;
1.560     damieng  7594:                     if ($value ne $all[$level]) {
                   7595:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7596:                     } else {
                   7597:                         $stillactive=1;
                   7598:                     }
                   7599:                 }
1.473     amueller 7600:             }
1.568     raeburn  7601:             $output .= '</td>';
                   7602: 
                   7603:             unless ($readonly) { 
                   7604:                 $output .= '<td>';
                   7605:                 if ($stillactive) {
                   7606:                     my $parmitem = &standard_parameter_names($parmname);
                   7607:                     $parmitem = &mt($parmitem);
                   7608:                     my $title=&mt('Changed [_1]',$parmitem);
                   7609:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7610:                         $parmitem,$realmdescription,
                   7611:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7612:                     if (($uname) && ($udom)) {
                   7613:                         $output .=
                   7614:                         &Apache::loncommon::messagewrapper('Notify User',
                   7615:                                                            $uname,$udom,$title,
                   7616:                                                            $description);
                   7617:                     } else {
                   7618:                         $output .=
                   7619:                             &Apache::lonrss::course_blog_link($id,$title,
                   7620:                                                               $description);
                   7621:                     }
1.560     damieng  7622:                 }
1.568     raeburn  7623:                 $output .= '</td>';
1.560     damieng  7624:             }
1.568     raeburn  7625:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7626:         }
1.560     damieng  7627:         if ($env{'form.displayfilter'} eq 'containing') {
                   7628:             my $wholeentry=$about_me_link.':'.
                   7629:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7630:             $output;
                   7631:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7632:         }
1.349     www      7633:         if ($count) {
1.560     damieng  7634:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7635:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7636:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7637:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7638:             $send_msg_link.'</td>'.$output);
                   7639:             $shown++;
                   7640:         }
                   7641:         if (!($env{'form.show'} eq &mt('all')
                   7642:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7643:     }
1.301     www      7644:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7645:     &endSettingsScreen($r);
1.284     www      7646:     $r->print(&Apache::loncommon::end_page());
                   7647: }
                   7648: 
1.560     damieng  7649: ##################################################
                   7650: # MISC !
                   7651: ##################################################
                   7652: 
1.563     damieng  7653: # Stores slot information.
1.560     damieng  7654: # Used by table UI
1.563     damieng  7655: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7656: #
                   7657: # @param {string} $slot_name - slot name
                   7658: # @param {string} $cdom - course domain
                   7659: # @param {string} $cnum - course number
                   7660: # @param {string} $symb - resource symb
                   7661: # @param {string} $uname - user name
                   7662: # @param {string} $udom - user domain
                   7663: # @returns {string} - 'ok' or error name
1.437     raeburn  7664: sub update_slots {
                   7665:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7666:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7667:     if (!keys(%slot)) {
                   7668:         return 'error: slot does not exist';
                   7669:     }
                   7670:     my $max=$slot{'maxspace'};
                   7671:     if (!defined($max)) { $max=99999; }
                   7672: 
                   7673:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7674:                                        "^$slot_name\0");
                   7675:     my ($tmp)=%consumed;
                   7676:     if ($tmp=~/^error: 2 / ) {
                   7677:         return 'error: unable to determine current slot status';
                   7678:     }
                   7679:     my $last=0;
                   7680:     foreach my $key (keys(%consumed)) {
                   7681:         my $num=(split('\0',$key))[1];
                   7682:         if ($num > $last) { $last=$num; }
                   7683:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7684:             return 'ok';
                   7685:         }
                   7686:     }
                   7687: 
                   7688:     if (scalar(keys(%consumed)) >= $max) {
                   7689:         return 'error: no space left in slot';
                   7690:     }
                   7691:     my $wanted=$last+1;
                   7692: 
                   7693:     my %reservation=('name'      => $uname.':'.$udom,
                   7694:                      'timestamp' => time,
                   7695:                      'symb'      => $symb);
                   7696: 
                   7697:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7698:                                         {"$slot_name\0$wanted" =>
                   7699:                                              \%reservation},
                   7700:                                         $cdom, $cnum);
1.438     raeburn  7701:     if ($success eq 'ok') {
                   7702:         my %storehash = (
                   7703:                           symb    => $symb,
                   7704:                           slot    => $slot_name,
                   7705:                           action  => 'reserve',
                   7706:                           context => 'parameter',
                   7707:                         );
1.526     raeburn  7708:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7709:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7710: 
1.526     raeburn  7711:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7712:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7713:     }
1.437     raeburn  7714:     return $success;
                   7715: }
                   7716: 
1.563     damieng  7717: # Deletes a slot reservation.
1.560     damieng  7718: # Used by table UI
1.563     damieng  7719: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7720: #
                   7721: # @param {string} $slot_name - slot name
                   7722: # @param {string} $cdom - course domain
                   7723: # @param {string} $cnum - course number
                   7724: # @param {string} $uname - user name
                   7725: # @param {string} $udom - user domain
                   7726: # @param {string} $symb - resource symb
                   7727: # @returns {string} - 'ok' or error name
1.437     raeburn  7728: sub delete_slots {
                   7729:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7730:     my $delresult;
                   7731:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7732:                                          $cnum, "^$slot_name\0");
                   7733:     if (&Apache::lonnet::error(%consumed)) {
                   7734:         return 'error: unable to determine current slot status';
                   7735:     }
                   7736:     my ($tmp)=%consumed;
                   7737:     if ($tmp=~/^error: 2 /) {
                   7738:         return 'error: unable to determine current slot status';
                   7739:     }
                   7740:     foreach my $key (keys(%consumed)) {
                   7741:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7742:             my $num=(split('\0',$key))[1];
                   7743:             my $entry = $slot_name.'\0'.$num;
                   7744:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7745:                                               $cdom,$cnum);
                   7746:             if ($delresult eq 'ok') {
                   7747:                 my %storehash = (
                   7748:                                   symb    => $symb,
                   7749:                                   slot    => $slot_name,
                   7750:                                   action  => 'release',
                   7751:                                   context => 'parameter',
                   7752:                                 );
1.526     raeburn  7753:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7754:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7755:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7756:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7757:             }
                   7758:         }
                   7759:     }
                   7760:     return $delresult;
                   7761: }
                   7762: 
1.563     damieng  7763: # Returns true if there is a current course.
1.560     damieng  7764: # Used by handler
1.563     damieng  7765: #
                   7766: # @returns {boolean}
1.355     albertel 7767: sub check_for_course_info {
                   7768:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7769:     return 1 if ($navmap);
                   7770:     return 0;
                   7771: }
                   7772: 
1.563     damieng  7773: # Returns the current course host and host LON-CAPA version.
                   7774: #
                   7775: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7776: sub parameter_release_vars { 
1.504     raeburn  7777:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7778:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7779:    my $chostname = &Apache::lonnet::hostname($chome);
                   7780:    my ($cmajor,$cminor) = 
                   7781:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7782:    return ($chostname,$cmajor,$cminor);
                   7783: }
                   7784: 
1.563     damieng  7785: # Checks if the course host version can handle a parameter required version,
                   7786: # and if it does, stores the release needed for the course.
                   7787: #
                   7788: # @param {string} $name - parameter name
                   7789: # @param {string} $value - parameter value
                   7790: # @param {string} $valmatch - name of the test used for checking the value
                   7791: # @param {string} $namematch - name of the test used for checking the name
                   7792: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7793: # @param {integer} $cmajor - course major version number
                   7794: # @param {integer} $cminor - course minor version number
                   7795: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7796: sub parameter_releasecheck {
1.557     raeburn  7797:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7798:     my $needsnewer;
                   7799:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7800:     if (($cmajor < $needsmajor) || 
                   7801:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7802:         $needsnewer = 1;
1.557     raeburn  7803:     } elsif ($name) {
                   7804:         if ($valmatch) {
                   7805:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7806:         } elsif ($value) { 
                   7807:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7808:         }
                   7809:     } elsif ($namematch) {
                   7810:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7811:     }
                   7812:     return $needsnewer;
                   7813: }
                   7814: 
1.568     raeburn  7815: sub get_permission {
                   7816:     my %permission;
                   7817:     my $allowed = 0;
                   7818:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7819:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7820:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7821:                   $env{'request.course.sec'}))) {
                   7822:         %permission= (
                   7823:                        'edit'               => 1,
                   7824:                        'set'                => 1,
                   7825:                        'setoverview'        => 1,
                   7826:                        'addmetadata'        => 1,
                   7827:                        'ordermetadata'      => 1,
                   7828:                        'setrestrictmeta'    => 1,
                   7829:                        'newoverview'        => 1,
                   7830:                        'setdefaults'        => 1,
                   7831:                        'settable'           => 1,
                   7832:                        'parameterchangelog' => 1,
                   7833:                        'cleanparameters'    => 1,
                   7834:                        'dateshift1'         => 1,
                   7835:                        'dateshift2'         => 1,
                   7836:                        'helper'             => 1,
                   7837:          );
                   7838:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7839:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7840:                   $env{'request.course.sec'}))) {
                   7841:         %permission = (
                   7842:                        'set'                => 1,
                   7843:                        'settable'           => 1,
                   7844:                        'newoverview'        => 1,
                   7845:                        'setoverview'        => 1,
                   7846:                        'parameterchangelog' => 1,
                   7847:                       );
                   7848:     }
                   7849:     foreach my $perm (values(%permission)) {
                   7850:         if ($perm) { $allowed=1; last; }
                   7851:     }
                   7852:     return (\%permission,$allowed);
                   7853: }
                   7854: 
1.560     damieng  7855: ##################################################
                   7856: # HANDLER
                   7857: ##################################################
                   7858: 
                   7859: # Main handler for lonparmset.
                   7860: # Sub called based on request parameters action and command:
                   7861: # no command or action: print_main_menu
                   7862: # command 'set': assessparms (direct access to table mode for a resource)
                   7863: #                (this can also be accessed simply with the symb parameter)
                   7864: # action 'setoverview': overview (display all existing parameter settings)
                   7865: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7866: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7867: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7868: # action 'newoverview': newoverview (overview mode)
                   7869: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7870: # action 'settable': assessparms (table mode)
                   7871: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7872: #                              blog postings, user notification changes)
                   7873: # action 'cleanparameters': clean_parameters (unused)
                   7874: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7875: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7876: sub handler {
1.43      albertel 7877:     my $r=shift;
1.30      www      7878: 
1.376     albertel 7879:     &reset_caches();
                   7880: 
1.414     droeschl 7881:     &Apache::loncommon::content_type($r,'text/html');
                   7882:     $r->send_http_header;
                   7883:     return OK if $r->header_only;
                   7884: 
1.193     albertel 7885:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7886:                         ['action','state',
1.205     www      7887:                                              'pres_marker',
                   7888:                                              'pres_value',
1.206     www      7889:                                              'pres_type',
1.506     www      7890:                                              'filter','part',
1.390     www      7891:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7892: 
1.83      bowersj2 7893: 
1.193     albertel 7894:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7895:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7896:                         text=>"Content and Problem Settings",
1.473     amueller 7897:                         faq=>10,
                   7898:                         bug=>'Instructor Interface',
1.442     droeschl 7899:                                             help =>
                   7900:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7901: 
1.30      www      7902: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7903:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7904:     my $exists = &check_for_course_info();
                   7905: 
1.568     raeburn  7906:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7907:         #
                   7908:         # Main switch on form.action and form.state, as appropriate
                   7909:         #
                   7910:         # Check first if coming from someone else headed directly for
                   7911:         #  the table mode
1.568     raeburn  7912:         if (($parm_permission->{'set'}) && 
                   7913:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7914:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7915:             &assessparms($r,$parm_permission);
1.193     albertel 7916:         } elsif (! exists($env{'form.action'})) {
                   7917:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7918:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7919:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7920:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7921:             &overview($r,$parm_permission);
1.560     damieng  7922:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7923:             &addmetafield($r);
                   7924:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7925:             &order_meta_fields($r);
1.414     droeschl 7926:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7927:             &setrestrictmeta($r);
1.414     droeschl 7928:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7929:             &newoverview($r,$parm_permission);
1.414     droeschl 7930:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7931:             &defaultsetter($r);
                   7932:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7933:             &assessparms($r,$parm_permission);
1.414     droeschl 7934:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7935:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7936:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7937:             &clean_parameters($r);
1.414     droeschl 7938:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7939:             &date_shift_one($r);
1.414     droeschl 7940:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7941:             &date_shift_two($r);
1.446     bisitz   7942:         }
1.43      albertel 7943:     } else {
1.1       www      7944: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7945:         if ($exists) {
                   7946:             $env{'user.error.msg'}=
                   7947:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7948:         } else {
                   7949:             $env{'user.error.msg'}=
                   7950:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7951:         }
                   7952:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7953:     }
1.376     albertel 7954:     &reset_caches();
                   7955: 
1.43      albertel 7956:     return OK;
1.1       www      7957: }
                   7958: 
                   7959: 1;
                   7960: __END__
                   7961: 
                   7962: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>