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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.611   ! raeburn     4: # $Id: lonparmset.pm,v 1.610 2022/04/30 19:29:43 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.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $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       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       980: sub valout {
1.600     raeburn   981:     my ($value,$type,$editable)=@_;
1.59      matthew   982:     my $result = '';
                    983:     # Values of zero are valid.
                    984:     if (! $value && $value ne '0') {
1.528     bisitz    985:         if ($editable) {
                    986:             $result =
                    987:                 '<img src="/res/adm/pages/editmap.png"'
                    988:                .' alt="'.&mt('Change').'"'
1.539     raeburn   989:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    990:         } else {
                    991:             $result='&nbsp;';
                    992:         }
1.59      matthew   993:     } else {
1.66      www       994:         if ($type eq 'date_interval') {
1.559     raeburn   995:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    996:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    997:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    998:                 $donebuttontext = $1;
                    999:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1000:                 $usesdone = 'done';
                   1001:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1002:                 $donebuttontext = &mt('Done');
                   1003:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1004:             }
1.554     raeburn  1005:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1006:             my @timer;
1.66      www      1007:             $year=$year-70;
                   1008:             $mday--;
                   1009:             if ($year) {
1.413     bisitz   1010: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1011:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1012:             }
                   1013:             if ($mon) {
1.413     bisitz   1014: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1015:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1016:             }
                   1017:             if ($mday) {
1.413     bisitz   1018: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1019:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1020:             }
                   1021:             if ($hour) {
1.413     bisitz   1022: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1023:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1024:             }
                   1025:             if ($min) {
1.413     bisitz   1026: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1027:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1028:             }
                   1029:             if ($sec) {
1.413     bisitz   1030: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1031:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1032:             }
1.413     bisitz   1033: #           $result=~s/\s+$//;
                   1034:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1035:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1036:             }
                   1037:             $result.=join(", ",@timer);
1.559     raeburn  1038:             if ($usesdone eq 'done') {
1.558     raeburn  1039:                 if ($secretkey) {
1.559     raeburn  1040:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1041:                 } else {
1.559     raeburn  1042:                     $result .= ' + "'.$donebuttontext.'"';
                   1043:                 }
1.554     raeburn  1044:             }
1.213     www      1045:         } elsif (&isdateparm($type)) {
1.361     albertel 1046:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1047:                 &date_sanity_info($value);
1.59      matthew  1048:         } else {
                   1049:             $result = $value;
1.517     www      1050:             $result=~s/\,/\, /gs;
1.560     damieng  1051:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1052:         }
                   1053:     }
                   1054:     return $result;
1.9       www      1055: }
                   1056: 
1.59      matthew  1057: 
1.561     damieng  1058: # Returns HTML containing a link on a parameter value, for table mode.
                   1059: # The link uses the javascript function 'pjump'.
                   1060: #
                   1061: # @param {string} $type - parameter type
                   1062: # @param {string} $dis - dialog title for editing the parameter value and type
                   1063: # @param {string} $value - parameter value
                   1064: # @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.
                   1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1069: sub plink {
1.588     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.592     raeburn  1073:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1075:         } elsif ($type eq 'string_yesno') {
                   1076:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1077:                 $winvalue=$env{'form.recent_string'};
                   1078:             }
1.23      www      1079:         } else {
1.190     albertel 1080:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1081:         }
                   1082:     }
1.229     www      1083:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1084:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1085:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1086:     my $valout = &valout($value,$type,1);
1.429     raeburn  1087:     my $unencmarker = $marker;
1.378     albertel 1088:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1089:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1090:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1091:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1092:     }
1.429     raeburn  1093:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1094:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1095:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1096:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1097:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1098: 
1.5       www      1099: }
                   1100: 
1.561     damieng  1101: # Javascript for table mode.
1.280     albertel 1102: sub page_js {
                   1103: 
1.81      www      1104:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1105:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1106: 
                   1107:     return(<<ENDJS);
                   1108: <script type="text/javascript">
1.454     bisitz   1109: // <![CDATA[
1.44      albertel 1110: 
1.88      matthew  1111:     $pjump_def
1.44      albertel 1112: 
                   1113:     function psub() {
1.591     raeburn  1114:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1115:         if (document.parmform.pres_marker.value!='') {
                   1116:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1117:             var typedef=new Array();
                   1118:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1119:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1120:                 if ((typedef[0]=='date') || 
1.591     raeburn  1121:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1122:                     eval('document.parmform.recent_'+
                   1123:                         document.parmform.pres_type.value+
                   1124:                         '.value=document.parmform.pres_value.value;');
                   1125:                 } else {
                   1126:                     eval('document.parmform.recent_'+typedef[0]+
                   1127:                         '.value=document.parmform.pres_value.value;');
                   1128:                 }
1.44      albertel 1129:             }
                   1130:             document.parmform.submit();
                   1131:         } else {
                   1132:             document.parmform.pres_value.value='';
                   1133:             document.parmform.pres_marker.value='';
                   1134:         }
                   1135:     }
                   1136: 
1.57      albertel 1137:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1138:         var options = "width=" + w + ",height=" + h + ",";
                   1139:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1140:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1141:         var newWin = window.open(url, wdwName, options);
                   1142:         newWin.focus();
                   1143:     }
1.523     raeburn  1144: 
1.454     bisitz   1145: // ]]>
1.523     raeburn  1146: 
1.44      albertel 1147: </script>
1.81      www      1148: $selscript
1.280     albertel 1149: ENDJS
                   1150: 
                   1151: }
1.507     www      1152: 
1.561     damieng  1153: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1154: # for table and overview modes.
1.523     raeburn  1155: sub showhide_js {
                   1156:     return <<"COURSECONTENTSCRIPT";
                   1157: 
                   1158: function showHide_courseContent() {
                   1159:     var parmlevValue=document.getElementById("parmlev").value;
                   1160:     if (parmlevValue == 'general') {
                   1161:         document.getElementById('mapmenu').style.display="none";
                   1162:     } else {
                   1163:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1164:             document.getElementById('mapmenu').style.display ="";
                   1165:         } else {
                   1166:             document.getElementById('mapmenu').style.display="none";
                   1167:         }
                   1168:     }
                   1169:     return;
                   1170: }
                   1171: 
                   1172: COURSECONTENTSCRIPT
                   1173: }
                   1174: 
1.561     damieng  1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1176: sub toggleparmtextbox_js {
                   1177:     return <<"ENDSCRIPT";
                   1178: 
                   1179: if (!document.getElementsByClassName) {
                   1180:     function getElementsByClassName(node, classname) {
                   1181:         var a = [];
                   1182:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1183:         var els = node.getElementsByTagName("*");
                   1184:         for(var i=0,j=els.length; i<j; i++)
                   1185:             if(re.test(els[i].className))a.push(els[i]);
                   1186:         return a;
                   1187:     }
                   1188: }
                   1189: 
                   1190: function showHideLenient() {
                   1191:     var lenients;
                   1192:     var setRegExp = /^set_/;
                   1193:     if (document.getElementsByClassName) {
                   1194:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1195:     } else {
                   1196:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1197:     }
                   1198:     if (lenients != 'undefined') {
                   1199:         for (var i=0; i<lenients.length; i++) {
                   1200:             if (lenients[i].checked) {
                   1201:                 if (lenients[i].value == 'weighted') {
                   1202:                     if (setRegExp.test(lenients[i].name)) {
                   1203:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1204:                         toggleParmTextbox(document.parmform,identifier);
                   1205:                     }
                   1206:                 }
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     return;
                   1211: }
                   1212: 
                   1213: function toggleParmTextbox(form,key) {
                   1214:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1215:     if (divfortext) {
                   1216:         var caller = form.elements['set_'+key];
                   1217:         if (caller.length) {
                   1218:             for (i=0; i<caller.length; i++) {
                   1219:                 if (caller[i].checked) {
                   1220:                     if (caller[i].value == 'weighted') {
                   1221:                         divfortext.style.display = 'inline';
                   1222:                     } else {
                   1223:                         divfortext.style.display = 'none';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         }
                   1228:     }
                   1229:     return;
                   1230: }
                   1231: 
                   1232: ENDSCRIPT
                   1233: }
                   1234: 
1.561     damieng  1235: # Javascript function validateParms, for overview mode
1.549     raeburn  1236: sub validateparms_js {
                   1237:     return <<'ENDSCRIPT';
                   1238: 
                   1239: function validateParms() {
                   1240:     var textRegExp = /^settext_/;
                   1241:     var tailLenient = /\.lenient$/;
                   1242:     var patternRelWeight = /^\-?[\d.]+$/;
                   1243:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1244:     var ipRegExp = /^setip/;
1.549     raeburn  1245:     var ipallowRegExp = /^setipallow_/;
                   1246:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1247:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1248:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1249:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1250:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1251:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1252:     var dlKeyRegExp = /^deeplink_key_/;
                   1253:     var dlMenusRegExp = /^deeplink_menus_/;
                   1254:     var dlCollsRegExp = /^deeplink_colls_/;
1.549     raeburn  1255:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1256:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1257:         if (document.parmform.elements.length) {
                   1258:             for (i=0; i<document.parmform.elements.length; i++) {
                   1259:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1260:                 if (textRegExp.test(name)) {
1.549     raeburn  1261:                     var identifier = name.replace(textRegExp,'');
                   1262:                     if (tailLenient.test(identifier)) {
                   1263:                         if (document.parmform.elements['set_'+identifier].length) {
                   1264:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1265:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1266:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1267:                                         var relweight = document.parmform.elements[i].value;
                   1268:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1269:                                         if (!patternRelWeight.test(relweight)) {
                   1270:                                             relweight = '0.0';
                   1271:                                         }
                   1272:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1273:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1274:                                         } else {
                   1275:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1276:                                         }
                   1277:                                     }
                   1278:                                     break;
                   1279:                                 }
                   1280:                             }
                   1281:                         }
                   1282:                     }
1.597     raeburn  1283:                 } else if (ipRegExp.test(name)) {
                   1284:                     if (ipallowRegExp.test(name)) {
                   1285:                         var identifier = name.replace(ipallowRegExp,'');
                   1286:                         var possallow = document.parmform.elements[i].value;
                   1287:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1288:                         if (patternIP.test(possallow)) {
                   1289:                             if (document.parmform.elements['set_'+identifier].value) {
                   1290:                                 possallow = ','+possallow;
                   1291:                             }
                   1292:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1293:                         }
                   1294:                     } else if (ipdenyRegExp.test(name)) {
                   1295:                         var identifier = name.replace(ipdenyRegExp,'');
                   1296:                         var possdeny = document.parmform.elements[i].value;
                   1297:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1298:                         if (patternIP.test(possdeny)) {
                   1299:                             possdeny = '!'+possdeny;
                   1300:                             if (document.parmform.elements['set_'+identifier].value) {
                   1301:                                 possdeny = ','+possdeny;
                   1302:                             }
                   1303:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1304:                         }
                   1305:                     }
                   1306:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1307:                     if (dlListScopeRegExp.test(name)) {
                   1308:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1309:                         var idx = document.parmform.elements[i].selectedIndex;
                   1310:                         if (idx > 0) { 
                   1311:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1312:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1313:                             if (document.parmform.elements['set_'+identifier].value) {
                   1314:                                 possdeeplink = ','+possdeeplink;
                   1315:                             }
                   1316:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1317:                         }
1.601     raeburn  1318:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1319:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1320:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1321:                             var posslinkurl = document.parmform.elements[i].value;
                   1322:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1323:                             if (document.parmform.elements['set_'+identifier].value) {
                   1324:                                 posslinkurl = ','+posslinkurl;
                   1325:                             }
                   1326:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1327:                         }
1.601     raeburn  1328:                     } else if (dlLtidRegExp.test(name)) {
                   1329:                         var identifier = name.replace(dlLtidRegExp,'');
                   1330:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1331:                             var possltid = document.parmform.elements[i].value;
                   1332:                             possltid = possltid.replace(/\D+/g,'');
                   1333:                             if (possltid.length) {
1.597     raeburn  1334:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1335:                                     possltid = ':'+possltid;
1.597     raeburn  1336:                                 }
1.601     raeburn  1337:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1338:                             } else {
                   1339:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1340:                                 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  1341:                                 return false;  
                   1342:                             }
                   1343:                         }
1.601     raeburn  1344:                     } else if (dlLticRegExp.test(name)) {
                   1345:                         var identifier = name.replace(dlLticRegExp,'');
                   1346:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1347:                             var possltic = document.parmform.elements[i].value;
                   1348:                             possltic = possltic.replace(/\D+/g,'');
                   1349:                             if (possltic.length) {
                   1350:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1351:                                     possltic = ':'+possltic;
                   1352:                                 }
                   1353:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1354:                             } else {
                   1355:                                 document.parmform.elements['set_'+identifier].value = '';
                   1356:                                 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.");
                   1357:                                 return false;
                   1358:                             }
                   1359:                         }
1.597     raeburn  1360:                     } else if (dlKeyRegExp.test(name)) {
                   1361:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1362:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1363:                             var posskey = document.parmform.elements[i].value;
                   1364:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1365:                             var origlength = posskey.length;
                   1366:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1367:                             var newlength = posskey.length;
                   1368:                             if (newlength > 0) {
                   1369:                                 var change = origlength - newlength;
                   1370:                                 if (change) {
                   1371:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1372:                                 }
                   1373:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1374:                                     posskey = ':'+posskey;
                   1375:                                 }
                   1376:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1377:                             } else {
                   1378:                                 document.parmform.elements['set_'+identifier].value = '';
                   1379:                                 if (newlength < origlength) {
                   1380:                                     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_.!@#$%^&*()+=-");
                   1381:                                 } else {
                   1382:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1383:                                 }
                   1384:                                 return false;
                   1385:                             }
                   1386:                         }
                   1387:                     } else if (dlMenusRegExp.test(name)) {
                   1388:                         if (document.parmform.elements[i].checked) {
                   1389:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1390:                             var posslinkmenu = document.parmform.elements[i].value;
                   1391:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1392:                             if (posslinkmenu == 'std') {
                   1393:                                 posslinkmenu = '0';
                   1394:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1395:                                     posslinkmenu = ','+posslinkmenu;
                   1396:                                 }
                   1397:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1398:                             }
                   1399:                         }
                   1400:                     } else if (dlCollsRegExp.test(name)) {
                   1401:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1402:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1403:                             var posslinkmenu = document.parmform.elements[i].value;
                   1404:                             if (document.parmform.elements['set_'+identifier].value) {
                   1405:                                 posslinkmenu = ','+posslinkmenu;
                   1406:                             }
                   1407:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1408:                         }
1.549     raeburn  1409:                     }
                   1410:                 }
                   1411:             }
                   1412:         }
                   1413:     }
                   1414:     return true;
                   1415: }
                   1416: 
1.597     raeburn  1417: function isRadioSet(name,expected) {
                   1418:     var menuitems = document.getElementsByName(name);
                   1419:     var radioLength = menuitems.length;
                   1420:     result = false;
                   1421:     if (radioLength  > 1) {
                   1422:         for (var j=0; j<radioLength; j++) {
                   1423:             if (menuitems[j].checked) {
                   1424:                 if (menuitems[j].value == expected) {
                   1425:                     result = true;
                   1426:                     break;
                   1427:                 }
                   1428:             }
                   1429:         }
                   1430:     }
                   1431:     return result;
                   1432: }
                   1433: 
1.549     raeburn  1434: ENDSCRIPT
                   1435: }
                   1436: 
1.561     damieng  1437: # Javascript initialization, for overview mode
1.549     raeburn  1438: sub ipacc_boxes_js  {
                   1439:     my $remove = &mt('Remove');
                   1440:     return <<"END";
                   1441: \$(document).ready(function() {
                   1442:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1443:     var add_button      = \$(".LC_add_ipacc_button");
                   1444:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1445: 
                   1446:     \$(add_button).click(function(e){
                   1447:         e.preventDefault();
                   1448:         var identifier = \$(this).closest("div").attr("id");
                   1449:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1450:         \$(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  1451:     });
                   1452: 
                   1453:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1454:         e.preventDefault(); \$(this).closest("div").remove();
                   1455:     })
                   1456: });
                   1457: 
                   1458: 
                   1459: END
                   1460: }
                   1461: 
1.561     damieng  1462: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1463: sub done_proctor_js {
1.611   ! raeburn  1464:     my $defaultdone = &mt('Done');
        !          1465:     &js_escape(\$defaultdone);
1.558     raeburn  1466:     return <<"END";
                   1467: function toggleSecret(form,radio,key) {
                   1468:     var radios = form[radio+key];
                   1469:     if (radios.length) {
                   1470:         for (var i=0; i<radios.length; i++) {
                   1471:             if (radios[i].checked) {
                   1472:                 if (radios[i].value == '_done_proctor') {
                   1473:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1474:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1475:                     }
                   1476:                 } else {
                   1477:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1478:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1479:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1480:                     }
                   1481:                 }
1.611   ! raeburn  1482:                 if (document.getElementById('done_'+key+'_buttontext')) {
        !          1483:                     if (radios[i].value == '') {
        !          1484:                         document.getElementById('done_'+key+'_buttontext').value = '';
        !          1485:                     } else {
        !          1486:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
        !          1487:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
        !          1488:                         }
        !          1489:                     }
        !          1490:                 }
1.558     raeburn  1491:             }
                   1492:         }
                   1493:     }
                   1494: }
                   1495: END
                   1496: 
                   1497: }
                   1498: 
1.588     raeburn  1499: # Javascript function toggle
                   1500: sub deeplink_js {
                   1501:     return <<"END";
                   1502: function toggleDeepLink(form,item,key) {
                   1503:     var radios = form['deeplink_'+item+'_'+key];
                   1504:     if (radios.length) {
                   1505:         var keybox;
                   1506:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1507:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1508:         }
1.601     raeburn  1509:         var divoptions = new Array();
                   1510:         if (item == 'protect') {
                   1511:             divoptions = ['ltic','ltid'];
1.597     raeburn  1512:         } else {
                   1513:             if (item == 'menus') {
1.601     raeburn  1514:                 divoptions = ['colls'];
1.597     raeburn  1515:             }
                   1516:         }
1.601     raeburn  1517:         var seldivs = new Array();
                   1518:         if ((item == 'protect') || (item == 'menus')) {
                   1519:             for (var i=0; i<divoptions.length; i++) {
                   1520:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1521:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1522:                 } else {
                   1523:                     seldivs[i] = '';
                   1524:                 }
                   1525:             }
1.588     raeburn  1526:         }
                   1527:         for (var i=0; i<radios.length; i++) {
                   1528:             if (radios[i].checked) {
1.601     raeburn  1529:                 if ((item == 'protect') || (item == 'menus')) {
                   1530:                     for (var j=0; j<seldivs.length; j++) {
                   1531:                         if (radios[i].value == divoptions[j]) {
                   1532:                             if (seldivs[j] != '') {
                   1533:                                 seldivs[j].style.display = 'inline-block';
                   1534:                             }
                   1535:                             if (item == 'protect') {
                   1536:                                 keybox.type = 'hidden';
                   1537:                                 keybox.value = '';
                   1538:                             }
                   1539:                         } else {
                   1540:                             if (seldivs[j] != '') {
                   1541:                                 seldivs[j].style.display = 'none';
                   1542:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1543:                             }
                   1544:                         }
1.597     raeburn  1545:                     }
1.601     raeburn  1546:                     if (item == 'protect') {
1.597     raeburn  1547:                         if (radios[i].value == 'key') {
                   1548:                             keybox.type = 'text';
                   1549:                         } else {
                   1550:                             keybox.type = 'hidden';
                   1551:                         }
1.588     raeburn  1552:                     }
                   1553:                 }
                   1554:             }
                   1555:         }
                   1556:     }
                   1557: }
                   1558: END
                   1559: 
                   1560: }
                   1561: 
1.561     damieng  1562: # Prints HTML page start for table mode.
                   1563: # @param {Apache2::RequestRec} $r - the Apache request
                   1564: # @param {string} $psymb - resource symb
                   1565: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1566: sub startpage {
1.531     raeburn  1567:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1568: 
1.515     raeburn  1569:     my %loaditems = (
                   1570:                       'onload'   => "group_or_section('cgroup')",
                   1571:                     );
                   1572:     if (!$psymb) {
1.523     raeburn  1573:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1574:     }
1.280     albertel 1575: 
1.560     damieng  1576:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1577:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1578:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1579:             text=>"Problem Parameters"});
1.414     droeschl 1580:     } else {
1.560     damieng  1581:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1582:             text=>"Table Mode",
                   1583:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1584:     }
1.523     raeburn  1585:     my $js = &page_js().'
                   1586: <script type="text/javascript">
                   1587: // <![CDATA[
                   1588: '.
                   1589:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1590: // ]]>
                   1591: </script>
                   1592: ';
1.446     bisitz   1593:     my $start_page =
1.523     raeburn  1594:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1595:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1596:     my $breadcrumbs =
1.473     amueller 1597:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1598:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1599:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1600:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1601:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1602:     $r->print(<<ENDHEAD);
1.193     albertel 1603: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1604: <input type="hidden" value="" name="pres_value" />
                   1605: <input type="hidden" value="" name="pres_type" />
                   1606: <input type="hidden" value="" name="pres_marker" />
                   1607: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1608: <input type="hidden" value="$escfilter" name="filter" />
                   1609: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1610: ENDHEAD
                   1611: }
                   1612: 
1.209     www      1613: 
1.561     damieng  1614: # Prints a row for table mode (except for the tr start).
                   1615: # Every time a hash reference is passed, a single entry is used, so print_row
                   1616: # could just use these values, but why make it simple when it can be complicated ?
                   1617: #
                   1618: # @param {Apache2::RequestRec} $r - the Apache request
                   1619: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1620: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1621: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1622: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1623: # @param {string} $rid - resource id
                   1624: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1625: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1626: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1627: # @param {string} $defbgone - user level and other levels background color
                   1628: # @param {string} $defbgtwo - section level background color, also used for part number
                   1629: # @param {string} $defbgthree - group level background color
                   1630: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1631: # @param {string} $uname - user name
                   1632: # @param {string} $udom - user domain
                   1633: # @param {string} $csec - section name
                   1634: # @param {string} $cgroup - group name
                   1635: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1636: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1637: # @param {boolean} $readonly - true if no editing allowed.
                   1638: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1639: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1640: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1641: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1642: sub print_row {
1.201     www      1643:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1644:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1645:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1646:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1647:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1648:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1649:     my $numlinks = 0;
1.553     raeburn  1650: 
1.560     damieng  1651:     # get the values for the parameter in cascading order
                   1652:     # empty levels will remain empty
1.44      albertel 1653:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1654:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1655:     # get the type for the parameters
                   1656:     # problem: these may not be set for all levels
1.66      www      1657:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1658:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1659:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1660:     # cascade down manually
1.182     albertel 1661:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1662:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1663:         if ($typeoutpar[$i]) {
1.66      www      1664:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1665:         } else {
1.66      www      1666:             $typeoutpar[$i]=$cascadetype;
                   1667:         }
                   1668:     }
1.57      albertel 1669:     my $parm=$$display{$which};
                   1670: 
1.203     www      1671:     if ($parmlev eq 'full') {
1.419     bisitz   1672:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1673:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1674:     } else {
1.57      albertel 1675:         $parm=~s|\[.*\]\s||g;
                   1676:     }
1.231     www      1677:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1678:     if ($automatic) {
1.560     damieng  1679:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1680:     }
1.427     bisitz   1681:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1682: 
1.44      albertel 1683:     my $thismarker=$which;
                   1684:     $thismarker=~s/^parameter\_//;
                   1685:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1686:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1687:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1688:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1689:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1690:         if ($result eq '') {
                   1691:             $recurse_check = 1;
                   1692:         } elsif (($uname ne '') && ($result > 3)) {
                   1693:             $recurse_check = 1;
                   1694:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1695:             $recurse_check = 1;
                   1696:         } elsif (($csec ne '') && ($result > 11)) {
                   1697:             $recurse_check = 1;
                   1698:         } elsif ($result > 17) {
                   1699:             $recurse_check = 1;
                   1700:         }
                   1701:         if ($recurse_check) {
                   1702:             my $what = $$part{$which}.'.'.$$name{$which};
                   1703:             my $prefix;
                   1704:             if (($uname ne '') && ($udom ne '')) {
                   1705:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1706:                 $prefix = $env{'request.course.id'};
                   1707:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1708:                 if (ref($recursinfo) eq 'ARRAY') {
                   1709:                     $effparm_rec = 1;
                   1710:                     $effparm_level = &mt('user: [_1]',$uname);
                   1711:                 }
                   1712:             }
                   1713:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1714:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1715:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1716:                 if (ref($recursinfo) eq 'ARRAY') {
                   1717:                     $effparm_rec = 1;
                   1718:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1719:                 }
                   1720:             }
                   1721:             if (($csec ne '') && (!$effparm_rec)) {
                   1722:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1723:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1724:                 if (ref($recursinfo) eq 'ARRAY') {
                   1725:                     $effparm_rec = 1;
                   1726:                     $effparm_level = &mt('section: [_1]',$csec);
                   1727:                 }
                   1728:             }
                   1729:             if (!$effparm_rec) {
                   1730:                 $prefix = $env{'request.course.id'};
                   1731:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1732:                 if (ref($recursinfo) eq 'ARRAY') {
                   1733:                     $effparm_rec = 1;
                   1734:                 }
                   1735:             }
                   1736:         }
                   1737:     }
                   1738:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1739:         $effparm_rec = 1;
                   1740:     }
                   1741:     if ((!$effparm_rec) && 
                   1742:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1743:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1744:         $effparm_rec = 1;
                   1745:     }
1.588     raeburn  1746:     if ($parmname eq 'deeplink') {
1.601     raeburn  1747:         my ($domltistr,$crsltistr);
1.588     raeburn  1748:         my %lti =
                   1749:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1750:                                             'linkprot');
1.601     raeburn  1751:         if (keys(%lti)) {
                   1752:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1753:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1754:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1755:                 }
                   1756:             }
1.601     raeburn  1757:             $domltistr =~ s/,$//;
                   1758:             if ($domltistr) {
                   1759:                 $extra = 'ltid_'.$domltistr;
                   1760:             }
1.588     raeburn  1761:         }
1.601     raeburn  1762:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1763:         if (keys(%courselti)) {
                   1764:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1765:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1766:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1767:                 }
                   1768:             }
                   1769:             $crsltistr =~ s/,$//;
                   1770:             if ($crsltistr) {
                   1771:                 if ($extra) {
                   1772:                     $extra .= '&';
                   1773:                 }
                   1774:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1775:             }
                   1776:         }
1.597     raeburn  1777:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1778:             my @colls;
                   1779:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1780:                 my ($num,$value) = split(/\%/,$item);
                   1781:                 if ($num =~ /^\d+$/) {
                   1782:                     push(@colls,$num);
                   1783:                 }
                   1784:             }
                   1785:             if (@colls) {
                   1786:                 if ($extra) {
                   1787:                     $extra .= '&';
                   1788:                 }
                   1789:                 $extra .= 'menus_'.join(',',@colls);
                   1790:             }
                   1791:         }
1.588     raeburn  1792:     }
1.57      albertel 1793:     if ($parmlev eq 'general') {
                   1794:         if ($uname) {
1.588     raeburn  1795:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1796:         } elsif ($cgroup) {
1.588     raeburn  1797:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1798:         } elsif ($csec) {
1.588     raeburn  1799:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1800:         } else {
1.588     raeburn  1801:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1802:         }
                   1803:     } elsif ($parmlev eq 'map') {
                   1804:         if ($uname) {
1.588     raeburn  1805:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1806:         } elsif ($cgroup) {
1.588     raeburn  1807:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1808:         } elsif ($csec) {
1.588     raeburn  1809:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1810:         } else {
1.588     raeburn  1811:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1812:         }
                   1813:     } else {
1.275     raeburn  1814:         if ($uname) {
                   1815:             if (@{$usersgroups} > 1) {
1.582     raeburn  1816:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1817:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1818:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1819:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1820:                     if (defined($controlgrp)) {
                   1821:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1822:                             $eff_groupparm = $grp_parm;
                   1823:                             undef($result);
                   1824:                             undef($effparm_rec);
                   1825:                             if ($grp_is_rec) {
                   1826:                                  $effparm_rec = 1;
                   1827:                             }
1.275     raeburn  1828:                         }
                   1829:                     }
                   1830:                 }
                   1831:             }
                   1832:         }
1.57      albertel 1833: 
1.588     raeburn  1834:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1835:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1836:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1837:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1838:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1839: 
                   1840:         if ($csec) {
1.588     raeburn  1841:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1842:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1843:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1844:         }
1.269     raeburn  1845: 
                   1846:         if ($cgroup) {
1.588     raeburn  1847:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1848:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1849:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1850:         }
1.446     bisitz   1851: 
1.548     raeburn  1852:         if ($uname) {
1.275     raeburn  1853:             if ($othergrp) {
                   1854:                 $r->print($othergrp);
                   1855:             }
1.588     raeburn  1856:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1857:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1858:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1859:         }
1.57      albertel 1860:     } # end of $parmlev if/else
1.582     raeburn  1861:     if (ref($recursinfo) eq 'ARRAY') {
                   1862:         my $rectitle = &mt('recursive');
                   1863:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1864:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1865:                 $rectitle = &mt('set in: [_1]','"'.
                   1866:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1867:                                                               "'$parmname','$$part{$which}'".');">'.
                   1868:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1869:               
                   1870:                 $numlinks ++;
                   1871:             }
                   1872:         }
                   1873:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1874:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1875:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1876:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1877:                   $effparm_level.'</span></td>');
                   1878:     } else {
                   1879:         if ($result) {
1.593     raeburn  1880:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1881:         }
                   1882:         if ($eff_groupparm) {
                   1883:             $effective_parm = $eff_groupparm;
                   1884:         }
                   1885:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1886:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1887:                                 '</span>':'').'</td>');
                   1888:     }
1.203     www      1889:     if ($parmlev eq 'full') {
1.136     albertel 1890:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1891:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1892:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1893:         if (!defined($sessionvaltype)) {
                   1894:             $sessionvaltype=$$defaulttype{$which};
                   1895:         }
1.419     bisitz   1896:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1897:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1898:                   '</font></td>');
1.136     albertel 1899:     }
1.44      albertel 1900:     $r->print('</tr>');
1.57      albertel 1901:     $r->print("\n");
1.582     raeburn  1902:     if (($numlinks) && (ref($reclinks))) {
                   1903:         $$reclinks = $numlinks;
                   1904:     }
1.44      albertel 1905: }
1.59      matthew  1906: 
1.561     damieng  1907: # Prints a cell for table mode.
                   1908: #
                   1909: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1910: # Also, it would make more sense to pass the display for this cell rather
                   1911: # than the full display hash and the key to use.
                   1912: #
                   1913: # @param {Apache2::RequestRec} $r - the Apache request
                   1914: # @param {integer} $which - level
                   1915: # @param {string} $defbg - cell background color
                   1916: # @param {integer} $result - the most specific level that is defined for that parameter
                   1917: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1918: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1919: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1920: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1921: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1922: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1923: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1924: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1925: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1926: sub print_td {
1.578     raeburn  1927:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1928:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1929:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1930:     $ineffect = 0;
                   1931:     $currval = $$outpar[$which];
                   1932:     $currtype = $$typeoutpar[$which];
                   1933:     $currlevel = $which;
                   1934:     if (($result) && ($result == $which)) {
                   1935:         $ineffect = 1;
                   1936:     } 
                   1937:     if ($ismaplevel) {
                   1938:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1939:             if (($result) && ($result == $which)) {
                   1940:                 $recursive = 1;
                   1941:             }
                   1942:         } elsif ($$outpar[$which+1] ne '') {
                   1943:             $recursive = 1;
                   1944:             $currlevel = $which+1;
                   1945:             $currval = $$outpar[$currlevel];
                   1946:             $currtype = $$typeoutpar[$currlevel];
                   1947:             if (($result) && ($result == $currlevel)) {
                   1948:                 $ineffect = 1;
                   1949:             }
                   1950:         }
                   1951:     }
                   1952:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1953:               ';" align="center">');
1.437     raeburn  1954:     my $nolink = 0;
1.568     raeburn  1955:     if ($readonly) {
1.552     raeburn  1956:         $nolink = 1;
1.568     raeburn  1957:     } else { 
1.578     raeburn  1958:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1959:             $nolink = 1;
1.568     raeburn  1960:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1961:             $nolink = 1;
1.568     raeburn  1962:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1963:             if ($noeditgrp) {
                   1964:                 $nolink = 1;
                   1965:             }
                   1966:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  1967:             $nolink = 1;
1.568     raeburn  1968:         } elsif ($mprefix =~ /examcode\&$/) {
                   1969:             unless ($which == 2) {
                   1970:                 $nolink = 1;
                   1971:             }
1.533     raeburn  1972:         }
1.437     raeburn  1973:     }
                   1974:     if ($nolink) {
1.577     raeburn  1975:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  1976:         $r->print(&valout($currval,$currtype));
1.114     www      1977:     } else {
1.578     raeburn  1978:         $r->print(&plink($currtype,
                   1979:                          $$display{$value},$currval,
1.588     raeburn  1980:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   1981:                          $extra));
1.114     www      1982:     }
                   1983:     $r->print('</td>'."\n");
1.57      albertel 1984: }
                   1985: 
1.561     damieng  1986: # Returns HTML and other info for the cell added when a user is selected
                   1987: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1988: #
                   1989: # @param {string} $what - parameter part.'.'.parameter name
                   1990: # @param {string} $rid - resource id
                   1991: # @param {string} $cgroup - group name
                   1992: # @param {string} $defbg - cell background color
                   1993: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1994: # @param {integer} $result - level
                   1995: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1996: # @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  1997: sub check_other_groups {
                   1998:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1999:     my $courseid = $env{'request.course.id'};
                   2000:     my $output;
                   2001:     my $symb = &symbcache($rid);
                   2002:     my $symbparm=$symb.'.'.$what;
                   2003:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2004:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2005:     my $mapparm=$map.'___(all).'.$what;
                   2006:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2007:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2008:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2009:     my $bgcolor = $defbg;
1.582     raeburn  2010:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2011:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2012:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2013:         if ($result > 3) {
1.419     bisitz   2014:             $bgcolor = '#AAFFAA';
1.275     raeburn  2015:         }
1.593     raeburn  2016:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2017:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2018:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2019:             if ($resultlevel eq 'recursive') {
                   2020:                 $resultlevel = 'map/folder';
                   2021:                 $grp_is_rec = 1;
                   2022:             }
                   2023:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2024:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2025:              
1.275     raeburn  2026:         } else {
                   2027:             $output .= '&nbsp;';
                   2028:         }
                   2029:         $output .= '</td>';
                   2030:     } else {
1.419     bisitz   2031:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2032:     }
1.582     raeburn  2033:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2034: }
                   2035: 
1.561     damieng  2036: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2037: # Used by check_other_groups.
1.561     damieng  2038: #
                   2039: # @param {string} $courseid - the course id
                   2040: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2041: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2042: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2043: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2044: # @param {string} $what - parameter part.'.'.parameter name
                   2045: # @param {hash reference} $courseopt - course parameters hash
                   2046: # @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  2047: sub parm_control_group {
1.556     raeburn  2048:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2049:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2050:     my $grpfound = 0;
1.556     raeburn  2051:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2052:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2053:     foreach my $group (@{$usersgroups}) {
                   2054:         if ($grpfound) { last; }
                   2055:         for (my $i=0; $i<@levels; $i++) {
                   2056:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2057:             if (defined($$courseopt{$item})) {
                   2058:                 $coursereply = $$courseopt{$item};
                   2059:                 $resultitem = $item;
                   2060:                 $resultgroup = $group;
                   2061:                 $resultlevel = $levelnames[$i];
                   2062:                 $resulttype = $$courseopt{$item.'.type'};
                   2063:                 $grpfound = 1;
                   2064:                 last;
                   2065:             }
                   2066:         }
                   2067:     }
                   2068:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2069: }
1.201     www      2070: 
1.63      bowersj2 2071: 
                   2072: 
1.562     damieng  2073: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2074: # All the parameters are references and are filled by the sub.
                   2075: #
1.566     damieng  2076: # @param {array reference} $ids - resource and map ids
                   2077: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2078: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2079: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2080: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2081: # @param {hash reference} $allmaps - hash map pc -> map src
                   2082: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2083: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2084: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2085: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2086: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2087: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2088: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2089: sub extractResourceInformation {
                   2090:     my $ids = shift;
                   2091:     my $typep = shift;
                   2092:     my $keyp = shift;
                   2093:     my $allparms = shift;
                   2094:     my $allparts = shift;
                   2095:     my $allmaps = shift;
                   2096:     my $mapp = shift;
                   2097:     my $symbp = shift;
1.82      www      2098:     my $maptitles=shift;
1.196     www      2099:     my $uris=shift;
1.210     www      2100:     my $keyorder=shift;
1.211     www      2101:     my $defkeytype=shift;
1.603     raeburn  2102:     my $pssymb=shift;
1.196     www      2103: 
1.210     www      2104:     my $keyordercnt=100;
1.63      bowersj2 2105: 
1.196     www      2106:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2107:     return unless(ref($navmap));
                   2108:     my @allres;
                   2109:     if ($pssymb ne '') {
                   2110:         my $res = $navmap->getBySymb($pssymb);
                   2111:         if (ref($res)) {
                   2112:             @allres = ($res);
                   2113:         }
                   2114:     }
                   2115:     if (!@allres) { 
                   2116:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2117:     }
1.196     www      2118:     foreach my $resource (@allres) {
1.480     amueller 2119:         my $id=$resource->id();
1.196     www      2120:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2121:         if ($mapid eq '0') { next; }
                   2122:         $$ids[$#$ids+1]=$id;
                   2123:         my $srcf=$resource->src();
                   2124:         $srcf=~/\.(\w+)$/;
                   2125:         $$typep{$id}=$1;
1.584     raeburn  2126:         my $toolsymb;
                   2127:         if ($srcf =~ /ext\.tool$/) {
                   2128:             $toolsymb = $resource->symb();
                   2129:         }
1.480     amueller 2130:         $$keyp{$id}='';
1.196     www      2131:         $$uris{$id}=$srcf;
1.512     foxr     2132: 
1.584     raeburn  2133:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2134:             next if ($key!~/^parameter_/);
1.363     albertel 2135: 
1.209     www      2136: # Hidden parameters
1.584     raeburn  2137:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2138: #
                   2139: # allparms is a hash of parameter names
                   2140: #
1.584     raeburn  2141:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2142:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2143:                 my ($display,$parmdis);
                   2144:                 $display = &standard_parameter_names($name);
                   2145:                 if ($display eq '') {
1.584     raeburn  2146:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2147:                     $parmdis = $display;
                   2148:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2149:                 } else {
                   2150:                     $parmdis = &mt($display);
                   2151:                 }
                   2152:                 $$allparms{$name}=$parmdis;
                   2153:                 if (ref($defkeytype)) {
                   2154:                     $$defkeytype{$name}=
1.584     raeburn  2155:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2156:                 }
                   2157:             }
1.363     albertel 2158: 
1.209     www      2159: #
                   2160: # allparts is a hash of all parts
                   2161: #
1.584     raeburn  2162:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2163:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2164: #
                   2165: # Remember all keys going with this resource
                   2166: #
1.480     amueller 2167:             if ($$keyp{$id}) {
                   2168:                 $$keyp{$id}.=','.$key;
                   2169:             } else {
                   2170:                 $$keyp{$id}=$key;
                   2171:             }   
1.210     www      2172: #
                   2173: # Put in order
1.446     bisitz   2174: #
1.480     amueller 2175:             unless ($$keyorder{$key}) {
                   2176:                 $$keyorder{$key}=$keyordercnt;
                   2177:                 $keyordercnt++;
                   2178:             }
1.473     amueller 2179:         }
                   2180: 
                   2181: 
1.480     amueller 2182:         if (!exists($$mapp{$mapid})) {
                   2183:             $$mapp{$id}=
                   2184:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2185:             $$mapp{$mapid}=$$mapp{$id};
                   2186:             $$allmaps{$mapid}=$$mapp{$id};
                   2187:             if ($mapid eq '1') {
1.532     raeburn  2188:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2189:             } else {
                   2190:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2191:             }
                   2192:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2193:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2194:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2195:                                                      # are commented out in rev. 1.57
1.473     amueller 2196:         } else {
1.480     amueller 2197:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2198:         }
1.480     amueller 2199:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2200:     }
                   2201: }
                   2202: 
1.582     raeburn  2203: sub get_recursive {
                   2204:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2205:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2206:         foreach my $item (@{$recurseup}) {
                   2207:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2208:             if (defined($resdata->{$norecursechk})) {
                   2209:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2210:                     my $type = $resdata->{$norecursechk.'.type'};
                   2211:                     return [$resdata->{$norecursechk},$type,$item];
                   2212:                 } else {
                   2213:                     last;
                   2214:                 }
                   2215:             }
                   2216:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2217:             if (defined($resdata->{$recursechk})) {
                   2218:                 my $type = $resdata->{$recursechk.'.type'};
                   2219:                 return [$resdata->{$recursechk},$type,$item];
                   2220:             }
                   2221:         }
                   2222:     }
                   2223:     return;
                   2224: }
                   2225: 
1.208     www      2226: 
1.562     damieng  2227: # Tells if a parameter type is a date.
                   2228: #
                   2229: # @param {string} type - parameter type
                   2230: # @returns{boolean} - true if it is a date
1.213     www      2231: sub isdateparm {
                   2232:     my $type=shift;
                   2233:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2234: }
                   2235: 
1.589     raeburn  2236: # Determine if parameter type is specialized string type (i.e.,
                   2237: # not just string or string_yesno.  
                   2238: 
                   2239: sub is_specialstring {
                   2240:     my $type=shift;
1.603     raeburn  2241:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2242: }
                   2243: 
1.562     damieng  2244: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2245: #
1.581     raeburn  2246: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2247: sub parmmenu {
1.581     raeburn  2248:     my ($r)=@_;
1.208     www      2249:     $r->print(<<ENDSCRIPT);
                   2250: <script type="text/javascript">
1.454     bisitz   2251: // <![CDATA[
1.208     www      2252:     function checkall(value, checkName) {
1.453     schualex 2253: 
                   2254:         var li = "_li";
                   2255:         var displayOverview = "";
                   2256:         
                   2257:         if (value == false) {
                   2258:             displayOverview = "none"
                   2259:         }
                   2260: 
1.562     damieng  2261:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2262:             ele = document.forms.parmform.elements[i];
                   2263:             if (ele.name == checkName) {
                   2264:                 document.forms.parmform.elements[i].checked=value;
                   2265:             }
                   2266:         }
                   2267:     }
1.210     www      2268: 
                   2269:     function checkthis(thisvalue, checkName) {
1.562     damieng  2270:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2271:             ele = document.forms.parmform.elements[i];
                   2272:             if (ele.name == checkName) {
1.562     damieng  2273:                 if (ele.value == thisvalue) {
                   2274:                     document.forms.parmform.elements[i].checked=true;
                   2275:                 }
1.210     www      2276:             }
                   2277:         }
                   2278:     }
                   2279: 
                   2280:     function checkdates() {
1.562     damieng  2281:         checkthis('duedate','pscat');
                   2282:         checkthis('opendate','pscat');
                   2283:         checkthis('answerdate','pscat');
1.218     www      2284:     }
                   2285: 
                   2286:     function checkdisset() {
1.562     damieng  2287:         checkthis('discussend','pscat');
                   2288:         checkthis('discusshide','pscat');
                   2289:         checkthis('discussvote','pscat');
1.218     www      2290:     }
                   2291: 
                   2292:     function checkcontdates() {
1.562     damieng  2293:         checkthis('contentopen','pscat');
                   2294:         checkthis('contentclose','pscat');
1.218     www      2295:     }
1.446     bisitz   2296: 
1.210     www      2297:     function checkvisi() {
1.562     damieng  2298:         checkthis('hiddenresource','pscat');
                   2299:         checkthis('encrypturl','pscat');
                   2300:         checkthis('problemstatus','pscat');
                   2301:         checkthis('contentopen','pscat');
                   2302:         checkthis('opendate','pscat');
1.210     www      2303:     }
                   2304: 
                   2305:     function checkparts() {
1.562     damieng  2306:         checkthis('hiddenparts','pscat');
                   2307:         checkthis('display','pscat');
                   2308:         checkthis('ordered','pscat');
1.210     www      2309:     }
                   2310: 
                   2311:     function checkstandard() {
                   2312:         checkall(false,'pscat');
1.562     damieng  2313:         checkdates();
                   2314:         checkthis('weight','pscat');
                   2315:         checkthis('maxtries','pscat');
                   2316:         checkthis('type','pscat');
                   2317:         checkthis('problemstatus','pscat');
1.210     www      2318:     }
                   2319: 
1.454     bisitz   2320: // ]]>
1.208     www      2321: </script>
                   2322: ENDSCRIPT
1.453     schualex 2323: 
1.491     bisitz   2324:     $r->print('<hr />');
1.581     raeburn  2325:     &shortCuts($r);
1.491     bisitz   2326:     $r->print('<hr />');
1.453     schualex 2327: }
1.562     damieng  2328: 
                   2329: # Returns parameter categories.
                   2330: #
                   2331: # @returns {hash} - category name -> title in English
1.465     amueller 2332: sub categories {
                   2333:     return ('time_settings' => 'Time Settings',
                   2334:     'grading' => 'Grading',
                   2335:     'tries' => 'Tries',
                   2336:     'problem_appearance' => 'Problem Appearance',
                   2337:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2338:     'hiding' => 'Hiding',
                   2339:     'high_level_randomization' => 'High Level Randomization',
                   2340:     'slots' => 'Slots',
                   2341:     'file_submission' => 'File Submission',
                   2342:     'misc' => 'Miscellaneous' ); 
                   2343: }
                   2344: 
1.562     damieng  2345: # Returns the category for each parameter.
                   2346: #
                   2347: # @returns {hash} - parameter name -> category name
1.465     amueller 2348: sub lookUpTableParameter {
                   2349:  
                   2350:     return ( 
                   2351:         'opendate' => 'time_settings',
                   2352:         'duedate' => 'time_settings',
                   2353:         'answerdate' => 'time_settings',
                   2354:         'interval' => 'time_settings',
                   2355:         'contentopen' => 'time_settings',
                   2356:         'contentclose' => 'time_settings',
                   2357:         'discussend' => 'time_settings',
1.560     damieng  2358:         'printstartdate' => 'time_settings',
                   2359:         'printenddate' => 'time_settings',
1.465     amueller 2360:         'weight' => 'grading',
                   2361:         'handgrade' => 'grading',
                   2362:         'maxtries' => 'tries',
                   2363:         'hinttries' => 'tries',
1.503     raeburn  2364:         'randomizeontries' => 'tries',
1.465     amueller 2365:         'type' => 'problem_appearance',
                   2366:         'problemstatus' => 'problem_appearance',
                   2367:         'display' => 'problem_appearance',
                   2368:         'ordered' => 'problem_appearance',
                   2369:         'numbubbles' => 'problem_appearance',
                   2370:         'tol' => 'behaviour_of_input_fields',
                   2371:         'sig' => 'behaviour_of_input_fields',
                   2372:         'turnoffunit' => 'behaviour_of_input_fields',
                   2373:         'hiddenresource' => 'hiding',
                   2374:         'hiddenparts' => 'hiding',
                   2375:         'discusshide' => 'hiding',
                   2376:         'buttonshide' => 'hiding',
                   2377:         'turnoffeditor' => 'hiding',
                   2378:         'encrypturl' => 'hiding',
1.587     raeburn  2379:         'deeplink' => 'hiding',
1.465     amueller 2380:         'randomorder' => 'high_level_randomization',
                   2381:         'randompick' => 'high_level_randomization',
                   2382:         'available' => 'slots',
                   2383:         'useslots' => 'slots',
                   2384:         'availablestudent' => 'slots',
                   2385:         'uploadedfiletypes' => 'file_submission',
                   2386:         'maxfilesize' => 'file_submission',
                   2387:         'cssfile' => 'misc',
                   2388:         'mapalias' => 'misc',
                   2389:         'acc' => 'misc',
                   2390:         'maxcollaborators' => 'misc',
                   2391:         'scoreformat' => 'misc',
1.514     raeburn  2392:         'lenient' => 'grading',
1.519     raeburn  2393:         'retrypartial' => 'tries',
1.521     raeburn  2394:         'discussvote'  => 'misc',
1.584     raeburn  2395:         'examcode' => 'high_level_randomization',
1.575     raeburn  2396:     );
1.465     amueller 2397: }
                   2398: 
1.562     damieng  2399: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2400: #
                   2401: # @param {string} $name - parameter name
                   2402: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2403: sub whatIsMyCategory {
                   2404:     my $name = shift;
                   2405:     my $catList = shift;
                   2406:     my @list;
                   2407:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2408:     my $cat = $lookUpList{$name};
                   2409:     if (defined($cat)) {
                   2410:         if (!defined($$catList{$cat})){
                   2411:             push @list, ($name);
                   2412:             $$catList{$cat} = \@list;
                   2413:         } else {
                   2414:             push @{${$catList}{$cat}}, ($name);     
                   2415:         }
                   2416:     } else {
                   2417:         if (!defined($$catList{'misc'})){
                   2418:             push @list, ($name);
                   2419:             $$catList{'misc'} = \@list;
                   2420:         } else {
                   2421:             push @{${$catList}{'misc'}}, ($name);     
                   2422:         }
                   2423:     }        
                   2424: }
                   2425: 
1.562     damieng  2426: # Sorts parameter names based on appearance order.
                   2427: #
                   2428: # @param {array reference} name - array reference of parameter names
                   2429: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2430: # @returns {Array} - array of parameter names
1.465     amueller 2431: sub keysindisplayorderCategory {
                   2432:     my ($name,$keyorder)=@_;
                   2433:     return sort {
1.473     amueller 2434:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2435:     } ( @{$name});
                   2436: }
                   2437: 
1.562     damieng  2438: # Returns a hash category name -> order, starting at 1 (integer)
                   2439: #
                   2440: # @returns {hash}
1.467     amueller 2441: sub category_order {
                   2442:     return (
                   2443:         'time_settings' => 1,
                   2444:         'grading' => 2,
                   2445:         'tries' => 3,
                   2446:         'problem_appearance' => 4,
                   2447:         'hiding' => 5,
                   2448:         'behaviour_of_input_fields' => 6,
                   2449:         'high_level_randomization'  => 7,
                   2450:         'slots' => 8,
                   2451:         'file_submission' => 9,
                   2452:         'misc' => 10
                   2453:     );
                   2454: 
                   2455: }
1.453     schualex 2456: 
1.562     damieng  2457: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2458: #
                   2459: # @param {Apache2::RequestRec} $r - the Apache request
                   2460: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2461: # @param {array reference} $pscat - list of selected parameter names
                   2462: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2463: sub parmboxes {
                   2464:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2465:     my %categories = &categories();
1.467     amueller 2466:     my %category_order = &category_order();
1.465     amueller 2467:     my %categoryList = (
                   2468:         'time_settings' => [],
                   2469:         'grading' => [],
                   2470:         'tries' => [],
                   2471:         'problem_appearance' => [],
                   2472:         'behaviour_of_input_fields' => [],
                   2473:         'hiding' => [],
                   2474:         'high_level_randomization' => [],
                   2475:         'slots' => [],
                   2476:         'file_submission' => [],
                   2477:         'misc' => [],
1.489     bisitz   2478:     );
1.510     www      2479: 
1.548     raeburn  2480:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2481:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2482:     }
1.453     schualex 2483:     #part to print the parm-list
1.536     raeburn  2484:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2485:         next if (@{$categoryList{$key}} == 0);
                   2486:         next if ($key eq '');
                   2487:         $r->print('<div class="LC_Box LC_400Box">'
                   2488:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2489:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2490:             next if ($tempkey eq '');
1.536     raeburn  2491:             $r->print('<span class="LC_nobreak">'
                   2492:                      .'<label><input type="checkbox" name="pscat" '
                   2493:                      .'value="'.$tempkey.'" ');
                   2494:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2495:                 $r->print( ' checked="checked"');
                   2496:             }
                   2497:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2498:                                                       : $tempkey)
1.536     raeburn  2499:                      .'</label></span><br />'."\n");
1.465     amueller 2500:         }
1.536     raeburn  2501:         $r->print('</div>');
1.465     amueller 2502:     }
1.536     raeburn  2503:     $r->print("\n");
1.453     schualex 2504: }
1.562     damieng  2505: 
                   2506: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2507: #
1.562     damieng  2508: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2509: sub shortCuts {
1.581     raeburn  2510:     my ($r)=@_;
1.453     schualex 2511: 
1.491     bisitz   2512:     # Parameter Selection
                   2513:     $r->print(
                   2514:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2515:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2516:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2517:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2518:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2519:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2520:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2521:        .&Apache::lonhtmlcommon::end_funclist()
                   2522:     );
                   2523: 
                   2524:     # Add Selection for...
                   2525:     $r->print(
                   2526:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2527:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2528:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2529:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2530:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2531:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2532:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2533:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2534:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2535:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2536:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2537:        .&Apache::lonhtmlcommon::end_funclist()
                   2538:     );
1.208     www      2539: }
                   2540: 
1.562     damieng  2541: # Prints HTML to select parts to view (except for the title).
                   2542: # Used by table and overview modes.
                   2543: #
                   2544: # @param {Apache2::RequestRec} $r - the Apache request
                   2545: # @param {hash reference} $allparts - hash parameter part -> part title
                   2546: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2547: sub partmenu {
1.446     bisitz   2548:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2549:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2550:     if ($selsize > 8) {
                   2551:         $selsize = 8;
                   2552:     }
1.446     bisitz   2553: 
1.523     raeburn  2554:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2555:     $r->print('<option value="all"');
1.562     damieng  2556:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2557:     $r->print('>'.&mt('All Parts').'</option>');
                   2558:     my %temphash=();
                   2559:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2560:     foreach my $tempkey (sort {
1.560     damieng  2561:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2562:             } keys(%{$allparts})) {
                   2563:         unless ($tempkey =~ /\./) {
                   2564:             $r->print('<option value="'.$tempkey.'"');
                   2565:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2566:                 $r->print(' selected="selected"');
                   2567:             }
                   2568:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2569:         }
1.208     www      2570:     }
1.446     bisitz   2571:     $r->print('</select>');
1.209     www      2572: }
                   2573: 
1.562     damieng  2574: # Prints HTML to select a user and/or a group.
                   2575: # Used by table mode.
                   2576: #
                   2577: # @param {Apache2::RequestRec} $r - the Apache request
                   2578: # @param {string} $uname - selected user name
                   2579: # @param {string} $id - selected Student/Employee ID
                   2580: # @param {string} $udom - selected user domain
                   2581: # @param {string} $csec - selected section name
                   2582: # @param {string} $cgroup - selected group name
                   2583: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2584: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2585: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2586: sub usermenu {
1.553     raeburn  2587:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2588:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2589:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2590:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2591: function setCourseadv(form,caller) {
                   2592:     if (caller.value == 'st') {
                   2593:         form.courseadv.value = 'none';
                   2594:     } else {
                   2595:         form.courseadv.value = '';
                   2596:     }
                   2597:     return;
                   2598: }
                   2599: ENDJS
1.412     bisitz   2600: 
1.596     raeburn  2601:     my (%chkroles,$stuonly,$courseadv);
                   2602:     if ($env{'form.userroles'} eq 'any') {
                   2603:         $chkroles{'any'} = ' checked="checked"';
                   2604:     } else {
                   2605:         $chkroles{'st'} = ' checked="checked"';
                   2606:         $courseadv = 'none';
                   2607:     }
                   2608:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2609:     if ($crstype eq 'Community') {
                   2610:         $stuonly = &mt('member only');
                   2611:     } else {
                   2612:         $stuonly = &mt('student only');
                   2613:     }
                   2614:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2615:                   &mt("User's role").':&nbsp;'.
                   2616:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2617:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2618:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2619:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2620:     my $sections='';
1.300     albertel 2621:     my %sectionhash = &Apache::loncommon::get_sections();
                   2622: 
1.269     raeburn  2623:     my $groups;
1.553     raeburn  2624:     my %grouphash;
                   2625:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2626:         %grouphash = &Apache::longroup::coursegroups();
                   2627:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2628:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2629:     }
1.299     albertel 2630: 
1.412     bisitz   2631:     my $g_s_header='';
                   2632:     my $g_s_footer='';
1.446     bisitz   2633: 
1.552     raeburn  2634:     my $currsec = $env{'request.course.sec'};
                   2635:     if ($currsec) {
                   2636:         $sections=&mt('Section:').' '.$currsec;
                   2637:         if (%grouphash) {
                   2638:             $sections .= ';'.('&nbsp;' x2);
                   2639:         }
                   2640:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2641:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2642:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2643:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2644:         }
                   2645:         $sections .= '>';
1.548     raeburn  2646:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2647:         $sections.='<option value="'.$section.'" '.
                   2648:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2649:                                                               '</option>';
1.209     www      2650:         }
                   2651:         $sections.='</select>';
1.269     raeburn  2652:     }
1.412     bisitz   2653: 
1.552     raeburn  2654:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2655:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2656:         $sections .= qq|
                   2657: <script type="text/javascript">
1.454     bisitz   2658: // <![CDATA[
1.269     raeburn  2659: function group_or_section(caller) {
                   2660:    if (caller == "cgroup") {
                   2661:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2662:            document.parmform.csec.selectedIndex = 0;
                   2663:        }
                   2664:    } else {
                   2665:        if (document.parmform.csec.selectedIndex != 0) {
                   2666:            document.parmform.cgroup.selectedIndex = 0;
                   2667:        }
                   2668:    }
                   2669: }
1.454     bisitz   2670: // ]]>
1.269     raeburn  2671: </script>
                   2672: |;
1.554     raeburn  2673:     } else {
1.269     raeburn  2674:         $sections .= qq|
                   2675: <script type="text/javascript">
1.454     bisitz   2676: // <![CDATA[
1.269     raeburn  2677: function group_or_section(caller) {
                   2678:     return;
                   2679: }
1.454     bisitz   2680: // ]]>
1.269     raeburn  2681: </script>
                   2682: |;
1.446     bisitz   2683:     }
1.299     albertel 2684: 
                   2685:     if (%grouphash) {
1.597     raeburn  2686:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2687:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2688:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2689:         }
                   2690:         $groups .= '>';
1.548     raeburn  2691:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2692:             $groups.='<option value="'.$grp.'" ';
                   2693:             if ($grp eq $cgroup) {
                   2694:                 unless ((defined($uname)) && ($grp eq '')) {
                   2695:                     $groups .=  'selected="selected" ';
                   2696:                 }
                   2697:             } elsif (!defined($cgroup)) {
                   2698:                 if (@{$usersgroups} == 1) {
                   2699:                     if ($grp eq $$usersgroups[0]) {
                   2700:                         $groups .=  'selected="selected" ';
                   2701:                     }
                   2702:                 }
                   2703:             }
                   2704:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2705:         }
                   2706:         $groups.='</select>';
                   2707:     }
1.412     bisitz   2708: 
1.445     neumanie 2709:     if (%sectionhash || %grouphash) {
1.446     bisitz   2710:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2711:         $r->print($sections.$groups);
1.448     bisitz   2712:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2713:     } else {
                   2714:         $r->print($sections); 
1.445     neumanie 2715:     }
1.446     bisitz   2716: 
                   2717:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2718:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2719:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2720:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2721:                  ,$chooseopt));
1.209     www      2722: }
                   2723: 
1.562     damieng  2724: # Prints HTML to select parameters from a list of all parameters.
                   2725: # Uses parmmenu and parmboxes.
                   2726: # Used by table and overview modes.
1.468     amueller 2727: #
1.562     damieng  2728: # @param {Apache2::RequestRec} $r - the Apache request
                   2729: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2730: # @param {array reference} $pscat - list of selected parameter names
                   2731: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2732: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2733: sub displaymenu {
1.581     raeburn  2734:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2735: 
1.445     neumanie 2736:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2737:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2738: 
1.581     raeburn  2739:     &parmmenu($r);
1.536     raeburn  2740:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2741:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2742:     $r->print(&Apache::loncommon::end_scrollbox());
                   2743: 
                   2744:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2745:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2746:  
1.209     www      2747: }
                   2748: 
1.562     damieng  2749: # Prints HTML to select a map.
                   2750: # Used by table mode and overview mode.
                   2751: #
                   2752: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2753: # @param {hash reference} $allmaps - hash map pc -> map src
                   2754: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2755: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2756: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2757: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2758: sub mapmenu {
1.610     raeburn  2759:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2760:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2761:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2762:     my $tree=[];
                   2763:     my $treeinfo={};
                   2764:     if (defined($navmap)) {
1.499     raeburn  2765:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2766:         my $curRes;
                   2767:         my $depth = 0;
1.468     amueller 2768:         my %parent = ();
                   2769:         my $startcount = 5;
                   2770:         my $lastcontainer = $startcount;
                   2771: # preparing what is to show ...
1.461     neumanie 2772:         while ($curRes = $it->next()) {
                   2773:             if ($curRes == $it->BEGIN_MAP()) {
                   2774:                 $depth++;
1.468     amueller 2775:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2776:             }
                   2777:             if ($curRes == $it->END_MAP()) {
                   2778:                 $depth--;
1.468     amueller 2779:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2780:             }
                   2781:             if (ref($curRes)) {
1.468     amueller 2782:                 my $symb = $curRes->symb();
                   2783:                 my $ressymb = $symb;
1.461     neumanie 2784:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2785:                     my $type = 'sequence';
                   2786:                     if ($curRes->is_page()) {
                   2787:                         $type = 'page';
                   2788:                     }
                   2789:                     my $id= $curRes->id();
1.468     amueller 2790:                     my $srcf = $curRes->src();
                   2791:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2792:                     if(!exists($treeinfo->{$id})) {
                   2793:                         push(@$tree,$id);
1.473     amueller 2794:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2795:                         $treeinfo->{$id} = {
1.461     neumanie 2796:                                     depth => $depth,
                   2797:                                     type  => $type,
1.468     amueller 2798:                                     name  => $resource_name,
                   2799:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2800:                                     };
1.462     neumanie 2801:                     }
1.461     neumanie 2802:                 }
                   2803:             }
                   2804:         }
1.462     neumanie 2805:     }
1.473     amueller 2806: # Show it ...    
1.610     raeburn  2807:     my $rowattr = ' id="mapmenu"';
                   2808:     if ($parmlev eq 'general') {
                   2809:         $rowattr .= ' style="display:none"';
                   2810:     }
                   2811:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2812:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2813:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2814:         my $whitespace =
                   2815:             '<img src="'
                   2816:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2817:            .'" alt="" />';
                   2818: 
1.498     bisitz   2819:         # Info about selectable folders/maps
                   2820:         $r->print(
                   2821:             '<div class="LC_info">'
1.508     www      2822:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2823:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2824:            .'</div>'
                   2825:         );
                   2826: 
1.536     raeburn  2827:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2828:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2829: 
1.498     bisitz   2830:         # Display row: "All Maps or Folders"
                   2831:         $r->print(
1.523     raeburn  2832:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2833:            .'<td>'
                   2834:            .'<label>'
                   2835:            .'<input type="radio" name="pschp"'
1.497     bisitz   2836:         );
                   2837:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2838:         $r->print(
                   2839:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2840:            .&mt('All Maps or Folders')
                   2841:            .'</label>'
                   2842:            .'<hr /></td>'
                   2843:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2844:         );
1.497     bisitz   2845: 
1.532     raeburn  2846:         # Display row: "Main Content"
1.468     amueller 2847:         if (exists($$allmaps{1})) {
1.498     bisitz   2848:             $r->print(
                   2849:                 &Apache::loncommon::start_data_table_row()
                   2850:                .'<td>'
                   2851:                .'<label>'
                   2852:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2853:             );
1.497     bisitz   2854:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2855:             $r->print(
                   2856:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2857:                .$$maptitles{1}
                   2858:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2859:                .'</label>'
                   2860:                .'</td>'
                   2861:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2862:             );
                   2863:         }
1.497     bisitz   2864: 
                   2865:         # Display rows for all course maps and folders
1.468     amueller 2866:         foreach my $id (@{$tree}) {
                   2867:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2868:             # Indentation
1.468     amueller 2869:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2870:             my $indent;
                   2871:             for (my $i = 0; $i < $depth; $i++) {
                   2872:                 $indent.= $whitespace;
                   2873:             }
1.461     neumanie 2874:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2875:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2876:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2877:             }
1.468     amueller 2878:             my $symb_name = $$symbp{$id};
                   2879:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2880:             $symb_name = $tail;
1.498     bisitz   2881:             $r->print(
                   2882:                 &Apache::loncommon::start_data_table_row()
                   2883:                .'<td>'
                   2884:                .'<label>'
1.463     bisitz   2885:             );
1.498     bisitz   2886:             # Only offer radio button for folders/maps which can be parameterized
                   2887:             if ($allmaps_inverted{$symb_name}) {
                   2888:                 $r->print(
                   2889:                     '<input type ="radio" name="pschp"'
                   2890:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2891:                 );
                   2892:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2893:                 $r->print('/>');
                   2894:             } else {
                   2895:                 $r->print($whitespace);
1.461     neumanie 2896:             }
1.498     bisitz   2897:             $r->print(
                   2898:                 $indent.$icon.'&nbsp;'
                   2899:                .$treeinfo->{$id}->{name}
                   2900:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2901:                .'</label>'
                   2902:                .'</td>'
                   2903:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2904:             );
1.461     neumanie 2905:         }
1.497     bisitz   2906: 
1.523     raeburn  2907:         $r->print(&Apache::loncommon::end_data_table().
                   2908:                   '<br style="line-height:2px;" />'.
                   2909:                   &Apache::loncommon::end_scrollbox());
1.209     www      2910:     }
                   2911: }
                   2912: 
1.563     damieng  2913: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2914: # Used by table and overview modes.
                   2915: #
                   2916: # @param {Apache2::RequestRec} $r - the Apache request
                   2917: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2918: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2919: sub levelmenu {
1.446     bisitz   2920:     my ($r,$alllevs,$parmlev)=@_;
                   2921: 
1.548     raeburn  2922:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2923:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2924:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2925:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2926:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2927:         if ($parmlev eq $$alllevs{$lev}) {
                   2928:             $r->print(' selected="selected"');
                   2929:         }
                   2930:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2931:     }
1.446     bisitz   2932:     $r->print("</select>");
1.208     www      2933: }
                   2934: 
1.211     www      2935: 
1.563     damieng  2936: # Returns HTML to select a section (with a select HTML element).
                   2937: # Used by overview mode.
                   2938: #
                   2939: # @param {array reference} $selectedsections - list of selected section ids
                   2940: # @returns {string}
1.211     www      2941: sub sectionmenu {
1.553     raeburn  2942:     my ($selectedsections)=@_;
1.300     albertel 2943:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2944:     return '' if (!%sectionhash);
1.300     albertel 2945: 
1.552     raeburn  2946:     my (@possibles,$disabled);
                   2947:     if ($env{'request.course.sec'} ne '') {
                   2948:         @possibles = ($env{'request.course.sec'});
                   2949:         $selectedsections = [$env{'request.course.sec'}];
                   2950:         $disabled = ' disabled="disabled"';
                   2951:     } else {
                   2952:         @possibles = ('all',sort(keys(%sectionhash)));
                   2953:     }
1.553     raeburn  2954:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2955:     foreach my $s (@possibles) {
1.553     raeburn  2956:         $output .= '    <option value="'.$s.'"';
                   2957:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2958:             $output .= ' selected="selected"';
1.473     amueller 2959:         }
1.553     raeburn  2960:         $output .= '>'."$s</option>\n";
1.300     albertel 2961:     }
1.553     raeburn  2962:     $output .= "</select>\n";
                   2963:     return $output;
1.269     raeburn  2964: }
                   2965: 
1.563     damieng  2966: # Returns HTML to select a group (with a select HTML element).
                   2967: # Used by overview mode.
                   2968: #
                   2969: # @param {array reference} $selectedgroups - list of selected group names
                   2970: # @returns {string}
1.269     raeburn  2971: sub groupmenu {
1.553     raeburn  2972:     my ($selectedgroups)=@_;
                   2973:     my %grouphash;
                   2974:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2975:         %grouphash = &Apache::longroup::coursegroups();
                   2976:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2977:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2978:     }
                   2979:     return '' if (!%grouphash);
1.299     albertel 2980: 
1.553     raeburn  2981:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2982:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2983:         $output .= '    <option value="'.$group.'"';
                   2984:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2985:             $output .=  ' selected="selected"';
1.473     amueller 2986:         }
1.553     raeburn  2987:         $output .= '>'."$group</option>\n";
1.211     www      2988:     }
1.553     raeburn  2989:     $output .= "</select>\n";
                   2990:     return $output;
1.211     www      2991: }
                   2992: 
1.563     damieng  2993: # Returns an array with the given parameter split by comma.
                   2994: # Used by assessparms (table mode).
                   2995: #
                   2996: # @param {string} $keyp - the string to split
                   2997: # @returns {Array<string>}
1.210     www      2998: sub keysplit {
                   2999:     my $keyp=shift;
                   3000:     return (split(/\,/,$keyp));
                   3001: }
                   3002: 
1.563     damieng  3003: # Returns the keys in $name, sorted using $keyorder.
                   3004: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3005: # Used by assessparms (table mode) for resource level.
                   3006: #
                   3007: # @param {hash reference} $name - parameter key -> parameter name
                   3008: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3009: # @returns {Array<string>}
1.210     www      3010: sub keysinorder {
                   3011:     my ($name,$keyorder)=@_;
                   3012:     return sort {
1.560     damieng  3013:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3014:     } (keys(%{$name}));
1.210     www      3015: }
                   3016: 
1.563     damieng  3017: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3018: # Used by assessparms (table mode) for map and general levels.
                   3019: #
                   3020: # @param {hash reference} $name - parameter key -> parameter name
                   3021: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3022: # @returns {Array<string>}
1.236     albertel 3023: sub keysinorder_bytype {
                   3024:     my ($name,$keyorder)=@_;
                   3025:     return sort {
1.563     damieng  3026:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3027:         my $tb=(split('_',$b))[-1];
                   3028:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3029:             return ($a cmp $b);
                   3030:         }
                   3031:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3032:     } (keys(%{$name}));
1.236     albertel 3033: }
                   3034: 
1.563     damieng  3035: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3036: # Used by defaultsetter (parameter settings default actions).
                   3037: #
                   3038: # @param {hash reference} $name - hash parameter name -> parameter title
                   3039: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3040: # @returns {Array<string>}
1.211     www      3041: sub keysindisplayorder {
                   3042:     my ($name,$keyorder)=@_;
                   3043:     return sort {
1.560     damieng  3044:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3045:     } (keys(%{$name}));
1.211     www      3046: }
                   3047: 
1.563     damieng  3048: # Prints HTML with a choice to sort results by realm or student first.
                   3049: # Used by overview mode.
                   3050: #
                   3051: # @param {Apache2::RequestRec} $r - the Apache request
                   3052: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3053: # @param {string} $context - newoverview|overview
1.214     www      3054: sub sortmenu {
1.608     raeburn  3055:     my ($r,$sortorder,$context)=@_;
                   3056:     my %text;
                   3057:     if ($context eq 'newoverview') {
                   3058:         %text = &Apache::lonlocal::texthash (
                   3059:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3060:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3061:         );
                   3062:     } else {
                   3063:         %text = &Apache::lonlocal::texthash (
                   3064:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3065:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3066:         );
1.214     www      3067:     }
1.608     raeburn  3068:     my %sortchecked = (
                   3069:        realmstudent => ' checked="checked"',
                   3070:        studentrealm => '',
                   3071:     );
1.214     www      3072:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3073:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3074:         $sortchecked{'realmstudent'} = '';
                   3075:     }
                   3076:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3077:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3078:                   $text{$sorttype}.'</label>');
1.214     www      3079:     }
                   3080: }
                   3081: 
1.563     damieng  3082: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3083: #
                   3084: # @returns {hash}
1.211     www      3085: sub standardkeyorder {
                   3086:     return ('parameter_0_opendate' => 1,
1.473     amueller 3087:         'parameter_0_duedate' => 2,
                   3088:         'parameter_0_answerdate' => 3,
                   3089:         'parameter_0_interval' => 4,
                   3090:         'parameter_0_weight' => 5,
                   3091:         'parameter_0_maxtries' => 6,
                   3092:         'parameter_0_hinttries' => 7,
                   3093:         'parameter_0_contentopen' => 8,
                   3094:         'parameter_0_contentclose' => 9,
                   3095:         'parameter_0_type' => 10,
                   3096:         'parameter_0_problemstatus' => 11,
                   3097:         'parameter_0_hiddenresource' => 12,
                   3098:         'parameter_0_hiddenparts' => 13,
                   3099:         'parameter_0_display' => 14,
                   3100:         'parameter_0_ordered' => 15,
                   3101:         'parameter_0_tol' => 16,
                   3102:         'parameter_0_sig' => 17,
                   3103:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3104:         'parameter_0_discussend' => 19,
                   3105:         'parameter_0_discusshide' => 20,
                   3106:         'parameter_0_discussvote' => 21,
1.560     damieng  3107:         'parameter_0_printstartdate'  =>  22,
                   3108:         'parameter_0_printenddate' =>  23);
1.211     www      3109: }
                   3110: 
1.59      matthew  3111: 
1.560     damieng  3112: # Table mode UI.
1.563     damieng  3113: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3114: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3115: #
                   3116: # Parameters used from the request:
                   3117: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3118: # cgroup - selected group
                   3119: # command - 'set': direct access to table mode for a resource
                   3120: # csec - selected section
                   3121: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3122: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3123: # id - student/employee ID
                   3124: # parmlev - selected level (full|map|general)
                   3125: # part - selected part (unused ?)
                   3126: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3127: # pres_type - &&&-separated parameter types
                   3128: # pres_value - &&&-separated parameter values
                   3129: # prevvisit - '1' if the user has submitted the form before
                   3130: # pscat (multiple values) - selected parameter names
1.566     damieng  3131: # pschp - selected map pc, or 'all'
1.563     damieng  3132: # psprt (multiple values) - list of selected parameter parts
                   3133: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3134: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3135: # symb - resource symb (when a single resource is selected)
                   3136: # udom - selected user domain
                   3137: # uname - selected user name
                   3138: # url - used only with command 'set', the resource url
                   3139: #
                   3140: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3141: # @param $parm_permission - ref to hash of permissions
                   3142: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3143: sub assessparms {
1.1       www      3144: 
1.568     raeburn  3145:     my ($r,$parm_permission) = @_;
1.201     www      3146: 
1.512     foxr     3147: 
                   3148: # -------------------------------------------------------- Variable declaration
1.566     damieng  3149:     my @ids=(); # resource and map ids
                   3150:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3151:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3152:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3153:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3154:     my %uris=(); # hash resource/map id -> resource src
                   3155:     my %maptitles=(); # hash map pc or src -> map title
                   3156:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3157:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3158:     my %alllevs=(); # hash English level title -> value
                   3159: 
                   3160:     my $uname; # selected user name
                   3161:     my $udom; # selected user domain
                   3162:     my $uhome; # server with the user's files, or 'no_host'
                   3163:     my $csec; # selected section name
                   3164:     my $cgroup; # selected group name
                   3165:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3166:     my $numreclinks = 0;
1.446     bisitz   3167: 
1.190     albertel 3168:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3169: 
1.57      albertel 3170:     $alllevs{'Resource Level'}='full';
1.215     www      3171:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3172:     $alllevs{'Course Level'}='general';
                   3173: 
1.563     damieng  3174:     my %allparms; # hash parameter name -> parameter title
                   3175:     my %allparts; # hash parameter part -> part title
1.512     foxr     3176: # ------------------------------------------------------------------------------
                   3177: 
1.210     www      3178: #
                   3179: # Order in which these parameters will be displayed
                   3180: #
1.211     www      3181:     my %keyorder=&standardkeyorder();
                   3182: 
1.512     foxr     3183: #    @ids=();
                   3184: #    %symbp=();       # These seem defined above already.
                   3185: #    %typep=();
1.43      albertel 3186: 
                   3187:     my $message='';
                   3188: 
1.190     albertel 3189:     $csec=$env{'form.csec'};
1.552     raeburn  3190:     if ($env{'request.course.sec'} ne '') {
                   3191:         $csec = $env{'request.course.sec'};    
                   3192:     }
                   3193: 
1.553     raeburn  3194: # Check group privs.
1.269     raeburn  3195:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3196:     my $noeditgrp; 
                   3197:     if ($cgroup ne '') {
                   3198:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3199:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3200:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3201:                 $noeditgrp = 1;
                   3202:             }
                   3203:         }
                   3204:     }
1.188     www      3205: 
1.190     albertel 3206:     if      ($udom=$env{'form.udom'}) {
                   3207:     } elsif ($udom=$env{'request.role.domain'}) {
                   3208:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3209:     } else {
1.473     amueller 3210:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3211:     }
1.468     amueller 3212:     
1.43      albertel 3213: 
1.134     albertel 3214:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3215:     my $pschp=$env{'form.pschp'};
1.506     www      3216: 
                   3217: 
1.134     albertel 3218:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3219:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3220:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3221: 
1.43      albertel 3222:     my $pssymb='';
1.57      albertel 3223:     my $parmlev='';
1.446     bisitz   3224: 
1.190     albertel 3225:     unless ($env{'form.parmlev'}) {
1.57      albertel 3226:         $parmlev = 'map';
                   3227:     } else {
1.190     albertel 3228:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3229:     }
1.26      www      3230: 
1.29      www      3231: # ----------------------------------------------- Was this started from grades?
                   3232: 
1.560     damieng  3233:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3234:             (!$env{'form.dis'})) {
1.473     amueller 3235:         my $url=$env{'form.url'};
                   3236:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3237:         $pssymb=&Apache::lonnet::symbread($url);
                   3238:         if (!@pscat) { @pscat=('all'); }
                   3239:         $pschp='';
1.57      albertel 3240:         $parmlev = 'full';
1.190     albertel 3241:     } elsif ($env{'form.symb'}) {
1.473     amueller 3242:         $pssymb=$env{'form.symb'};
                   3243:         if (!@pscat) { @pscat=('all'); }
                   3244:         $pschp='';
1.57      albertel 3245:         $parmlev = 'full';
1.43      albertel 3246:     } else {
1.473     amueller 3247:         $env{'form.url'}='';
1.43      albertel 3248:     }
                   3249: 
1.190     albertel 3250:     my $id=$env{'form.id'};
1.43      albertel 3251:     if (($id) && ($udom)) {
1.555     raeburn  3252:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3253:         if ($uname) {
                   3254:             $id='';
                   3255:         } else {
                   3256:             $message=
1.540     bisitz   3257:                 '<p class="LC_warning">'.
                   3258:                 &mt('Unknown ID [_1] at domain [_2]',
                   3259:                     "'".$id."'","'".$udom."'").
                   3260:                 '</p>';
1.473     amueller 3261:         }
1.43      albertel 3262:     } else {
1.473     amueller 3263:         $uname=$env{'form.uname'};
1.43      albertel 3264:     }
                   3265:     unless ($udom) { $uname=''; }
                   3266:     $uhome='';
                   3267:     if ($uname) {
1.473     amueller 3268:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3269:         if ($uhome eq 'no_host') {
1.473     amueller 3270:             $message=
1.540     bisitz   3271:                 '<p class="LC_warning">'.
                   3272:                 &mt('Unknown user [_1] at domain [_2]',
                   3273:                     "'".$uname."'","'".$udom."'").
                   3274:                 '</p>';
1.473     amueller 3275:             $uname='';
1.12      www      3276:         } else {
1.473     amueller 3277:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3278:                           $env{'request.course.id'});
                   3279:             if ($csec eq '-1') {
1.596     raeburn  3280:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3281:                 if ($env{'form.userroles'} eq 'any') {
                   3282:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3283:                         $csec = $env{'request.course.sec'};
                   3284:                         $message = '<span class="LC_info">';
                   3285:                         if ($crstype eq 'Community') {
                   3286:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3287:                                             $uname,$udom);
                   3288:                         } else {
                   3289:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3290:                                             $uname,$udom);
                   3291:                         }
                   3292:                         $message .= '</span>';
                   3293:                     } else {
                   3294:                         my @possroles = ('in','ep','ta','cr');
                   3295:                         if ($crstype eq 'Community') {
                   3296:                             unshift(@possroles,'co');
                   3297:                         } else {
                   3298:                             unshift(@possroles,'cc');
                   3299:                         }
                   3300:                         my %not_student_roles =
                   3301:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3302:                                                           \@possroles,[$udom],1,1);
                   3303:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3304:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3305:                         my %sections_by_role;
                   3306:                         foreach my $role (keys(%not_student_roles)) {
                   3307:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3308:                                 my ($rolename,$sec) = ($1,$2);
                   3309:                                 if ($rolename =~ m{^cr/}) {
                   3310:                                     $rolename = 'cr';
                   3311:                                 }
                   3312:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3313:                             }
                   3314:                         }
                   3315:                         my $numroles = scalar(keys(%sections_by_role));
                   3316:                         if ($numroles) {
                   3317:                             foreach my $role (@possroles) {
                   3318:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3319:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3320:                                     $csec = $secs[0];
                   3321:                                     last;
                   3322:                                 }
                   3323:                             }
                   3324:                         }
                   3325:                         if ($csec eq '-1') {
                   3326:                             $message = '<span class="LC_warning">';
                   3327:                             if ($crstype eq 'Community') {
                   3328:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3329:                                                 $uname,$udom);
                   3330:                             } else {
                   3331:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3332:                                                 $uname,$udom);
                   3333:                             }
                   3334:                             $message .= '</span>';
                   3335:                             $uname='';
                   3336:                             if ($env{'request.course.sec'} ne '') {
                   3337:                                 $csec=$env{'request.course.sec'};
                   3338:                             } else {
                   3339:                                 $csec=$env{'form.csec'};
                   3340:                             }
                   3341:                             $cgroup=$env{'form.cgroup'};
                   3342:                         } else {
                   3343:                             $message = '<span class="LC_info">';
                   3344:                             if ($crstype eq 'Community') {
                   3345:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3346:                                          $uname,$udom);
                   3347:                             } else {
                   3348:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3349:                                                 $uname,$udom);
                   3350:                             }
                   3351:                             $message .= '</span>';
                   3352:                         }
                   3353:                     }
1.594     raeburn  3354:                 } else {
1.596     raeburn  3355:                     $message = '<span class="LC_warning">';
                   3356:                     if ($crstype eq 'Community') {
                   3357:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3358:                                          $uname,$udom);
                   3359:                     } else {
                   3360:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3361:                                          $uname,$udom);
                   3362:                     }
                   3363:                     $message .= '</span>';
                   3364:                     $uname='';
                   3365:                     if ($env{'request.course.sec'} ne '') {
                   3366:                         $csec=$env{'request.course.sec'};
                   3367:                     } else {
                   3368:                         $csec=$env{'form.csec'};
                   3369:                     }
                   3370:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3371:                 }
                   3372:             } elsif ($env{'request.course.sec'} ne '') {
                   3373:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3374:                     $message='<span class="LC_warning">'.
1.594     raeburn  3375:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3376:                                   $uname,$udom,$env{'request.course.sec'}).
                   3377:                               '</span>';
                   3378:                     $uname='';
                   3379:                     $csec=$env{'request.course.sec'};
                   3380:                 }
1.269     raeburn  3381:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3382:             }
                   3383:             if ($uname ne '') {
1.473     amueller 3384:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3385:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3386:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3387:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3388:                             .$name{'lastname'}.' '.$name{'generation'}
                   3389:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3390:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3391:                                    $udom,$uname,$env{'request.course.id'});
                   3392:                 if (@usersgroups > 0) {
                   3393:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3394:                         $cgroup = $usersgroups[0];
                   3395:                     }
                   3396:                 } else {
                   3397:                     $cgroup = '';
1.297     raeburn  3398:                 }
1.269     raeburn  3399:             }
1.12      www      3400:         }
1.43      albertel 3401:     }
1.2       www      3402: 
1.43      albertel 3403:     unless ($csec) { $csec=''; }
1.269     raeburn  3404:     unless ($cgroup) { $cgroup=''; }
1.12      www      3405: 
1.14      www      3406: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3407:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3408:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3409:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3410: 
1.582     raeburn  3411:     %allmaps_inverted = reverse(%allmaps);
                   3412: 
1.57      albertel 3413:     $mapp{'0.0'} = '';
                   3414:     $symbp{'0.0'} = '';
1.99      albertel 3415: 
1.14      www      3416: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3417:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3418:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3419:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3420:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3421:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3422:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3423:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3424:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3425:         my $totalstored = 0;
1.605     raeburn  3426:         my $totalskippeduser = 0;
1.546     raeburn  3427:         my $now = time;
1.473     amueller 3428:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3429:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3430:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3431:                 next if ($csec ne $env{'request.course.sec'});
                   3432:             }
1.556     raeburn  3433:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3434:                 next if ($noeditgrp);
1.605     raeburn  3435:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3436:                 if ($uname eq '') {
                   3437:                     $totalskippeduser ++;
                   3438:                     next;
                   3439:                 }
1.557     raeburn  3440:             }
                   3441:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3442:                 $namematch = 'maplevelrecurse';
                   3443:             }
1.556     raeburn  3444:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3445:                 my (@ok_slots,@fail_slots,@del_slots);
                   3446:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3447:                 my ($level,@all) =
                   3448:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3449:                                      $csec,$cgroup,$courseopt);
                   3450:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3451:                     next if ($slot_name eq '');
                   3452:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3453:                         push(@ok_slots,$slot_name);
                   3454: 
                   3455:                     } else {
                   3456:                         push(@fail_slots,$slot_name);
                   3457:                     }
                   3458:                 }
                   3459:                 if (@ok_slots) {
                   3460:                     $values[$i] = join(':',@ok_slots);
                   3461:                 } else {
                   3462:                     $values[$i] = '';
                   3463:                 }
                   3464:                 if ($all[$level] ne '') {
                   3465:                     my @existing = split(/:/,$all[$level]);
                   3466:                     foreach my $slot_name (@existing) {
                   3467:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3468:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3469:                                 push(@del_slots,$slot_name);
                   3470:                             }
                   3471:                         }
                   3472:                     }
                   3473:                 }
1.554     raeburn  3474:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3475:                 $name = $1;
1.533     raeburn  3476:                 my $val = $values[$i];
1.549     raeburn  3477:                 my $valmatch = '';
1.533     raeburn  3478:                 if ($name eq 'examcode') {
1.544     raeburn  3479:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3480:                         $val = 'valid';
                   3481:                     }
1.546     raeburn  3482:                 } elsif ($name eq 'printstartdate') {
                   3483:                     if ($val =~ /^\d+$/) {
                   3484:                         if ($val > $now) {
                   3485:                             $val = 'future';
                   3486:                         }
                   3487:                     } 
                   3488:                 } elsif ($name eq 'printenddate') {
                   3489:                     if ($val =~ /^\d+$/) {
                   3490:                         if ($val < $now) {
                   3491:                             $val = 'past';
                   3492:                         }
                   3493:                     }
1.549     raeburn  3494:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3495:                     my $stringtype = &get_stringtype($name);
                   3496:                     my $stringmatch = &standard_string_matches($stringtype);
                   3497:                     if (ref($stringmatch) eq 'ARRAY') {
                   3498:                         foreach my $item (@{$stringmatch}) {
                   3499:                             if (ref($item) eq 'ARRAY') {
                   3500:                                 my ($regexpname,$pattern) = @{$item};
                   3501:                                 if ($pattern ne '') {
                   3502:                                     if ($val =~ /$pattern/) {
                   3503:                                         $valmatch = $regexpname;
                   3504:                                         $val = '';
                   3505:                                         last;
                   3506:                                     }
                   3507:                                 }
                   3508:                             }
                   3509:                         }
                   3510:                     }
1.554     raeburn  3511:                 } elsif ($name eq 'interval') {
                   3512:                     my $intervaltype = &get_intervaltype($name);
                   3513:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3514:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3515:                         foreach my $item (@{$intervalmatch}) {
                   3516:                             if (ref($item) eq 'ARRAY') {
                   3517:                                 my ($regexpname,$pattern) = @{$item};
                   3518:                                 if ($pattern ne '') {
                   3519:                                     if ($val =~ /$pattern/) {
                   3520:                                         $valmatch = $regexpname;
                   3521:                                         $val = '';
                   3522:                                         last;
                   3523:                                     }
                   3524:                                 }
                   3525:                             }
                   3526:                         }
                   3527:                     }
1.533     raeburn  3528:                 }
1.504     raeburn  3529:                 $needsrelease =
1.557     raeburn  3530:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3531:                 if ($needsrelease) {
1.505     raeburn  3532:                     unless ($got_chostname) {
1.514     raeburn  3533:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3534:                         $got_chostname = 1;
1.546     raeburn  3535:                     } 
1.557     raeburn  3536:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3537:                                                           $needsrelease,
                   3538:                                                           $cmajor,$cminor);
1.500     raeburn  3539:                 }
1.437     raeburn  3540:             }
1.504     raeburn  3541:             if ($needsnewer) {
1.557     raeburn  3542:                 undef($namematch);
                   3543:             } else {
                   3544:                 my $currneeded;
                   3545:                 if ($needsrelease) {
                   3546:                     $currneeded = $needsrelease;
                   3547:                 }
                   3548:                 if ($namematch) {
                   3549:                     $needsrelease =
                   3550:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3551:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3552:                         unless ($got_chostname) {
                   3553:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3554:                             $got_chostname = 1;
                   3555:                         }
                   3556:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3557:                                                               $needsrelease,
                   3558:                                                               $cmajor,$cminor);
                   3559:                     } else {
                   3560:                         undef($namematch);
                   3561:                     }
                   3562:                 }
                   3563:             }
                   3564:             if ($needsnewer) {
                   3565:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3566:                                                 $cminor,$needsrelease);
                   3567:             } else {
                   3568:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3569:                                      $values[$i],
                   3570:                                      $types[$i],
                   3571:                                      $uname,$udom,$csec,$cgroup);
                   3572:                 $totalstored ++;
                   3573:             }
1.473     amueller 3574:         }
1.68      www      3575: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3576:         if ($totalstored) {
                   3577:             $message.='<p class="LC_warning">'
1.605     raeburn  3578:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3579:                      .'<br />'
1.504     raeburn  3580:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3581:                      .&Apache::loncommon::help_open_topic('Caching')
                   3582:                      .'</p>';
1.605     raeburn  3583:         } else {
                   3584:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3585:         }
                   3586:         if ($totalskippeduser) {
                   3587:             $message .= '<p class="LC_warning">';
                   3588:             if ($uhome eq 'no_host') {
                   3589:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3590:                                 $totalskippeduser);
                   3591:             } elsif ($env{'form.userroles'} eq 'any') {
                   3592:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3593:                                 $totalskippeduser);
                   3594:             } else {
                   3595:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3596:                                 $totalskippeduser);
                   3597:             }
                   3598:             $message .= '</p>';
1.504     raeburn  3599:         }
1.68      www      3600:     }
1.584     raeburn  3601: 
1.57      albertel 3602: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3603:     if ($pscat[0] eq "all") {
                   3604:         @pscat = (keys(%allparms));
                   3605:     }
                   3606:     if (!@pscat) {
                   3607:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3608:     };
                   3609:     if ($psprt[0] eq "all" || !@psprt) {
                   3610:         @psprt = (keys(%allparts));
                   3611:     }
1.2       www      3612: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3613: 
1.531     raeburn  3614:     my $crstype = &Apache::loncommon::course_type();
                   3615:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3616: 
1.548     raeburn  3617:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3618:             'date_interval','int','float','string','string_lenient',
                   3619:             'string_examcode','string_deeplink','string_discussvote',
                   3620:             'string_useslots','string_problemstatus','string_ip',
                   3621:             'string_questiontype') {
1.473     amueller 3622:         $r->print('<input type="hidden" value="'.
1.563     damieng  3623:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3624:             '" name="recent_'.$item.'" />');
1.44      albertel 3625:     }
1.446     bisitz   3626: 
1.459     bisitz   3627:     # ----- Start Parameter Selection
                   3628: 
1.606     raeburn  3629:     # Hide parm selection and possibly table?
                   3630:     my ($tablejs,$tabledivsty);
                   3631:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3632:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3633:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3634:         $tabledivsty = ' style="display:none"';
                   3635:     }
1.459     bisitz   3636:     $r->print(<<ENDPARMSELSCRIPT);
                   3637: <script type="text/javascript">
                   3638: // <![CDATA[
                   3639: function parmsel_show() {
1.562     damieng  3640:     document.getElementById('parmsel').style.display = "";
                   3641:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3642:     $tablejs
1.459     bisitz   3643: }
                   3644: // ]]>
                   3645: </script>
                   3646: ENDPARMSELSCRIPT
1.474     amueller 3647:     
1.445     neumanie 3648:     if (!$pssymb) {
1.563     damieng  3649:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3650:         my $parmselhiddenstyle=' style="display:none"';
                   3651:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3652:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3653:         } else  {
                   3654:            $r->print('<div id="parmsel">');
                   3655:         }
                   3656: 
1.491     bisitz   3657:         # Step 1
1.523     raeburn  3658:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3659:         $r->print('
1.474     amueller 3660: <script type="text/javascript">
1.523     raeburn  3661: // <![CDATA['.
                   3662:                  &showhide_js().'
1.474     amueller 3663: // ]]>
                   3664: </script>
1.523     raeburn  3665: ');
                   3666:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3667:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3668:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3669:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3670:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3671:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3672:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3673:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3674:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3675: 
                   3676:         # Step 2
1.523     raeburn  3677:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3678:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3679: 
                   3680:         # Step 3
1.523     raeburn  3681:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3682:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3683:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3684:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3685:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3686: 
                   3687:         # Update Display Button
1.486     www      3688:         $r->print('<p>'
                   3689:              .'<input type="submit" name="dis"'
1.511     www      3690:              .' value="'.&mt('Update Display').'" />'
1.486     www      3691:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3692:              .'</p>');
                   3693:         $r->print('</div>');
1.491     bisitz   3694: 
1.486     www      3695:         # Offer link to display parameter selection again
                   3696:         $r->print('<p id="parmsellink"');
                   3697:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3698:            $r->print($parmselhiddenstyle);
                   3699:         }
                   3700:         $r->print('>'
                   3701:              .'<a href="javascript:parmsel_show()">'
                   3702:              .&mt('Change Parameter Selection')
                   3703:              .'</a>'
                   3704:              .'</p>');
1.44      albertel 3705:     } else {
1.478     amueller 3706:         # parameter screen for a single resource. 
1.486     www      3707:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3708:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3709:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3710:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3711:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3712:                   '<br />');
                   3713:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3714:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3715:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3716:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3717:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3718:         $r->print('<p>'
1.459     bisitz   3719:              .'<input type="submit" name="dis"'
1.511     www      3720:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3721:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3722:              .'</p>');
1.459     bisitz   3723:     }
1.478     amueller 3724:     
1.486     www      3725:     # ----- End Parameter Selection
1.57      albertel 3726: 
1.459     bisitz   3727:     # Display Messages
                   3728:     $r->print('<div>'.$message.'</div>');
1.210     www      3729: 
1.57      albertel 3730: 
                   3731:     my @temp_pscat;
                   3732:     map {
                   3733:         my $cat = $_;
                   3734:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3735:     } @pscat;
                   3736: 
                   3737:     @pscat = @temp_pscat;
                   3738: 
1.548     raeburn  3739: 
1.209     www      3740:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3741: # ----------------------------------------------------------------- Start Table
1.57      albertel 3742:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3743:         my $csuname=$env{'user.name'};
                   3744:         my $csudom=$env{'user.domain'};
1.568     raeburn  3745:         my $readonly = 1;
                   3746:         if ($parm_permission->{'edit'}) {
                   3747:             undef($readonly); 
                   3748:         }
1.606     raeburn  3749:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3750: 
1.203     www      3751:         if ($parmlev eq 'full') {
1.506     www      3752: #
                   3753: # This produces the cascading table output of parameters
                   3754: #
1.578     raeburn  3755:             my $coursespan=$csec?8:5;
                   3756:             my $userspan=3;
1.560     damieng  3757:             if ($cgroup ne '') {
1.578     raeburn  3758:                 $coursespan += 3;
1.560     damieng  3759:             }
1.473     amueller 3760: 
1.560     damieng  3761:             $r->print(&Apache::loncommon::start_data_table());
                   3762:             #
                   3763:             # This produces the headers
                   3764:             #
                   3765:             $r->print('<tr><td colspan="5"></td>');
                   3766:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3767:             if ($uname) {
1.473     amueller 3768:                 if (@usersgroups > 1) {
1.560     damieng  3769:                     $userspan ++;
                   3770:                 }
                   3771:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3772:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3773:             }
                   3774:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3775:                 'pie'    => "Parameter in Effect",
                   3776:                 'csv'    => "Current Session Value",
1.472     amueller 3777:                 'rl'     => "Resource Level",
1.473     amueller 3778:                 'ic'     => 'in Course',
                   3779:                 'aut'    => "Assessment URL and Title",
                   3780:                 'type'   => 'Type',
                   3781:                 'emof'   => "Enclosing Map or Folder",
                   3782:                 'part'   => 'Part',
1.472     amueller 3783:                 'pn'     => 'Parameter Name',
1.473     amueller 3784:                 'def'    => 'default',
                   3785:                 'femof'  => 'from Enclosing Map or Folder',
                   3786:                 'gen'    => 'general',
                   3787:                 'foremf' => 'for Enclosing Map or Folder',
                   3788:                 'fr'     => 'for Resource'
                   3789:             );
1.560     damieng  3790:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3791: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3792: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3793: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3794: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3795: 
1.10      www      3796: ENDTABLETWO
1.560     damieng  3797:             if ($csec) {
1.578     raeburn  3798:                 $r->print('<th colspan="3">'.
1.560     damieng  3799:                 &mt("in Section")." $csec</th>");
                   3800:             }
                   3801:             if ($cgroup) {
1.578     raeburn  3802:                 $r->print('<th colspan="3">'.
1.472     amueller 3803:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3804:             }
                   3805:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3806: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3807: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3808: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3809: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3810: ENDTABLEHEADFOUR
1.57      albertel 3811: 
1.560     damieng  3812:             if ($csec) {
1.578     raeburn  3813:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3814:             }
1.473     amueller 3815: 
1.560     damieng  3816:             if ($cgroup) {
1.578     raeburn  3817:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3818:             }
                   3819: 
                   3820:             if ($uname) {
                   3821:                 if (@usersgroups > 1) {
                   3822:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3823:                 }
1.578     raeburn  3824:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3825:             }
                   3826: 
                   3827:             $r->print('</tr>');
1.506     www      3828: #
                   3829: # Done with the headers
                   3830: # 
1.560     damieng  3831:             my $defbgone='';
                   3832:             my $defbgtwo='';
                   3833:             my $defbgthree = '';
1.57      albertel 3834: 
1.560     damieng  3835:             foreach my $rid (@ids) {
1.57      albertel 3836: 
                   3837:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3838:                 if ((!$pssymb &&
1.560     damieng  3839:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3840:                         ||
                   3841:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3842: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3843:                     if ($defbgone eq '#E0E099') {
                   3844:                         $defbgone='#E0E0DD';
1.57      albertel 3845:                     } else {
1.419     bisitz   3846:                         $defbgone='#E0E099';
1.57      albertel 3847:                     }
1.419     bisitz   3848:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3849:                         $defbgtwo='#FFFFDD';
1.57      albertel 3850:                     } else {
1.473     amueller 3851:                         $defbgtwo='#FFFF99';
1.57      albertel 3852:                     }
1.419     bisitz   3853:                     if ($defbgthree eq '#FFBB99') {
                   3854:                         $defbgthree='#FFBBDD';
1.269     raeburn  3855:                     } else {
1.419     bisitz   3856:                         $defbgthree='#FFBB99';
1.269     raeburn  3857:                     }
                   3858: 
1.57      albertel 3859:                     my $thistitle='';
                   3860:                     my %name=   ();
                   3861:                     undef %name;
                   3862:                     my %part=   ();
                   3863:                     my %display=();
                   3864:                     my %type=   ();
                   3865:                     my %default=();
1.196     www      3866:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3867:                     my $toolsymb;
                   3868:                     if ($uri =~ /ext\.tool$/) {
                   3869:                         $toolsymb = $symbp{$rid};
                   3870:                     }
1.57      albertel 3871: 
1.506     www      3872:                     my $filter=$env{'form.filter'};
1.548     raeburn  3873:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3874:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3875:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3876:     # We may only want certain parameters listed
                   3877:                             if ($filter) {
                   3878:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3879:                             }
                   3880:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3881:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3882: 
1.584     raeburn  3883:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3884:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3885:                                 my $identifier;
                   3886:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3887:                                     $identifier = $1;
                   3888:                                 }
                   3889:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3890:                             } else {
                   3891:                                 $display{$tempkeyp} = $parmdis;
                   3892:                             }
                   3893:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3894:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3895:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3896:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3897:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3898:                         }
                   3899:                     }
1.548     raeburn  3900:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3901:                     if ($totalparms>0) {
1.560     damieng  3902:                         my $firstrow=1;
1.473     amueller 3903:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3904:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3905:                         my @recurseup;
                   3906:                         if (ref($navmap) && $mapp{$rid}) {
                   3907:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3908:                         }
1.419     bisitz   3909:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3910:                              ' rowspan='.$totalparms.
1.419     bisitz   3911:                              '><tt><font size="-1">'.
1.57      albertel 3912:                              join(' / ',split(/\//,$uri)).
                   3913:                              '</font></tt><p><b>'.
1.154     albertel 3914:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3915:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3916:                           &escape($symbp{$rid}).
1.336     albertel 3917:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3918:                              " target=\"_self\">$title");
1.57      albertel 3919: 
                   3920:                         if ($thistitle) {
1.473     amueller 3921:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3922:                         }
                   3923:                         $r->print('</a></b></td>');
1.419     bisitz   3924:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3925:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3926:                                       '</td>');
                   3927: 
1.419     bisitz   3928:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3929:                                       ' rowspan='.$totalparms.
1.238     www      3930:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3931:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3932:                             unless ($firstrow) {
                   3933:                                 $r->print('<tr>');
                   3934:                             } else {
                   3935:                                 undef $firstrow;
                   3936:                             }
1.548     raeburn  3937:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3938:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3939:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3940:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3941:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3942:                                        \$numreclinks);
1.57      albertel 3943:                         }
                   3944:                     }
                   3945:                 }
                   3946:             } # end foreach ids
1.43      albertel 3947: # -------------------------------------------------- End entry for one resource
1.517     www      3948:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3949:         } # end of  full
1.57      albertel 3950: #--------------------------------------------------- Entry for parm level map
                   3951:         if ($parmlev eq 'map') {
1.419     bisitz   3952:             my $defbgone = '#E0E099';
                   3953:             my $defbgtwo = '#FFFF99';
                   3954:             my $defbgthree = '#FFBB99';
1.57      albertel 3955: 
                   3956:             my %maplist;
                   3957: 
                   3958:             if ($pschp eq 'all') {
1.446     bisitz   3959:                 %maplist = %allmaps;
1.57      albertel 3960:             } else {
                   3961:                 %maplist = ($pschp => $mapp{$pschp});
                   3962:             }
                   3963: 
                   3964: #-------------------------------------------- for each map, gather information
                   3965:             my $mapid;
1.607     raeburn  3966:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 3967:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3968: 
                   3969: #-----------------------  loop through ids and get all parameter types for map
                   3970: #-----------------------------------------          and associated information
                   3971:                 my %name = ();
                   3972:                 my %part = ();
                   3973:                 my %display = ();
                   3974:                 my %type = ();
                   3975:                 my %default = ();
                   3976:                 my $map = 0;
                   3977: 
1.473     amueller 3978: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3979: 
1.548     raeburn  3980:                 foreach my $id (@ids) {
                   3981:                     ($map)=($id =~ /([\d]*?)\./);
                   3982:                     my $rid = $id;
1.446     bisitz   3983: 
1.57      albertel 3984: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3985: 
1.560     damieng  3986:                     if ($map eq $mapid) {
1.473     amueller 3987:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3988:                         my $toolsymb;
                   3989:                         if ($uri =~ /ext\.tool$/) {
                   3990:                             $toolsymb = $symbp{$rid};
                   3991:                         }
1.582     raeburn  3992: 
1.57      albertel 3993: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3994: 
                   3995: #--------------------------------------------------------------------
                   3996: # @catmarker contains list of all possible parameters including part #s
                   3997: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3998: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3999: # When storing information, store as part 0
                   4000: # When requesting information, request from full part
                   4001: #-------------------------------------------------------------------
1.548     raeburn  4002:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4003:                             my $tempkeyp = $fullkeyp;
                   4004:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4005: 
1.548     raeburn  4006:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4007:                                 $part{$tempkeyp}="0";
1.584     raeburn  4008:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4009:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4010:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4011:                                     my $identifier;
                   4012:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4013:                                         $identifier = $1;
                   4014:                                     }
                   4015:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4016:                                 } else {
                   4017:                                     $display{$tempkeyp} = $parmdis;
                   4018:                                 }
                   4019:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4020:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4021:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4022:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4023:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4024:                               }
                   4025:                         } # end loop through keys
1.560     damieng  4026:                     }
1.57      albertel 4027:                 } # end loop through ids
1.446     bisitz   4028: 
1.57      albertel 4029: #---------------------------------------------------- print header information
1.133     www      4030:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4031:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4032:                 my $tmp="";
1.57      albertel 4033:                 if ($uname) {
1.473     amueller 4034:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4035:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4036:                         &mt('in')." \n";
1.57      albertel 4037:                 } else {
1.401     bisitz   4038:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4039:                 }
1.269     raeburn  4040:                 if ($cgroup) {
1.401     bisitz   4041:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4042:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4043:                     $csec = '';
                   4044:                 } elsif ($csec) {
1.401     bisitz   4045:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4046:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4047:                 }
1.401     bisitz   4048:                 $r->print('<div align="center"><h4>'
                   4049:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4050:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4051:                              ,$tmp
                   4052:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4053:                              )
                   4054:                          ."<br /></h4>\n"
1.422     bisitz   4055:                 );
1.57      albertel 4056: #---------------------------------------------------------------- print table
1.419     bisitz   4057:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4058:                          .&Apache::loncommon::start_data_table_header_row()
                   4059:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4060:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4061:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4062:                          .&Apache::loncommon::end_data_table_header_row()
                   4063:                 );
1.57      albertel 4064: 
1.582     raeburn  4065:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4066:                 my @recurseup;
                   4067:                 if (ref($navmap)) {
                   4068:                      my $mapres = $navmap->getByMapPc($mapid);
                   4069:                      if (ref($mapres)) {
                   4070:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4071:                      }
                   4072:                 }
                   4073: 
                   4074: 
1.548     raeburn  4075:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4076:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4077:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4078:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4079:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4080:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4081:                            \$numreclinks);
1.57      albertel 4082:                 }
1.422     bisitz   4083:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4084:                          .'</div>'
                   4085:                 );
1.57      albertel 4086:             } # end each map
                   4087:         } # end of $parmlev eq map
                   4088: #--------------------------------- Entry for parm level general (Course level)
                   4089:         if ($parmlev eq 'general') {
1.473     amueller 4090:             my $defbgone = '#E0E099';
1.419     bisitz   4091:             my $defbgtwo = '#FFFF99';
                   4092:             my $defbgthree = '#FFBB99';
1.57      albertel 4093: 
                   4094: #-------------------------------------------- for each map, gather information
                   4095:             my $mapid="0.0";
                   4096: #-----------------------  loop through ids and get all parameter types for map
                   4097: #-----------------------------------------          and associated information
                   4098:             my %name = ();
                   4099:             my %part = ();
                   4100:             my %display = ();
                   4101:             my %type = ();
                   4102:             my %default = ();
1.446     bisitz   4103: 
1.548     raeburn  4104:             foreach $id (@ids) {
                   4105:                 my $rid = $id;
1.446     bisitz   4106: 
1.196     www      4107:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4108:                 my $toolsymb;
                   4109:                 if ($uri =~ /ext\.tool$/) {
                   4110:                     $toolsymb = $symbp{$rid};
                   4111:                 }
1.57      albertel 4112: 
                   4113: #--------------------------------------------------------------------
                   4114: # @catmarker contains list of all possible parameters including part #s
                   4115: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4116: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4117: # When storing information, store as part 0
                   4118: # When requesting information, request from full part
                   4119: #-------------------------------------------------------------------
1.548     raeburn  4120:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4121:                     my $tempkeyp = $fullkeyp;
                   4122:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4123:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4124:                         $part{$tempkeyp}="0";
1.584     raeburn  4125:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4126:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4127:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4128:                             my $identifier;
                   4129:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4130:                                 $identifier = $1;
                   4131:                             }
                   4132:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4133:                         } else {
                   4134:                             $display{$tempkeyp} = $parmdis;
                   4135:                         }
                   4136:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4137:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4138:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4139:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4140:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4141:                     }
1.57      albertel 4142:                 } # end loop through keys
                   4143:             } # end loop through ids
1.446     bisitz   4144: 
1.57      albertel 4145: #---------------------------------------------------- print header information
1.473     amueller 4146:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4147:             $r->print(<<ENDMAPONE);
1.419     bisitz   4148: <center>
                   4149: <h4>$setdef
1.135     albertel 4150: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4151: ENDMAPONE
                   4152:             if ($uname) {
1.473     amueller 4153:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4154:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4155:             } else {
1.135     albertel 4156:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4157:             }
1.446     bisitz   4158: 
1.135     albertel 4159:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4160:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4161:             $r->print("</h4>\n");
1.57      albertel 4162: #---------------------------------------------------------------- print table
1.419     bisitz   4163:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4164:                      .&Apache::loncommon::start_data_table_header_row()
                   4165:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4166:                      .'<th>'.&mt('Default Value').'</th>'
                   4167:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4168:                      .&Apache::loncommon::end_data_table_header_row()
                   4169:             );
1.57      albertel 4170: 
1.548     raeburn  4171:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4172:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4173:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4174:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4175:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4176:                            $readonly);
1.57      albertel 4177:             }
1.419     bisitz   4178:             $r->print(&Apache::loncommon::end_data_table()
                   4179:                      .'</p>'
                   4180:                      .'</center>'
                   4181:             );
1.57      albertel 4182:         } # end of $parmlev eq general
1.606     raeburn  4183:         $r->print('</div>');
1.43      albertel 4184:     }
1.507     www      4185:     $r->print('</form>');
1.582     raeburn  4186:     if ($numreclinks) {
                   4187:         $r->print(<<"END");
                   4188: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4189: <input type="hidden" name="pschp" />
                   4190: <input type="hidden" name="pscat" />
                   4191: <input type="hidden" name="psprt" />
                   4192: <input type="hidden" name="hideparmsel" value="hidden" />
                   4193: </form>
                   4194: <script type="text/javascript">
                   4195: function pjumprec(rid,name,part) {
                   4196:     document.forms.recurseform.pschp.value = rid;
                   4197:     document.forms.recurseform.pscat.value = name;
                   4198:     document.forms.recurseform.psprt.value = part;
                   4199:     document.forms.recurseform.submit();
                   4200:     return false;
                   4201: }
                   4202: </script>
                   4203: END
                   4204:     }
1.507     www      4205:     &endSettingsScreen($r);
                   4206:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4207: } # end sub assessparms
1.30      www      4208: 
1.560     damieng  4209: 
                   4210: 
1.120     www      4211: ##################################################
1.560     damieng  4212: # OVERVIEW MODE
1.207     www      4213: ##################################################
1.124     www      4214: 
1.563     damieng  4215: my $tableopen; # boolean, true if HTML table is already opened
                   4216: 
                   4217: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4218: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4219: # @returns {string}
1.124     www      4220: sub tablestart {
1.576     raeburn  4221:     my ($readonly,$is_map) = @_;
1.124     www      4222:     if ($tableopen) {
1.552     raeburn  4223:         return '';
1.124     www      4224:     } else {
1.552     raeburn  4225:         $tableopen=1;
                   4226:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4227:         if ($readonly) {
                   4228:             $output .= '<th>'.&mt('Current value').'</th>';
                   4229:         } else {
1.576     raeburn  4230:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4231:                        '<th>'.&mt('Set to ...').'</th>';
                   4232:             if ($is_map) {
                   4233:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4234:             }
1.552     raeburn  4235:         }
                   4236:         $output .= '</tr>';
                   4237:         return $output;
1.124     www      4238:     }
                   4239: }
                   4240: 
1.563     damieng  4241: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4242: # @returns {string}
1.124     www      4243: sub tableend {
                   4244:     if ($tableopen) {
1.560     damieng  4245:         $tableopen=0;
                   4246:         return &Apache::loncommon::end_data_table();
1.124     www      4247:     } else {
1.560     damieng  4248:         return'';
1.124     www      4249:     }
                   4250: }
                   4251: 
1.563     damieng  4252: # Reads course and user information.
                   4253: # 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).
                   4254: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4255: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4256: # @param {string} $crs - course number
                   4257: # @param {string} $dom - course domain
                   4258: # @returns {hash reference|Array}
1.207     www      4259: sub readdata {
                   4260:     my ($crs,$dom)=@_;
                   4261: # Read coursedata
                   4262:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4263: # Read userdata
                   4264: 
                   4265:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4266:     foreach my $user (keys(%$classlist)) {
                   4267:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4268:             my ($tuname,$tudom)=($1,$2);
                   4269:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4270:             foreach my $userkey (keys(%{$useropt})) {
                   4271:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4272:                     my $newkey=$userkey;
1.548     raeburn  4273:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4274:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4275:                 }
                   4276:             }
1.473     amueller 4277:         }
                   4278:     }
1.552     raeburn  4279:     if (wantarray) {
                   4280:         return ($resourcedata,$classlist);
                   4281:     } else {
                   4282:         return $resourcedata;
                   4283:     }
1.207     www      4284: }
                   4285: 
                   4286: 
1.563     damieng  4287: # Stores parameter data, using form parameters directly.
                   4288: #
                   4289: # 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  4290: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4291: # del_* - remove a parameter
                   4292: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4293: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4294: # key_* - date values
                   4295: # days_* - for date intervals
                   4296: # hours_* - for date intervals
                   4297: # minutes_* - for date intervals
                   4298: # seconds_* - for date intervals
                   4299: # done_* - for date intervals
                   4300: # typeof_* - parameter type
                   4301: # 
                   4302: # @param {Apache2::RequestRec} $r - the Apache request
                   4303: # @param {string} $crs - course number
                   4304: # @param {string} $dom - course domain
1.208     www      4305: sub storedata {
                   4306:     my ($r,$crs,$dom)=@_;
1.207     www      4307: # Set userlevel immediately
                   4308: # Do an intermediate store of course level
                   4309:     my $olddata=&readdata($crs,$dom);
1.124     www      4310:     my %newdata=();
                   4311:     undef %newdata;
                   4312:     my @deldata=();
1.576     raeburn  4313:     my @delrec=();
                   4314:     my @delnonrec=();
1.124     www      4315:     undef @deldata;
1.504     raeburn  4316:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4317:     my $now = time;
1.560     damieng  4318:     foreach my $key (keys(%env)) {
                   4319:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4320:             my $cmd=$1;
                   4321:             my $thiskey=$2;
1.576     raeburn  4322:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4323:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4324:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4325:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4326:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4327:                     $altkey = $thiskey;
                   4328:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4329:                     if ($env{'form.rec_'.$thiskey}) {
                   4330:                         $recursive = 1;
                   4331:                     }
                   4332:                 }
                   4333:             }
1.560     damieng  4334:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4335:             if ($tuname) {
1.576     raeburn  4336:                 $tkey=$thiskey;
1.560     damieng  4337:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4338:                 if ($altkey) {
                   4339:                     $tkeynonrec = $tkey; 
                   4340:                     $tkeyrec = $altkey;
                   4341:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4342:                 }
1.560     damieng  4343:             }
                   4344:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4345:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4346:                 if ($cmd eq 'set') {
                   4347:                     $data=$env{$key};
                   4348:                     $valmatch = '';
                   4349:                     $valchk = $data;
                   4350:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4351:                     $text = &mt('Saved modified parameter for');
                   4352:                     if ($typeof eq 'string_questiontype') {
                   4353:                         $name = 'type';
1.588     raeburn  4354:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4355:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4356:                         my $stringmatch = &standard_string_matches($typeof);
                   4357:                         if (ref($stringmatch) eq 'ARRAY') {
                   4358:                             foreach my $item (@{$stringmatch}) {
                   4359:                                 if (ref($item) eq 'ARRAY') {
                   4360:                                     my ($regexpname,$pattern) = @{$item};
                   4361:                                     if ($pattern ne '') {
                   4362:                                         if ($data =~ /$pattern/) {
                   4363:                                             $valmatch = $regexpname;
                   4364:                                             $valchk = '';
                   4365:                                             last;
                   4366:                                         }
1.560     damieng  4367:                                     }
1.549     raeburn  4368:                                 }
                   4369:                             }
                   4370:                         }
1.563     damieng  4371:                     } elsif ($typeof eq 'string_discussvote') {
                   4372:                         $name = 'discussvote';
                   4373:                     } elsif ($typeof eq 'string_examcode') {
                   4374:                         $name = 'examcode';
                   4375:                         if (&Apache::lonnet::validCODE($data)) {
                   4376:                             $valchk = 'valid';
                   4377:                         }
                   4378:                     } elsif ($typeof eq 'string_yesno') {
                   4379:                         if ($thiskey =~ /\.retrypartial$/) {
                   4380:                             $name = 'retrypartial';
                   4381:                         }
1.549     raeburn  4382:                     }
1.563     damieng  4383:                 } elsif ($cmd eq 'datepointer') {
                   4384:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4385:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4386:                     $text = &mt('Saved modified date for');
                   4387:                     if ($typeof eq 'date_start') {
                   4388:                         if ($thiskey =~ /\.printstartdate$/) {
                   4389:                             $name = 'printstartdate';
                   4390:                             if (($data) && ($data > $now)) {
                   4391:                                 $valchk = 'future';
                   4392:                             }
1.560     damieng  4393:                         }
1.563     damieng  4394:                     } elsif ($typeof eq 'date_end') {
                   4395:                         if ($thiskey =~ /\.printenddate$/) {
                   4396:                             $name = 'printenddate';
                   4397:                             if (($data) && ($data < $now)) {
                   4398:                                 $valchk = 'past';
                   4399:                             }
1.560     damieng  4400:                         }
1.504     raeburn  4401:                     }
1.563     damieng  4402:                 } elsif ($cmd eq 'dateinterval') {
                   4403:                     $data=&get_date_interval_from_form($thiskey);
                   4404:                     if ($thiskey =~ /\.interval$/) {
                   4405:                         $name = 'interval';
                   4406:                         my $intervaltype = &get_intervaltype($name);
                   4407:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4408:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4409:                             foreach my $item (@{$intervalmatch}) {
                   4410:                                 if (ref($item) eq 'ARRAY') {
                   4411:                                     my ($regexpname,$pattern) = @{$item};
                   4412:                                     if ($pattern ne '') {
                   4413:                                         if ($data =~ /$pattern/) {
                   4414:                                             $valmatch = $regexpname;
                   4415:                                             $valchk = '';
                   4416:                                             last;
                   4417:                                         }
1.560     damieng  4418:                                     }
1.554     raeburn  4419:                                 }
                   4420:                             }
                   4421:                         }
                   4422:                     }
1.563     damieng  4423:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4424:                     $text = &mt('Saved modified date for');
1.554     raeburn  4425:                 }
1.576     raeburn  4426:                 if ($recursive) {
1.563     damieng  4427:                     $namematch = 'maplevelrecurse';
1.560     damieng  4428:                 }
1.563     damieng  4429:                 if (($name ne '') || ($namematch ne '')) {
                   4430:                     my ($needsrelease,$needsnewer);
                   4431:                     if ($name ne '') {
                   4432:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4433:                         if ($needsrelease) {
                   4434:                             unless ($got_chostname) {
1.563     damieng  4435:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4436:                                 $got_chostname = 1;
                   4437:                             }
1.563     damieng  4438:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4439:                                                                 $needsrelease,
                   4440:                                                                 $cmajor,$cminor);
                   4441:                         }
                   4442:                     }
                   4443:                     if ($namematch ne '') {
                   4444:                         if ($needsnewer) {
                   4445:                             undef($namematch);
1.560     damieng  4446:                         } else {
1.563     damieng  4447:                             my $currneeded;
                   4448:                             if ($needsrelease) {
                   4449:                                 $currneeded = $needsrelease;
                   4450:                             }
                   4451:                             $needsrelease =
                   4452:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4453:                             if (($needsrelease) &&
                   4454:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4455:                                 unless ($got_chostname) {
                   4456:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4457:                                     $got_chostname = 1;
                   4458:                                 }
                   4459:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4460:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4461:                             } else {
                   4462:                                 undef($namematch);
                   4463:                             }
1.560     damieng  4464:                         }
1.557     raeburn  4465:                     }
1.563     damieng  4466:                     if ($needsnewer) {
                   4467:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4468:                                                             $chostname,$cmajor,
                   4469:                                                             $cminor,$needsrelease));
                   4470:                         next;
                   4471:                     }
1.504     raeburn  4472:                 }
1.576     raeburn  4473:                 my ($reconlychg,$haschange,$storekey);
                   4474:                 if ($tuname) {
                   4475:                     my $ustorekey;
                   4476:                     if ($altkey) {
                   4477:                         if ($recursive) {
                   4478:                             if (exists($$olddata{$thiskey})) {
                   4479:                                 if ($$olddata{$thiskey} eq $data) {
                   4480:                                     $reconlychg = 1;
                   4481:                                 }
                   4482:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4483:                             }
                   4484:                             if (exists($$olddata{$altkey})) {
                   4485:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4486:                                     $haschange = 1;
                   4487:                                 }
                   4488:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4489:                                 $haschange = 1;
                   4490:                             }
                   4491:                             $ustorekey = $tkeyrec;
                   4492:                         } else {
                   4493:                             if (exists($$olddata{$altkey})) {
                   4494:                                 if ($$olddata{$altkey} eq $data) {
                   4495:                                     $reconlychg = 1;
                   4496:                                 }
                   4497:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4498:                             }
                   4499:                             if (exists($$olddata{$thiskey})) {
                   4500:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4501:                                     $haschange = 1;
                   4502:                                 }
                   4503:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4504:                                 $haschange = 1;
                   4505:                             }
                   4506:                             $ustorekey = $tkeynonrec;
                   4507:                         }
                   4508:                     } else {
                   4509:                         if (exists($$olddata{$tkey})) {
                   4510:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4511:                                 $haschange = 1;
                   4512:                             }
                   4513:                             $ustorekey = $tkey;
                   4514:                         }
                   4515:                     }
                   4516:                     if ($haschange || $reconlychg)  {
                   4517:                         unless ($env{'form.del_'.$thiskey}) {
                   4518:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4519:                                                                      $ustorekey.'.type' => $typeof},
                   4520:                                                                      $tudom,$tuname) eq 'ok') {
                   4521:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4522:                                 $r->print('<br />'.$text.' '.
                   4523:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4524:                             } else {
                   4525:                                 $r->print('<div class="LC_error">'.
                   4526:                                           &mt('Error saving parameters').'</div>');
                   4527:                             }
                   4528:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4529:                         }
                   4530:                     }
                   4531:                 } else {
                   4532:                     if ($altkey) {
                   4533:                         if ($recursive) {
                   4534:                             if (exists($$olddata{$thiskey})) {
                   4535:                                 if ($$olddata{$thiskey} eq $data) {
                   4536:                                     $reconlychg = 1;
                   4537:                                 }
                   4538:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4539:                             }
                   4540:                             if (exists($$olddata{$altkey})) {
                   4541:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4542:                                     $haschange = 1;
                   4543:                                 }
                   4544:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4545:                                 $haschange = 1;
                   4546:                             }
                   4547:                             $storekey = $altkey;
1.563     damieng  4548:                         } else {
1.576     raeburn  4549:                             if (exists($$olddata{$altkey})) {
                   4550:                                 if ($$olddata{$altkey} eq $data) {
                   4551:                                     $reconlychg = 1;
                   4552:                                 }
                   4553:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4554:                             } 
                   4555:                             if (exists($$olddata{$thiskey})) {
                   4556:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4557:                                     $haschange = 1;
                   4558:                                 }
                   4559:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4560:                                 $haschange = 1;
                   4561:                             }
                   4562:                             $storekey = $thiskey;
1.563     damieng  4563:                         }
1.560     damieng  4564:                     } else {
1.576     raeburn  4565:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4566:                             $haschange = 1;
                   4567:                             $storekey = $thiskey;
                   4568:                         }
                   4569:                     }
                   4570:                 }
                   4571:                 if ($reconlychg || $haschange) {
                   4572:                     unless ($env{'form.del_'.$thiskey}) {
                   4573:                         $newdata{$storekey}=$data;
                   4574:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4575:                     }
                   4576:                 }
                   4577:             } elsif ($cmd eq 'del') {
                   4578:                 if ($tuname) {
1.576     raeburn  4579:                     my $error;
                   4580:                     if ($altkey) {  
                   4581:                         if (exists($$olddata{$altkey})) {
                   4582:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4583:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4584:                                 if ($recursive) {
                   4585:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4586:                                 }
                   4587:                             } elsif ($recursive) {
                   4588:                                 $error = 1;
                   4589:                             }
                   4590:                         }
                   4591:                         if (exists($$olddata{$thiskey})) {
                   4592:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4593:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4594:                                 unless ($recursive) {
                   4595:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4596:                                 }
                   4597:                             } elsif (!$recursive) {
                   4598:                                 $error = 1;
                   4599:                             }
                   4600:                         }
1.560     damieng  4601:                     } else {
1.576     raeburn  4602:                         if (exists($$olddata{$thiskey})) {
                   4603:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4604:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4605:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4606:                             } else {
                   4607:                                 $error = 1;
                   4608:                             }
                   4609:                         }
                   4610:                     }
                   4611:                     if ($error) { 
1.560     damieng  4612:                         $r->print('<div class="LC_error">'.
                   4613:                             &mt('Error deleting parameters').'</div>');
                   4614:                     }
                   4615:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4616:                 } else {
1.576     raeburn  4617:                     if ($altkey) {
                   4618:                         if (exists($$olddata{$altkey})) {
                   4619:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4620:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4621:                             }
                   4622:                         }
                   4623:                         if (exists($$olddata{$thiskey})) {
                   4624:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4625:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4626:                             }
                   4627:                         }
                   4628:                     } elsif (exists($$olddata{$thiskey})) {
                   4629:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4630:                     }
1.560     damieng  4631:                 }
1.473     amueller 4632:             }
                   4633:         }
                   4634:     }
1.207     www      4635: # Store all course level
1.144     www      4636:     my $delentries=$#deldata+1;
1.576     raeburn  4637:     my @alldels;
                   4638:     if (@delrec) {
                   4639:         push(@alldels,@delrec);
                   4640:     }
                   4641:     if (@delnonrec) {
                   4642:         push(@alldels,@delnonrec);
                   4643:     }
                   4644:     if (@deldata) {
                   4645:         push(@alldels,@deldata);
                   4646:     }
1.548     raeburn  4647:     my @newdatakeys=keys(%newdata);
1.144     www      4648:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4649:     my ($delresult,$devalidate);
                   4650:     if (@alldels) {
                   4651:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4652:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4653:             &log_parmset(\%loghash,1);
1.576     raeburn  4654:             if ($delentries) {
                   4655:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4656:             }
                   4657:         } elsif ($delentries) {
1.560     damieng  4658:             $r->print('<div class="LC_error">'.
                   4659:                 &mt('Error deleting parameters').'</div>');
                   4660:         }
1.576     raeburn  4661:         $devalidate = 1; 
1.144     www      4662:     }
                   4663:     if ($putentries) {
1.560     damieng  4664:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4665:                     &log_parmset(\%newdata,0);
                   4666:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4667:         } else {
                   4668:             $r->print('<div class="LC_error">'.
                   4669:                 &mt('Error saving parameters').'</div>');
                   4670:         }
1.576     raeburn  4671:         $devalidate = 1; 
                   4672:     }
                   4673:     if ($devalidate) {
1.560     damieng  4674:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4675:     }
1.208     www      4676: }
1.207     www      4677: 
1.563     damieng  4678: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4679: #
                   4680: # @param {string} $key - the key
                   4681: # @returns {Array}
1.208     www      4682: sub extractuser {
                   4683:     my $key=shift;
1.350     albertel 4684:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4685: }
1.206     www      4686: 
1.563     damieng  4687: # Parses a parameter key and returns the components.
                   4688: #
                   4689: # @param {string} $key - 
                   4690: # @param {hash reference} $listdata - 
                   4691: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4692: sub parse_listdata_key {
                   4693:     my ($key,$listdata) = @_;
                   4694:     # split into student/section affected, and
                   4695:     # the realm (folder/resource part and parameter
1.446     bisitz   4696:     my ($student,$realm) =
1.473     amueller 4697:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4698:     # if course wide student would be undefined
                   4699:     if (!defined($student)) {
1.560     damieng  4700:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4701:     }
                   4702:     # strip off the .type if it's not the Question type parameter
                   4703:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4704:         $realm=~s/\.type//;
1.381     albertel 4705:     }
                   4706:     # split into resource+part and parameter name
1.388     albertel 4707:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4708:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4709:     return ($student,$res,$part,$parm);
                   4710: }
                   4711: 
1.563     damieng  4712: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4713: #
                   4714: # @param {Apache2::RequestRec} $r - the Apache request
                   4715: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4716: # @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
                   4717: # @param {string} $sortorder - realmstudent|studentrealm
                   4718: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4719: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4720: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4721: # @param {string} $parmlev - full|map
                   4722: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4723: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4724: # @returns{integer} - number of $listdata parameters processed
1.208     www      4725: sub listdata {
1.608     raeburn  4726:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4727:     
1.207     www      4728: # Start list output
1.206     www      4729: 
1.122     www      4730:     my $oldsection='';
                   4731:     my $oldrealm='';
                   4732:     my $oldpart='';
1.123     www      4733:     my $pointer=0;
1.124     www      4734:     $tableopen=0;
1.145     www      4735:     my $foundkeys=0;
1.248     albertel 4736:     my %keyorder=&standardkeyorder();
1.594     raeburn  4737:     my $readonlyall = $readonly;
1.381     albertel 4738: 
1.552     raeburn  4739:     my ($secidx,%grouphash);
                   4740:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4741:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4742:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4743:             %grouphash = &Apache::longroup::coursegroups();
                   4744:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4745:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4746:         }
1.552     raeburn  4747:     }
                   4748: 
1.576     raeburn  4749:     foreach my $key (sort {
1.560     damieng  4750:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4751:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4752:         my ($aid,$bid);
                   4753:         if ($caller eq 'newoverview') {
                   4754:             if (ref($hash_for_realm) eq 'HASH') {
                   4755:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4756:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4757:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4758:                     $aid = $hash_for_realm->{$aurl};
                   4759:                     $bid = $hash_for_realm->{$burl};
                   4760:                 } elsif ($parmlev eq 'full') {
                   4761:                     $aid = $hash_for_realm->{$ares};
                   4762:                     $bid = $hash_for_realm->{$bres};
                   4763:                 }
                   4764:             }
                   4765:         }
1.381     albertel 4766: 
1.560     damieng  4767:         # get the numerical order for the param
                   4768:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4769:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4770: 
1.560     damieng  4771:         my $result=0;
1.381     albertel 4772: 
1.560     damieng  4773:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4774:             if ($ares     ne $bres    ) {
1.608     raeburn  4775:                 if ($caller eq 'newoverview') {
                   4776:                     if (ref($hash_for_realm) eq 'HASH') {
                   4777:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4778:                             $result = ($aid <=> $bid);
                   4779:                         } elsif ($parmlev eq 'full') {
                   4780:                             $result = ($aid <=> $bid);
                   4781:                         } else {
                   4782:                             $result = ($ares cmp $bres);
                   4783:                         }
                   4784:                     } else {
                   4785:                         $result = ($ares cmp $bres);
                   4786:                     }
                   4787:                 } else {
                   4788:                     $result = ($ares cmp $bres);
                   4789:                 }
1.446     bisitz   4790:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4791:                 $result = ($astudent cmp $bstudent);
                   4792:             } elsif ($apart    ne $bpart   ) {
                   4793:                 $result = ($apart    cmp $bpart);
                   4794:             }
                   4795:         } else {
                   4796:             if      ($astudent ne $bstudent) {
                   4797:                 $result = ($astudent cmp $bstudent);
                   4798:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4799:                 if ($caller eq 'newoverview') {
                   4800:                     if (ref($hash_for_realm) eq 'HASH') {
                   4801:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4802:                             $result = ($aid <=> $bid);
                   4803:                         } elsif ($parmlev eq 'full') {
                   4804:                             $result = ($aid <=> $bid);
                   4805:                         } else {
                   4806:                             $result = ($ares cmp $bres);
                   4807:                         }
                   4808:                     } else {
                   4809:                         $result = ($ares cmp $bres);
                   4810:                     }
                   4811:                 } else {
                   4812:                     $result = ($ares cmp $bres);
                   4813:                 }
1.560     damieng  4814:             } elsif ($apart    ne $bpart   ) {
                   4815:                 $result = ($apart    cmp $bpart);
                   4816:             }
1.473     amueller 4817:         }
1.446     bisitz   4818: 
1.560     damieng  4819:         if (!$result) {
1.381     albertel 4820:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4821:                 $result = ($aparm <=> $bparm);
1.381     albertel 4822:             } elsif (defined($aparm)) {
1.560     damieng  4823:                 $result = -1;
1.381     albertel 4824:             } elsif (defined($bparm)) {
1.560     damieng  4825:                 $result = 1;
                   4826:             }
1.473     amueller 4827:         }
1.381     albertel 4828: 
1.560     damieng  4829:         $result;
                   4830:         
1.576     raeburn  4831:     } keys(%{$listdata})) { # foreach my $key
                   4832:         my $thiskey = $key;
1.560     damieng  4833:         if ($$listdata{$thiskey.'.type'}) {
                   4834:             my $thistype=$$listdata{$thiskey.'.type'};
                   4835:             if ($$resourcedata{$thiskey.'.type'}) {
                   4836:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4837:             }
                   4838:             my ($middle,$part,$name)=
1.572     damieng  4839:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4840:             my $section=&mt('All Students');
1.594     raeburn  4841:             $readonly = $readonlyall;
1.599     raeburn  4842:             my $userscope;
1.576     raeburn  4843:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4844:             if ($middle=~/^\[(.*)\]/) {
                   4845:                 my $issection=$1;
                   4846:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4847:                     my ($stuname,$studom) = ($1,$2);
                   4848:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4849:                         if (ref($classlist) eq 'HASH') {
                   4850:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4851:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4852:                             }
                   4853:                         }
                   4854:                     }
                   4855:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4856:                     $userscope = 1;
1.560     damieng  4857:                 } else {
                   4858:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4859:                         if (exists($grouphash{$issection})) {
                   4860:                             $section=&mt('Group').': '.$issection;
                   4861:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4862:                             $section = &mt('Section').': '.$issection;
                   4863:                         } else {
                   4864:                             next; 
1.552     raeburn  4865:                         }
1.560     damieng  4866:                     } else {
                   4867:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4868:                     }
                   4869:                 }
1.560     damieng  4870:                 $middle=~s/^\[(.*)\]//;
                   4871:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4872:                 $readonly = 1;
                   4873:             }
                   4874:             $middle=~s/\.+$//;
                   4875:             $middle=~s/^\.+//;
                   4876:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4877:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4878:             if ($caller eq 'overview') {
                   4879:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4880:                     $mapurl = $1;
                   4881:                     $maplevel = $2;
                   4882:                     $is_map = 1;
                   4883:                 }
                   4884:             } elsif ($caller eq 'newoverview') {
                   4885:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4886:                     $mapurl = $1;
                   4887:                     $maplevel = $2;
                   4888:                     $is_map = 1;
                   4889:                 }
                   4890:             }
                   4891:             if ($is_map) {
1.560     damieng  4892:                 my $leveltitle = &mt('Folder/Map');
1.608     raeburn  4893:                 my $title = &Apache::lonnet::gettitle($1);
                   4894:                 if (ref($hash_for_realm) eq 'HASH') {
                   4895:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4896:                         $title = &mt('Main Content');
                   4897:                     }
                   4898:                 }
1.576     raeburn  4899:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4900:                     if ($caller eq 'newoverview') {
                   4901:                         my $altkey = $thiskey;
                   4902:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4903:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4904:                             $is_recursive = 1;
                   4905:                             if ($$resourcedata{$altkey.'.type'}) {
                   4906:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4907:                             }
                   4908:                             $showval = $$resourcedata{$altkey};
                   4909:                         }
                   4910:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4911:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4912:                         $is_recursive = 1;
                   4913:                     }
1.560     damieng  4914:                 }
1.608     raeburn  4915:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4916:             } elsif ($middle) {
                   4917:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4918:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4919:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4920:                     ': '.&Apache::lonnet::gettitle($middle).
                   4921:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4922:                     $id.')</span></span>';
                   4923:             }
                   4924:             if ($sortorder eq 'realmstudent') {
                   4925:                 if ($realm ne $oldrealm) {
                   4926:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4927:                     $oldrealm=$realm;
                   4928:                     $oldsection='';
                   4929:                 }
                   4930:                 if ($section ne $oldsection) {
                   4931:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4932:                     $oldsection=$section;
                   4933:                     $oldpart='';
                   4934:                 }
1.552     raeburn  4935:             } else {
1.560     damieng  4936:                 if ($section ne $oldsection) {
                   4937:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4938:                     $oldsection=$section;
                   4939:                     $oldrealm='';
                   4940:                 }
                   4941:                 if ($realm ne $oldrealm) {
                   4942:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4943:                     $oldrealm=$realm;
                   4944:                     $oldpart='';
1.552     raeburn  4945:                 }
                   4946:             }
1.560     damieng  4947:             if ($part ne $oldpart) {
                   4948:                 $r->print(&tableend().
                   4949:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4950:                 $oldpart=$part;
1.556     raeburn  4951:             }
1.560     damieng  4952:     #
                   4953:     # Ready to print
                   4954:     #
1.470     raeburn  4955:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4956:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4957:                 &Apache::loncommon::start_data_table_row().
                   4958:                 '<td><b>'.&mt($parmitem).
                   4959:                 '</b></td>');
                   4960:             unless ($readonly) {
1.599     raeburn  4961:                 my $disabled;
                   4962:                 if (($name eq 'availablestudent') &&
                   4963:                     (($showval eq '') || ($userscope))) {
                   4964:                     $disabled = ' disabled="disabled"';
                   4965:                 }
1.560     damieng  4966:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  4967:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  4968:             }
                   4969:             $r->print('<td>');
                   4970:             $foundkeys++;
                   4971:             if (&isdateparm($thistype)) {
                   4972:                 my $jskey='key_'.$pointer;
                   4973:                 my $state;
                   4974:                 $pointer++;
                   4975:                 if ($readonly) {
                   4976:                     $state = 'disabled';
                   4977:                 }
                   4978:                 $r->print(
                   4979:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4980:                                                         $jskey,
1.576     raeburn  4981:                                                         $showval,
1.560     damieng  4982:                                                         '',1,$state));
                   4983:                 unless  ($readonly) {
                   4984:                     $r->print(
                   4985:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4986:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4987:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4988:     &date_sanity_info($showval)
1.560     damieng  4989:                     );
                   4990:                 }
                   4991:             } elsif ($thistype eq 'date_interval') {
                   4992:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4993:                           $showval,$readonly));
1.560     damieng  4994:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  4995:                 if ($name eq 'availablestudent') {
                   4996:                     $readonly = 1;
                   4997:                 }
1.560     damieng  4998:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4999:                           $showval,$name,$readonly));
1.560     damieng  5000:             } else {
1.576     raeburn  5001:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5002:             }
1.560     damieng  5003:             unless ($readonly) {
                   5004:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5005:                         $thistype.'" />');
1.552     raeburn  5006:             }
1.576     raeburn  5007:             $r->print('</td>');
                   5008:             if ($is_map) {
                   5009:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5010:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5011:                 } else {
                   5012:                     my ($disabled,$recon,$recoff);
                   5013:                     if ($readonly) {
                   5014:                         $disabled = ' disabled="disabled"';
                   5015:                     }
                   5016:                     if ($is_recursive) {
                   5017:                         $recon = ' checked="checked"';
                   5018:                     } else {
                   5019:                         $recoff = ' checked="checked"';
                   5020:                     }
                   5021:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5022:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5023:                 }
                   5024:             }
                   5025:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5026:         }
1.121     www      5027:     }
1.208     www      5028:     return $foundkeys;
                   5029: }
                   5030: 
1.563     damieng  5031: # Returns a string representing the interval, directly using form data matching the given key.
                   5032: # The returned string may also include information related to proctored exams.
                   5033: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5034: #
                   5035: # @param {string} $key - suffix for form fields related to the interval
                   5036: # @returns {string}
1.385     albertel 5037: sub get_date_interval_from_form {
                   5038:     my ($key) = @_;
                   5039:     my $seconds = 0;
1.611   ! raeburn  5040:     my $numnotnull = 0;
1.385     albertel 5041:     foreach my $which (['days', 86400],
1.473     amueller 5042:                ['hours', 3600],
                   5043:                ['minutes', 60],
                   5044:                ['seconds',  1]) {
1.560     damieng  5045:         my ($name, $factor) = @{ $which };
                   5046:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611   ! raeburn  5047:             unless ($env{'form.'.$name.'_'.$key} eq '') {
        !          5048:                 $numnotnull ++;
        !          5049:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
        !          5050:             }
1.560     damieng  5051:         }
1.473     amueller 5052:     }
1.560     damieng  5053:     if (($key =~ /\.interval$/) &&
                   5054:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5055:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5056:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5057:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5058:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5059:                 $seconds .= '_proctor';
                   5060:             }
                   5061:         } else {
                   5062:             $seconds .= $env{'form.done_'.$key}; 
                   5063:         }
                   5064:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5065:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5066:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5067:         }
1.554     raeburn  5068:     }
1.611   ! raeburn  5069:     return if (!$numnotnull);
1.385     albertel 5070:     return $seconds;
                   5071: }
                   5072: 
                   5073: 
1.563     damieng  5074: # Returns HTML to enter a text value for a parameter.
                   5075: #
                   5076: # @param {string} $thiskey - parameter key
                   5077: # @param {string} $showval - the current value
                   5078: # @param {boolean} $readonly - true if the field should not be made editable
                   5079: # @returns {string}
1.383     albertel 5080: sub default_selector {
1.552     raeburn  5081:     my ($thiskey, $showval, $readonly) = @_;
                   5082:     my $disabled;
                   5083:     if ($readonly) {
                   5084:         $disabled = ' disabled="disabled"';
                   5085:     }
                   5086:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5087: }
                   5088: 
1.563     damieng  5089: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5090: #
                   5091: # @param {string} $thiskey - parameter key
                   5092: # @param {string} $showval - the current value
                   5093: # @param {boolean} $readonly - true if the fields should not be made editable
                   5094: # @returns {string}
1.549     raeburn  5095: sub string_ip_selector {
1.552     raeburn  5096:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5097:     my %access = (
                   5098:                    allow => [],
                   5099:                    deny  => [],
                   5100:                  );
                   5101:     if ($showval ne '') {
                   5102:         my @current;
                   5103:         if ($showval =~ /,/) {
                   5104:             @current = split(/,/,$showval);
                   5105:         } else {
                   5106:             @current = ($showval);
                   5107:         }
                   5108:         foreach my $item (@current) {
                   5109:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5110:                 push(@{$access{'deny'}},$1);
                   5111:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5112:                 push(@{$access{'allow'}},$item);
                   5113:             }
                   5114:         }
                   5115:     }
                   5116:     if (!@{$access{'allow'}}) {
                   5117:         @{$access{'allow'}} = ('');
                   5118:     }
                   5119:     if (!@{$access{'deny'}}) {
                   5120:         @{$access{'deny'}} = ('');
                   5121:     }
1.552     raeburn  5122:     my ($disabled,$addmore);
1.567     raeburn  5123:     if ($readonly) {
1.552     raeburn  5124:         $disabled=' disabled="disabled"';
                   5125:     } else {
                   5126:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5127:     }
1.549     raeburn  5128:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5129: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5130:     foreach my $acctype ('allow','deny') {
                   5131:         $output .= '
                   5132: <td valign="top">
                   5133: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5134:   <div class="LC_string_ipacc_inner">'."\n";
                   5135:         my $num = 0;
                   5136:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5137:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5138:             if ($num > 0) {
                   5139:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5140:             }
                   5141:             $output .= '</div>'."\n";
                   5142:             $num ++;
                   5143:         }
                   5144:         $output .= '
1.552     raeburn  5145:   </div>'.$addmore.'
1.549     raeburn  5146: </div>
                   5147: </td>';
                   5148:    }
                   5149:    $output .= '
                   5150: </tr>
                   5151: </table>'."\n";
                   5152:     return $output;
                   5153: }
                   5154: 
1.588     raeburn  5155: sub string_deeplink_selector {
                   5156:     my ($thiskey, $showval, $readonly) = @_;
1.597     raeburn  5157:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601     raeburn  5158:         %selectnull,%domlti,%crslti,@possmenus);
                   5159:     @components = ('state','others','listing','scope','protect','menus');
1.588     raeburn  5160:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5161:                   state   => 'Access status',
                   5162:                   others  => 'Hide other resources',
1.588     raeburn  5163:                   listing => 'In Contents and/or Gradebook',
                   5164:                   scope   => 'Access scope for link',
1.601     raeburn  5165:                   protect => 'Link protection',
1.597     raeburn  5166:                   menus   => 'Menu Items Displayed',
1.588     raeburn  5167:               );
                   5168:     %options = (
1.601     raeburn  5169:                    state   => ['only','off','both'],
                   5170:                    others  => ['hide','unhide'],
1.588     raeburn  5171:                    listing => ['full','absent','grades','details','datestatus'],
                   5172:                    scope   => ['res','map','rec'],
1.601     raeburn  5173:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5174:                    menus   => ['std','colls'],
1.588     raeburn  5175:                );
                   5176:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5177:                     only       => 'deep only',
                   5178:                     off        => 'deeplink off',
                   5179:                     both       => 'regular + deep',
                   5180:                     hide       => 'Hidden',
                   5181:                     unhide     => 'Unhidden',
1.588     raeburn  5182:                     full       => 'Listed (linked) in both',
                   5183:                     absent     => 'Not listed',
                   5184:                     grades     => 'Listed in grades only',
                   5185:                     details    => 'Listed (unlinked) in both',
                   5186:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5187:                     res        => 'resource only',
                   5188:                     map        => 'enclosing map/folder',
                   5189:                     rec        => 'recursive map/folder',
1.601     raeburn  5190:                     none       => 'not in use',
                   5191:                     key        => 'key access',
                   5192:                     ltic       => 'LTI access (course)',
                   5193:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5194:                     std        => 'Standard (all menus)',
                   5195:                     colls      => 'Numbered collection',
                   5196:                   );
                   5197:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5198:                     ltic => 'Select Launcher',
                   5199:                     ltid => 'Select Launcher', 
1.597     raeburn  5200:                     colls => 'Select',
1.588     raeburn  5201:                   );
                   5202:     if ($showval =~ /,/) {
1.597     raeburn  5203:         %values=();
1.588     raeburn  5204:         @current = split(/,/,$showval);
1.601     raeburn  5205:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5206:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5207:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5208:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5209:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5210:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588     raeburn  5211:     } else {
1.601     raeburn  5212:         $defaults{'state'} = 'off',
                   5213:         $defaults{'others'} = 'unhide',
1.588     raeburn  5214:         $defaults{'listing'} = 'full';
                   5215:         $defaults{'scope'} = 'res';
1.601     raeburn  5216:         $defaults{'protect'} = 'none';
1.597     raeburn  5217:         $defaults{'menus'} = '0';
1.588     raeburn  5218:     }
                   5219:     my $disabled;
                   5220:     if ($readonly) {
                   5221:         $disabled=' disabled="disabled"';
                   5222:     }
1.601     raeburn  5223:     my %courselti =
                   5224:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5225:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5226:     foreach my $item (keys(%courselti)) {
                   5227:         if (ref($courselti{$item}) eq 'HASH') {
                   5228:             $crslti{$item} = $courselti{$item}{'name'};
                   5229:         }
                   5230:     }
                   5231:     my %lti =
1.588     raeburn  5232:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5233:                                         'linkprot');
1.588     raeburn  5234:     foreach my $item (keys(%lti)) {
1.604     raeburn  5235:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5236:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5237:         }
                   5238:     }
1.597     raeburn  5239:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5240:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5241:             my ($num,$value) = split(/\%/,$item);
                   5242:             if ($num =~ /^\d+$/) {
                   5243:                 push(@possmenus,$num);
                   5244:             }
                   5245:         }
                   5246:     }
                   5247: 
1.588     raeburn  5248:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597     raeburn  5249:     foreach my $item (@components) {
1.588     raeburn  5250:         $output .= '<th>'.$titles{$item}.'</th>';
                   5251:     }
                   5252:     $output .= '</tr><tr>';
                   5253:     foreach my $item (@components) {
                   5254:         $output .= '<td>';
1.601     raeburn  5255:         if (($item eq 'protect') || ($item eq 'menus')) {
1.588     raeburn  5256:             my $selected = $values{$item};
                   5257:             foreach my $option (@{$options{$item}}) {
1.601     raeburn  5258:                 if ($item eq 'protect') { 
                   5259:                     if ($option eq 'ltid') {
                   5260:                         next unless (keys(%domlti));
                   5261:                     } elsif ($option eq 'ltic') {
                   5262:                         next unless (keys(%crslti));
                   5263:                     }
1.597     raeburn  5264:                 } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5265:                     next unless (@possmenus);
1.588     raeburn  5266:                 }
                   5267:                 my $checked;
1.597     raeburn  5268:                 if ($item eq 'menus') {
                   5269:                     if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5270:                         (grep(/^\Q$selected\E$/,@possmenus))) {
                   5271:                         if ($option eq 'colls') {
                   5272:                             $checked = ' checked="checked"';
                   5273:                         }
                   5274:                     } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                   5275:                         $checked = ' checked="checked"';
                   5276:                     }
                   5277:                 } elsif ($selected =~ /^\Q$option\E/) {
1.588     raeburn  5278:                     $checked = ' checked="checked"';
                   5279:                 }
                   5280:                 my $onclick;
                   5281:                 unless ($readonly) {
                   5282:                     my $esc_key = &js_escape($thiskey);
                   5283:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5284:                 }
                   5285:                 $output .= '<span class="LC_nobreak"><label>'.
                   5286:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5287:                            $optiontext{$option}.'</label>';
1.601     raeburn  5288:                 if (($item eq 'protect') && ($option eq 'key')) {
1.588     raeburn  5289:                     my $visibility="hidden";
                   5290:                     my $currkey;
                   5291:                     if ($checked) {
                   5292:                         $visibility = "text";
                   5293:                         $currkey = (split(/\:/,$values{$item}))[1];
                   5294:                     }
                   5295:                     $output .= '&nbsp;'.
1.597     raeburn  5296:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601     raeburn  5297:                 } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588     raeburn  5298:                     my $display="none";
1.597     raeburn  5299:                     my ($current,$blankcheck,@possibles);
1.588     raeburn  5300:                     if ($checked) {
                   5301:                         $display = 'inline-block';
1.601     raeburn  5302:                         if (($option eq 'ltic') || ($option eq 'ltid'))  {
1.597     raeburn  5303:                             $current = (split(/\:/,$selected))[1];
                   5304:                         } else {
                   5305:                             $current = $selected;
                   5306:                         }
1.588     raeburn  5307:                     } else {
                   5308:                         $blankcheck = ' selected="selected"';
                   5309:                     }
1.601     raeburn  5310:                     if ($option eq 'ltid') {
                   5311:                         @possibles = keys(%domlti);
                   5312:                     } elsif ($option eq 'ltic') {
                   5313:                         @possibles = keys(%crslti); 
1.597     raeburn  5314:                     } else {
                   5315:                         @possibles = @possmenus;
                   5316:                     }
1.588     raeburn  5317:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5318:                                ' style="display: '.$display.'">&nbsp;<select name="'.
1.597     raeburn  5319:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5320:                     if (@possibles > 1) {
                   5321:                         $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5322:                                    '</option>'."\n";
                   5323:                     }
                   5324:                     foreach my $poss (sort { $a <=> $b } @possibles) {
1.588     raeburn  5325:                         my $selected;
1.597     raeburn  5326:                         if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588     raeburn  5327:                             $selected = ' selected="selected"';
                   5328:                         }
1.597     raeburn  5329:                         my $shown = $poss;
1.601     raeburn  5330:                         if ($option eq 'ltid') {
                   5331:                             $shown = $domlti{$poss};
                   5332:                         } elsif ($option eq 'ltic') {
                   5333:                             $shown = $crslti{$poss};
1.597     raeburn  5334:                         }
                   5335:                         $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588     raeburn  5336:                     }
                   5337:                     $output .= '</select></div>';
                   5338:                 }
                   5339:                 $output .= '</span> ';
                   5340:             }
                   5341:         } else {
                   5342:             my $selected = $values{$item};
                   5343:             my $defsel;
                   5344:             if ($selected eq '') {
                   5345:                 $defsel = ' selected="selected"';
                   5346:             }
                   5347:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5348:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5349:             foreach my $option (@{$options{$item}}) {
                   5350:                 $output .= '<option value="'.$option.'"';
                   5351:                 if ($option eq $selected) {
                   5352:                     $output .= ' selected="selected"';
                   5353:                 }
                   5354:                 $output .= '>'.$optiontext{$option}.'</option>';
                   5355:             }
                   5356:             $output .= '</select>';
                   5357:         }
                   5358:         $output .= '</td>';
                   5359:     }
                   5360:     $output .= '</tr></table>'."\n";
                   5361:     return $output;
                   5362: }
                   5363: 
1.560     damieng  5364: 
                   5365: { # block using some constants related to parameter types (overview mode)
                   5366: 
1.446     bisitz   5367: my %strings =
1.383     albertel 5368:     (
                   5369:      'string_yesno'
                   5370:              => [[ 'yes', 'Yes' ],
1.560     damieng  5371:                  [ 'no', 'No' ]],
1.383     albertel 5372:      'string_problemstatus'
                   5373:              => [[ 'yes', 'Yes' ],
1.473     amueller 5374:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5375:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5376:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5377:      'string_questiontype'
                   5378:              => [[ 'problem', 'Standard Problem'],
                   5379:                  [ 'survey', 'Survey'],
                   5380:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5381:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5382:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5383:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5384:                  [ 'practice', 'Practice'],
                   5385:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5386:      'string_lenient'
                   5387:              => [['yes', 'Yes' ],
                   5388:                  [ 'no', 'No' ],
1.549     raeburn  5389:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5390:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5391:      'string_discussvote'
                   5392:              => [['yes','Yes'],
                   5393:                  ['notended','Yes, unless discussion ended'],
                   5394:                  ['no','No']],
1.549     raeburn  5395:      'string_ip'
                   5396:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5397:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5398:      'string_deeplink'
1.597     raeburn  5399:              => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587     raeburn  5400:     );
                   5401:    
1.383     albertel 5402: 
1.549     raeburn  5403: my %stringmatches = (
                   5404:          'string_lenient'
                   5405:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5406:          'string_ip'
                   5407:               => [['_allowfrom_','[^\!]+'],
                   5408:                   ['_denyfrom_','\!']],
1.588     raeburn  5409:          'string_deeplink'
1.602     raeburn  5410:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549     raeburn  5411:     );
                   5412: 
                   5413: my %stringtypes = (
                   5414:                     type         => 'string_questiontype',
                   5415:                     lenient      => 'string_lenient',
                   5416:                     retrypartial => 'string_yesno',
                   5417:                     discussvote  => 'string_discussvote',
                   5418:                     examcode     => 'string_examcode',
                   5419:                     acc          => 'string_ip',
1.587     raeburn  5420:                     deeplink     => 'string_deeplink',
1.549     raeburn  5421:                   );
                   5422: 
1.563     damieng  5423: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5424: # Used by courseprefs.
                   5425: #
                   5426: # @param {string} $string_type - a parameter type for strings
                   5427: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5428: sub standard_string_options {
                   5429:     my ($string_type) = @_;
                   5430:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5431:         return $strings{$string_type};
                   5432:     }
                   5433:     return;
                   5434: }
1.383     albertel 5435: 
1.563     damieng  5436: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5437: #
                   5438: # @param {string} $string_type - a parameter type for strings
                   5439: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5440: sub standard_string_matches {
                   5441:     my ($string_type) = @_;
                   5442:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5443:         return $stringmatches{$string_type};
                   5444:     }
                   5445:     return;
                   5446: }
                   5447: 
1.563     damieng  5448: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5449: #
                   5450: # @param {string} $name - parameter name
                   5451: # @returns {string}
1.549     raeburn  5452: sub get_stringtype {
                   5453:     my ($name) = @_;
                   5454:     if (exists($stringtypes{$name})) {
                   5455:         return $stringtypes{$name};
                   5456:     }
                   5457:     return;
                   5458: }
                   5459: 
1.563     damieng  5460: # Returns HTML to edit a string parameter.
                   5461: #
                   5462: # @param {string} $thistype - parameter type
                   5463: # @param {string} $thiskey - parameter key
                   5464: # @param {string} $showval - parameter current value
                   5465: # @param {string} $name - parameter name
                   5466: # @param {boolean} $readonly - true if the values should not be made editable
                   5467: # @returns {string}
1.383     albertel 5468: sub string_selector {
1.552     raeburn  5469:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5470: 
1.383     albertel 5471:     if (!exists($strings{$thistype})) {
1.552     raeburn  5472:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5473:     }
                   5474: 
1.504     raeburn  5475:     my %skiptype;
1.514     raeburn  5476:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5477:             ($thistype eq 'string_lenient') ||
                   5478:             ($thistype eq 'string_discussvote') ||
                   5479:             ($thistype eq 'string_ip') ||
1.588     raeburn  5480:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5481:             ($name eq 'retrypartial')) {
1.504     raeburn  5482:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5483:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5484:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5485:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5486:             my $parmmatch;
                   5487:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5488:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5489:                     if (ref($item) eq 'ARRAY') {
                   5490:                         if ($parmval eq $item->[0]) {
                   5491:                             $parmmatch = $parmval;
                   5492:                             $parmval = '';
                   5493:                             last;
                   5494:                         }
                   5495:                     }
                   5496:                 }
                   5497:             }
                   5498:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5499:             if ($needsrelease) {
                   5500:                 unless ($got_chostname) {
1.514     raeburn  5501:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5502:                     $got_chostname = 1;
                   5503:                 }
1.557     raeburn  5504:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5505:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5506:                 if ($needsnewer) {
1.549     raeburn  5507:                     if ($parmmatch ne '') {
                   5508:                         $skiptype{$parmmatch} = 1;
                   5509:                     } elsif ($parmval ne '') {
                   5510:                         $skiptype{$parmval} = 1;
                   5511:                     }
1.504     raeburn  5512:                 }
                   5513:             }
                   5514:         }
                   5515:     }
1.549     raeburn  5516: 
                   5517:     if ($thistype eq 'string_ip') {
1.552     raeburn  5518:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5519:     } elsif ($thistype eq 'string_deeplink') {
                   5520:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5521:     }
1.504     raeburn  5522: 
1.552     raeburn  5523:     my ($result,$disabled);
                   5524: 
                   5525:     if ($readonly) {
                   5526:         $disabled = ' disabled="disabled"';
                   5527:     }
1.504     raeburn  5528:     my $numinrow = 3;
                   5529:     if ($thistype eq 'string_problemstatus') {
                   5530:         $numinrow = 2;
                   5531:     } elsif ($thistype eq 'string_questiontype') {
                   5532:         if (keys(%skiptype) > 0) {
                   5533:              $numinrow = 4;
                   5534:         }
                   5535:     }
                   5536:     my $rem;
                   5537:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5538:         my $i=0;
                   5539:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5540:             next unless (ref($possibilities) eq 'ARRAY');
                   5541:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5542:             next if ($skiptype{$name});
1.504     raeburn  5543:             $rem = $i%($numinrow);
                   5544:             if ($rem == 0) {
                   5545:                 if ($i > 0) {
                   5546:                     $result .= '</tr>';
                   5547:                 }
                   5548:                 $result .= '<tr>';
                   5549:             }
1.549     raeburn  5550:             my $colspan;
                   5551:             if ($i == @{ $strings{$thistype} }-1) {
                   5552:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5553:                 if ($rem) {
                   5554:                     my $colsleft = $numinrow - $rem;
                   5555:                     if ($colsleft) {
                   5556:                         $colspan = $colsleft+1;
                   5557:                         $colspan = ' colspan="'.$colspan.'"';
                   5558:                     }
                   5559:                 }
                   5560:             }
                   5561:             my ($add,$onchange,$css_class);
                   5562:             if ($thistype eq 'string_lenient') {
                   5563:                 if ($name eq 'weighted') {
                   5564:                     my $display;
                   5565:                     my %relatives = &Apache::lonlocal::texthash(
                   5566:                                         corrchkd     => 'Correct (checked)',
                   5567:                                         corrunchkd   => 'Correct (unchecked)',
                   5568:                                         incorrchkd   => 'Incorrect (checked)',
                   5569:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5570:                     );
                   5571:                     my %textval = (
                   5572:                                     corrchkd     => '1.0',
                   5573:                                     corrunchkd   => '1.0',
                   5574:                                     incorrchkd   => '0.0',
                   5575:                                     incorrunchkd => '0.0',
                   5576:                     );
                   5577:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5578:                         $textval{'corrchkd'} = $1;
                   5579:                         $textval{'corrunchkd'} = $2;
                   5580:                         $textval{'incorrchkd'} = $3;
                   5581:                         $textval{'incorrunchkd'} = $4;
                   5582:                         $display = 'inline';
                   5583:                         $showval = $name;
                   5584:                     } else {
                   5585:                         $display = 'none';
                   5586:                     }
                   5587:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5588:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5589:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5590:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5591:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5592:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5593:                                 '</td></tr>';
                   5594:                     }
                   5595:                     $add .= '</table></div>'."\n";
                   5596:                 }
                   5597:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5598:                 $css_class = ' class="LC_lenient_radio"';
                   5599:             }
                   5600:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5601:                        '<span class="LC_nobreak"><label>'.
                   5602:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5603:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5604:             if ($showval eq $name) {
                   5605:                 $result .= ' checked="checked"';
                   5606:             }
1.549     raeburn  5607:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5608:             $i++;
                   5609:         }
                   5610:         $result .= '</tr>';
1.473     amueller 5611:     }
1.504     raeburn  5612:     if ($result) {
                   5613:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5614:     }
                   5615:     return $result;
                   5616: }
                   5617: 
1.554     raeburn  5618: my %intervals =
                   5619:     (
                   5620:      'date_interval'
                   5621:              => [[ 'done', 'Yes' ],
1.558     raeburn  5622:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5623:                  [ '', 'No' ]],
                   5624:     );
                   5625: 
                   5626: my %intervalmatches = (
                   5627:          'date_interval'
1.559     raeburn  5628:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5629:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5630:     );
                   5631: 
                   5632: my %intervaltypes = (
                   5633:                       interval => 'date_interval',
                   5634:     );
                   5635: 
1.563     damieng  5636: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5637: #
                   5638: # @param {string} $interval_type - a parameter type for intervals
                   5639: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5640: sub standard_interval_matches {
                   5641:     my ($interval_type) = @_;
                   5642:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5643:         return $intervalmatches{$interval_type};
                   5644:     }
                   5645:     return;
                   5646: }
                   5647: 
1.563     damieng  5648: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5649: #
                   5650: # @param {string} $name - parameter name
                   5651: # @returns {string}
1.554     raeburn  5652: sub get_intervaltype {
                   5653:     my ($name) = @_;
                   5654:     if (exists($intervaltypes{$name})) {
                   5655:         return $intervaltypes{$name};
                   5656:     }
                   5657:     return;
                   5658: }
                   5659: 
1.563     damieng  5660: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5661: # Used by courseprefs.
                   5662: #
                   5663: # @param {string} $interval_type - a parameter type for intervals
                   5664: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5665: sub standard_interval_options {
                   5666:     my ($interval_type) = @_;
                   5667:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5668:         return $intervals{$interval_type};
                   5669:     }
                   5670:     return;
                   5671: }
                   5672: 
1.563     damieng  5673: # Returns HTML to edit a date interval parameter.
                   5674: #
                   5675: # @param {string} $thiskey - parameter key
                   5676: # @param {string} $name - parameter name
                   5677: # @param {string} $showval - parameter current value
                   5678: # @param {boolean} $readonly - true if the values should not be made editable
                   5679: # @returns {string}
1.554     raeburn  5680: sub date_interval_selector {
                   5681:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5682:     my ($result,%skipval);
                   5683:     if ($name eq 'interval') {
                   5684:         my $intervaltype = &get_intervaltype($name);
                   5685:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5686:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5687:             next unless (ref($possibilities) eq 'ARRAY');
                   5688:             my ($parmval, $description) = @{ $possibilities };
                   5689:             my $parmmatch;
                   5690:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5691:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5692:                     if (ref($item) eq 'ARRAY') {
                   5693:                         if ($parmval eq $item->[0]) {
                   5694:                             $parmmatch = $parmval;
                   5695:                             $parmval = '';
                   5696:                             last;
                   5697:                         }
                   5698:                     }
                   5699:                 }
                   5700:             }
                   5701:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5702:             if ($needsrelease) {
                   5703:                 unless ($got_chostname) {
                   5704:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5705:                     $got_chostname = 1;
                   5706:                 }
1.557     raeburn  5707:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5708:                                                        $needsrelease,$cmajor,$cminor);
                   5709:                 if ($needsnewer) {
                   5710:                     if ($parmmatch ne '') {
                   5711:                         $skipval{$parmmatch} = 1;
                   5712:                     } elsif ($parmval ne '') {
                   5713:                         $skipval{$parmval} = 1;
                   5714:                     }
                   5715:                 }
                   5716:             }
                   5717:         }
                   5718:     }
                   5719: 
                   5720:     my $currval = $showval;
                   5721:     foreach my $which (['days', 86400, 31],
                   5722:                ['hours', 3600, 23],
                   5723:                ['minutes', 60, 59],
                   5724:                ['seconds',  1, 59]) {
1.560     damieng  5725:         my ($name, $factor, $max) = @{ $which };
                   5726:         my $amount = int($showval/$factor);
                   5727:         $showval  %= $factor;
                   5728:         my %select = ((map {$_ => $_} (0..$max)),
                   5729:                 'select_form_order' => [0..$max]);
1.611   ! raeburn  5730:         if ($currval eq '') {
        !          5731:             unshift(@{$select{'select_form_order'}},'');
        !          5732:             $select{''} = '';
        !          5733:             $amount = '';
        !          5734:         }
1.560     damieng  5735:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5736:                             \%select,'',$readonly);
                   5737:         $result .= ' '.&mt($name);
1.554     raeburn  5738:     }
                   5739:     if ($name eq 'interval') {
                   5740:         unless ($skipval{'done'}) {
                   5741:             my $checkedon = '';
1.611   ! raeburn  5742:             my $checkedoff = '';
1.558     raeburn  5743:             my $checkedproc = '';
                   5744:             my $currproctorkey = '';
                   5745:             my $currprocdisplay = 'hidden';
1.559     raeburn  5746:             my $currdonetext = &mt('Done');
                   5747:             if ($currval =~ /^(?:\d+)_done$/) {
                   5748:                 $checkedon = ' checked="checked"';
                   5749:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5750:                 $currdonetext = $1;
1.554     raeburn  5751:                 $checkedon = ' checked="checked"';
1.558     raeburn  5752:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5753:                 $currproctorkey = $1;
                   5754:                 $checkedproc = ' checked="checked"';
                   5755:                 $currprocdisplay = 'text';
1.559     raeburn  5756:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5757:                 $currdonetext = $1;
                   5758:                 $currproctorkey = $2;
                   5759:                 $checkedproc = ' checked="checked"';
                   5760:                 $currprocdisplay = 'text';
1.611   ! raeburn  5761:             } elsif ($currval ne '') {
        !          5762:                 $checkedoff = ' checked="checked"';
        !          5763:             } else {
        !          5764:                 $currdonetext = '';
1.554     raeburn  5765:             }
1.558     raeburn  5766:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5767:             my $disabled;
                   5768:             if ($readonly) {
                   5769:                 $disabled = ' disabled="disabled"';
                   5770:             }
1.558     raeburn  5771:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5772:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5773:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5774:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5775:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5776:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5777:                        &mt('Yes, with proctor key').'</label>'.
                   5778:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5779:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5780:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611   ! raeburn  5781:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
        !          5782:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5783:         }
                   5784:     }
                   5785:     unless ($readonly) {
                   5786:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5787:     }
                   5788:     return $result;
                   5789: }
                   5790: 
1.563     damieng  5791: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5792: #
                   5793: # @param {string} $name - parameter name
                   5794: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5795: # @param {string} $value - parameter value
                   5796: # @param {string} $chostname - course server name
                   5797: # @param {integer} $cmajor - major version number
                   5798: # @param {integer} $cminor - minor version number
                   5799: # @param {string} $needsrelease - release version needed (major.minor)
                   5800: # @returns {string}
1.549     raeburn  5801: sub oldversion_warning {
1.557     raeburn  5802:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5803:     my $standard_name = &standard_parameter_names($name);
                   5804:     if ($namematch) {
                   5805:         my $level = &standard_parameter_levels($namematch);
                   5806:         my $msg = '';
                   5807:         if ($level) {
                   5808:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5809:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5810:         } else {
                   5811:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5812:                       $standard_name,'<b>','</b>');
                   5813:         }
                   5814:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5815:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5816:                    $cmajor.'.'.$cminor,$chostname,
                   5817:                    $needsrelease).
                   5818:                    '</p>';
                   5819:     }
1.549     raeburn  5820:     my $desc;
                   5821:     my $stringtype = &get_stringtype($name);
                   5822:     if ($stringtype ne '') {
                   5823:         if ($name eq 'examcode') {
                   5824:             $desc = $value;
                   5825:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5826:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5827:                 next unless (ref($possibilities) eq 'ARRAY');
                   5828:                 my ($parmval, $description) = @{ $possibilities };
                   5829:                 my $parmmatch;
                   5830:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5831:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5832:                         if (ref($item) eq 'ARRAY') {
                   5833:                             my ($regexpname,$pattern) = @{$item};
                   5834:                             if ($parmval eq $regexpname) {
                   5835:                                 if ($value =~ /$pattern/) {
                   5836:                                     $desc = $description; 
                   5837:                                     $parmmatch = 1;
                   5838:                                     last;
                   5839:                                 }
                   5840:                             }
                   5841:                         }
                   5842:                     }
                   5843:                     last if ($parmmatch);
                   5844:                 } elsif ($parmval eq $value) {
                   5845:                     $desc = $description;
                   5846:                     last;
                   5847:                 }
                   5848:             }
                   5849:         }
                   5850:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5851:         my $now = time;
                   5852:         if ($value =~ /^\d+$/) {
                   5853:             if ($name eq 'printstartdate') {
                   5854:                 if ($value > $now) {
                   5855:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5856:                 }
                   5857:             } elsif ($name eq 'printenddate') {
                   5858:                 if ($value < $now) {
                   5859:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5860:                 }
                   5861:             }
                   5862:         }
                   5863:     }
                   5864:     return '<p class="LC_warning">'.
1.557     raeburn  5865:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5866:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5867:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5868:        $cmajor.'.'.$cminor,$chostname,
                   5869:        $needsrelease).
                   5870:        '</p>';
1.549     raeburn  5871: }
                   5872: 
1.560     damieng  5873: } # end of block using some constants related to parameter types
                   5874: 
1.549     raeburn  5875: 
1.563     damieng  5876: 
                   5877: # Shifts all start and end dates in the current course by $shift.
1.389     www      5878: #
1.563     damieng  5879: # @param {integer} $shift - time to shift, in seconds
                   5880: # @returns {string} - error name or 'ok'
1.389     www      5881: sub dateshift {
1.594     raeburn  5882:     my ($shift,$numchanges)=@_;
1.389     www      5883:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5884:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5885:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5886:     my $secgrpregex;
                   5887:     if ($sec ne '') {
                   5888:         my @groups;
                   5889:         if ($env{'request.course.groups'} ne '') {
                   5890:             @groups = split(/:/,$env{'request.course.groups'});
                   5891:         }
                   5892:         if (@groups) {
                   5893:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   5894:         } else {
                   5895:             $secgrpregex = $sec;
                   5896:         }
                   5897:     }
1.389     www      5898:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5899: # ugly retro fix for broken version of types
1.548     raeburn  5900:     foreach my $key (keys(%data)) {
1.389     www      5901:         if ($key=~/\wtype$/) {
                   5902:             my $newkey=$key;
                   5903:             $newkey=~s/type$/\.type/;
                   5904:             $data{$newkey}=$data{$key};
                   5905:             delete $data{$key};
                   5906:         }
                   5907:     }
1.391     www      5908:     my %storecontent=();
1.389     www      5909: # go through all parameters and look for dates
1.548     raeburn  5910:     foreach my $key (keys(%data)) {
1.389     www      5911:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  5912:           if ($sec ne '') {
1.595     raeburn  5913:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  5914:           }
1.389     www      5915:           my $newdate=$data{$key}+$shift;
1.594     raeburn  5916:           $$numchanges ++;
1.391     www      5917:           $storecontent{$key}=$newdate;
1.389     www      5918:        }
                   5919:     }
1.391     www      5920:     my $reply=&Apache::lonnet::cput
                   5921:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5922:     if ($reply eq 'ok') {
                   5923:        &log_parmset(\%storecontent);
                   5924:     }
                   5925:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5926:     return $reply;
1.389     www      5927: }
                   5928: 
1.563     damieng  5929: # Overview mode UI to edit course parameters.
                   5930: #
                   5931: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5932: sub newoverview {
1.568     raeburn  5933:     my ($r,$parm_permission) = @_;
1.280     albertel 5934: 
1.208     www      5935:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5936:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5937:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5938:     my $readonly = 1;
                   5939:     if ($parm_permission->{'edit'}) {
                   5940:         undef($readonly);
                   5941:     }
1.414     droeschl 5942:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5943:         text=>"Overview Mode"});
1.523     raeburn  5944: 
                   5945:     my %loaditems = (
1.549     raeburn  5946:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5947:                     );
                   5948:     my $js = '
                   5949: <script type="text/javascript">
                   5950: // <![CDATA[
                   5951: '.
                   5952:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5953:             &showhide_js()."\n".
1.549     raeburn  5954:             &toggleparmtextbox_js()."\n".
                   5955:             &validateparms_js()."\n".
                   5956:             &ipacc_boxes_js()."\n".
1.558     raeburn  5957:             &done_proctor_js()."\n".
1.588     raeburn  5958:             &deeplink_js()."\n".
1.523     raeburn  5959: '// ]]>
                   5960: </script>
                   5961: ';
1.549     raeburn  5962: 
1.523     raeburn  5963:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5964:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5965:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5966:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5967:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5968:     $r->print(<<ENDOVER);
1.549     raeburn  5969: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5970: ENDOVER
1.211     www      5971:     my @ids=();
                   5972:     my %typep=();
                   5973:     my %keyp=();
                   5974:     my %allparms=();
                   5975:     my %allparts=();
                   5976:     my %allmaps=();
                   5977:     my %mapp=();
                   5978:     my %symbp=();
                   5979:     my %maptitles=();
                   5980:     my %uris=();
                   5981:     my %keyorder=&standardkeyorder();
                   5982:     my %defkeytype=();
                   5983: 
                   5984:     my %alllevs=();
                   5985:     $alllevs{'Resource Level'}='full';
1.215     www      5986:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5987:     $alllevs{'Course Level'}='general';
                   5988: 
                   5989:     my $csec=$env{'form.csec'};
1.269     raeburn  5990:     my $cgroup=$env{'form.cgroup'};
1.211     www      5991: 
                   5992:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5993:     my $pschp=$env{'form.pschp'};
1.506     www      5994: 
1.211     www      5995:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5996:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5997: 
1.446     bisitz   5998:     my @selected_sections =
1.473     amueller 5999:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6000:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6001:     foreach my $sec (@selected_sections) {
                   6002:         if ($sec eq 'all') {
1.211     www      6003:             @selected_sections = ('all');
                   6004:         }
                   6005:     }
1.552     raeburn  6006:     if ($env{'request.course.sec'} ne '') {
                   6007:         @selected_sections = ($env{'request.course.sec'});
                   6008:     }
1.269     raeburn  6009:     my @selected_groups =
                   6010:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6011: 
                   6012:     my $pssymb='';
                   6013:     my $parmlev='';
1.446     bisitz   6014: 
1.211     www      6015:     unless ($env{'form.parmlev'}) {
                   6016:         $parmlev = 'map';
                   6017:     } else {
                   6018:         $parmlev = $env{'form.parmlev'};
                   6019:     }
                   6020: 
1.446     bisitz   6021:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6022:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6023:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6024: 
1.374     albertel 6025:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6026:         @psprt = keys(%allparts);
1.374     albertel 6027:     }
1.211     www      6028: # Menu to select levels, etc
                   6029: 
1.456     bisitz   6030:     $r->print('<div class="LC_Box">');
1.445     neumanie 6031:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6032:     $r->print('<div>');
1.523     raeburn  6033:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6034:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6035:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6036:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6037:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6038:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6039:     $r->print('</div></div>');
1.446     bisitz   6040: 
1.456     bisitz   6041:     $r->print('<div class="LC_Box">');
1.452     bisitz   6042:     $r->print('<div>');
1.581     raeburn  6043:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6044:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6045:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6046:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6047:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6048:     $r->print('<table>'.
1.553     raeburn  6049:               '<tr><th>'.&mt('Parts').'</th>');
                   6050:     if ($sectionselector) {
                   6051:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6052:     }
                   6053:     if ($groupselector) {
                   6054:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6055:     }
                   6056:     $r->print('</tr><tr><td>');
1.211     www      6057:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6058:     $r->print('</td>');
                   6059:     if ($sectionselector) { 
                   6060:         $r->print('<td>'.$sectionselector.'</td>');
                   6061:     }
                   6062:     if ($groupselector) {
                   6063:         $r->print('<td>'.$groupselector.'</td>');
                   6064:     }
                   6065:     $r->print('</tr></table>');
1.447     bisitz   6066:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6067:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6068:     $r->print('</div></div>');
                   6069: 
1.456     bisitz   6070:     $r->print('<div class="LC_Box">');
1.452     bisitz   6071:     $r->print('<div>');
1.214     www      6072:     my $sortorder=$env{'form.sortorder'};
                   6073:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6074:     &sortmenu($r,$sortorder,'newoverview'));
1.445     neumanie 6075:     $r->print('</div></div>');
1.446     bisitz   6076: 
1.214     www      6077:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6078: 
1.211     www      6079: # Build the list data hash from the specified parms
                   6080: 
                   6081:     my $listdata;
                   6082:     %{$listdata}=();
                   6083: 
                   6084:     foreach my $cat (@pscat) {
1.269     raeburn  6085:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6086:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6087:     }
                   6088: 
1.212     www      6089:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6090: 
1.481     amueller 6091:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6092: 
                   6093: # Read modified data
                   6094: 
1.481     amueller 6095:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6096: 
                   6097: # List data
                   6098: 
1.608     raeburn  6099:         my $hash_for_realm;
                   6100:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6101:             %{$hash_for_realm} = reverse(%allmaps);
                   6102:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6103:             for (my $i=0; $i<@ids; $i++) {
                   6104:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6105:             }
                   6106:         }
                   6107:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6108:     }
                   6109:     $r->print(&tableend());
                   6110:     unless ($readonly) {
                   6111:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6112:     }
1.568     raeburn  6113:     $r->print('</form>');
1.507     www      6114:     &endSettingsScreen($r);
                   6115:     $r->print(&Apache::loncommon::end_page());
1.208     www      6116: }
                   6117: 
1.563     damieng  6118: # Fills $listdata with parameter information.
                   6119: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6120: # The non-type value is always 1.
                   6121: #
                   6122: # @param {string} $cat - parameter name
1.566     damieng  6123: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6124: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6125: # @param {hash reference} $listdata - the parameter data that will be modified
                   6126: # @param {array reference} $psprt - selected parts
                   6127: # @param {array reference} $selections - selected sections
                   6128: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6129: # @param {hash reference} $allmaps - hash map pc -> map src
                   6130: # @param {array reference} $ids - resource and map ids
                   6131: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6132: sub secgroup_lister {
                   6133:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6134:     foreach my $item (@{$selections}) {
                   6135:         foreach my $part (@{$psprt}) {
                   6136:             my $rootparmkey=$env{'request.course.id'};
                   6137:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6138:                 $rootparmkey.='.['.$item.']';
                   6139:             }
                   6140:             if ($parmlev eq 'general') {
                   6141: # course-level parameter
                   6142:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6143:                 $$listdata{$newparmkey}=1;
                   6144:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6145:             } elsif ($parmlev eq 'map') {
                   6146: # map-level parameter
1.548     raeburn  6147:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6148:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6149:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6150:                     $$listdata{$newparmkey}=1;
                   6151:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6152:                 }
                   6153:             } else {
                   6154: # resource-level parameter
                   6155:                 foreach my $rid (@{$ids}) {
                   6156:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6157:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6158:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6159:                     $$listdata{$newparmkey}=1;
                   6160:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6161:                 }
                   6162:             }
                   6163:         }
                   6164:     }
                   6165: }
                   6166: 
1.563     damieng  6167: # UI to edit parameter settings starting with a list of all existing parameters.
                   6168: # (called by setoverview action)
                   6169: #
                   6170: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6171: sub overview {
1.568     raeburn  6172:     my ($r,$parm_permission) = @_;
1.208     www      6173:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6174:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6175:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6176:     my $readonly = 1;
                   6177:     if ($parm_permission->{'edit'}) {
                   6178:         undef($readonly);
                   6179:     }
1.549     raeburn  6180:     my $js = '<script type="text/javascript">'."\n".
                   6181:              '// <![CDATA['."\n".
                   6182:              &toggleparmtextbox_js()."\n".
                   6183:              &validateparms_js()."\n".
                   6184:              &ipacc_boxes_js()."\n".
1.558     raeburn  6185:              &done_proctor_js()."\n".
1.588     raeburn  6186:              &deeplink_js()."\n".
1.549     raeburn  6187:              '// ]]>'."\n".
                   6188:              '</script>'."\n";
1.414     droeschl 6189:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6190:     text=>"Overview Mode"});
1.549     raeburn  6191:     my %loaditems = (
                   6192:                       'onload'   => "showHideLenient();",
                   6193:                     );
                   6194: 
                   6195:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6196:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6197:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6198:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6199:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6200: 
1.208     www      6201: # Store modified
                   6202: 
1.568     raeburn  6203:     unless ($readonly) {
                   6204:         &storedata($r,$crs,$dom);
                   6205:     }
1.208     www      6206: 
                   6207: # Read modified data
                   6208: 
1.552     raeburn  6209:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6210: 
1.214     www      6211: 
                   6212:     my $sortorder=$env{'form.sortorder'};
                   6213:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6214:     &sortmenu($r,$sortorder,'overview');
1.214     www      6215: 
1.568     raeburn  6216:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6217: 
                   6218:     if ($readonly) {
                   6219:         $r->print('<p>'.$submitbutton.'</p>');
                   6220:     }
                   6221: 
1.208     www      6222: # List data
                   6223: 
1.568     raeburn  6224:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6225:     $r->print(&tableend().'<p>');
                   6226:     if ($foundkeys) {
                   6227:         unless ($readonly) {
                   6228:             $r->print('<p>'.$submitbutton.'</p>');
                   6229:         }
                   6230:     } else {
                   6231:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6232:     }
                   6233:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6234: }
1.121     www      6235: 
1.560     damieng  6236: # Unused sub.
1.563     damieng  6237: #
                   6238: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6239: sub clean_parameters {
                   6240:     my ($r) = @_;
                   6241:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6242:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6243: 
1.414     droeschl 6244:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6245:         text=>"Clean Parameters"});
1.333     albertel 6246:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6247:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6248:     $r->print(<<ENDOVER);
                   6249: $start_page
                   6250: $breadcrumbs
                   6251: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6252: ENDOVER
                   6253: # Store modified
                   6254: 
                   6255:     &storedata($r,$crs,$dom);
                   6256: 
                   6257: # Read modified data
                   6258: 
                   6259:     my $resourcedata=&readdata($crs,$dom);
                   6260: 
                   6261: # List data
                   6262: 
                   6263:     $r->print('<h3>'.
1.473     amueller 6264:           &mt('These parameters refer to resources that do not exist.').
                   6265:           '</h3>'.
                   6266:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6267:           '<br />');
1.333     albertel 6268:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6269:           '<tr>'.
                   6270:           '<th>'.&mt('Delete').'</th>'.
                   6271:           '<th>'.&mt('Parameter').'</th>'.
                   6272:           '</tr>');
1.333     albertel 6273:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6274:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6275:             && $thiskey=~/\.type$/);
                   6276:         my %data = &parse_key($thiskey);
                   6277:         if (1) { #exists($data{'realm_exists'})
                   6278:             #&& !$data{'realm_exists'}) {
                   6279:             $r->print(&Apache::loncommon::start_data_table_row().
                   6280:                 '<tr>'.
                   6281:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6282: 
                   6283:             $r->print('<td>');
                   6284:             my $display_value = $resourcedata->{$thiskey};
                   6285:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6286:             $display_value =
                   6287:                 &Apache::lonlocal::locallocaltime($display_value);
                   6288:             }
1.470     raeburn  6289:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6290:             $parmitem = &mt($parmitem);
1.560     damieng  6291:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6292:                 $parmitem,$resourcedata->{$thiskey}));
                   6293:             $r->print('<br />');
                   6294:             if ($data{'scope_type'} eq 'all') {
                   6295:                 $r->print(&mt('All users'));
                   6296:             } elsif ($data{'scope_type'} eq 'user') {
                   6297:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6298:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6299:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6300:             }
                   6301:             $r->print('<br />');
                   6302:             if ($data{'realm_type'} eq 'all') {
                   6303:                 $r->print(&mt('All Resources'));
                   6304:             } elsif ($data{'realm_type'} eq 'folder') {
                   6305:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6306:             } elsif ($data{'realm_type'} eq 'symb') {
                   6307:             my ($map,$resid,$url) =
                   6308:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6309:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6310:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6311:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6312:             }
                   6313:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6314:             $r->print('</td></tr>');
                   6315: 
1.473     amueller 6316:         }
1.333     albertel 6317:     }
                   6318:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6319:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6320:           '</p></form>');
                   6321:     &endSettingsScreen($r);
                   6322:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6323: }
                   6324: 
1.563     damieng  6325: # UI to shift all dates (called by dateshift1 action).
                   6326: # Used by overview mode.
                   6327: #
                   6328: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6329: sub date_shift_one {
                   6330:     my ($r) = @_;
                   6331:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6332:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6333:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6334:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6335:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6336:         text=>"Shifting Dates"});
1.594     raeburn  6337:     my $submit_text = &mt('Shift all dates accordingly');
                   6338:     if ($sec ne '') {
1.595     raeburn  6339:         my @groups;
                   6340:         if ($env{'request.course.groups'} ne '') {
                   6341:             @groups = split(/:/,$env{'request.course.groups'});
                   6342:         }
                   6343:         if (@groups) {
                   6344:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6345:         } else {
                   6346:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6347:         }
1.594     raeburn  6348:     }
1.390     www      6349:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6350:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6351:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6352:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6353:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6354:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6355:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6356:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6357:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6358:                                                         'timeshifted',
                   6359:                                                         $env{'form.timebase'},,
                   6360:                                                         '').
                   6361:               '</td></tr></table>'.
                   6362:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6363:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6364:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6365:     &endSettingsScreen($r);
1.390     www      6366:     $r->print(&Apache::loncommon::end_page());
                   6367: }
                   6368: 
1.563     damieng  6369: # UI to shift all dates (second form).
                   6370: #
                   6371: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6372: sub date_shift_two {
                   6373:     my ($r) = @_;
                   6374:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6375:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6376:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6377:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6378:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6379:         text=>"Shifting Dates"});
1.390     www      6380:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6381:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6382:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6383:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6384:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6385:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6386:     if ($sec ne '') {
1.595     raeburn  6387:         my @groups;
                   6388:         if ($env{'request.course.groups'} ne '') {
                   6389:             @groups = split(/:/,$env{'request.course.groups'});
                   6390:         }
                   6391:         if (@groups) {
                   6392:             $r->print('<p>'.
                   6393:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6394:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6395:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6396:                       '</p>');
                   6397:         } else {
                   6398:             $r->print('<p>'.
                   6399:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6400:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6401:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6402:                       '</p>');
                   6403:         }
1.594     raeburn  6404:     } else {
                   6405:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6406:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6407:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6408:                   '</p>');
                   6409:     }
1.390     www      6410:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6411:     my $numchanges = 0;
                   6412:     my $result = &dateshift($delta,\$numchanges);
                   6413:     if ($result eq 'ok') {
                   6414:         $r->print(
                   6415:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6416:                                                     $numchanges)));
                   6417:     } elsif ($result eq 'con_delayed') {
                   6418:         $r->print(
                   6419:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6420:                                                         $numchanges)));
                   6421:     } else {
                   6422:         $r->print(
                   6423:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6424:     }
1.543     bisitz   6425:     $r->print(
                   6426:         '<br /><br />'.
                   6427:         &Apache::lonhtmlcommon::actionbox(
                   6428:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6429:     &endSettingsScreen($r);
1.390     www      6430:     $r->print(&Apache::loncommon::end_page());
                   6431: }
                   6432: 
1.563     damieng  6433: # Returns the different components of a resourcedata key.
                   6434: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6435: #       realm_exists, parameter_part, parameter_name.
                   6436: # Was used by clean_parameters (which is unused).
                   6437: #
                   6438: # @param {string} $key - the parameter key
                   6439: # @returns {hash}
1.333     albertel 6440: sub parse_key {
                   6441:     my ($key) = @_;
                   6442:     my %data;
                   6443:     my ($middle,$part,$name)=
1.572     damieng  6444:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6445:     $data{'scope_type'} = 'all';
                   6446:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6447:         $data{'scope'} = $1;
                   6448:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6449:             $data{'scope_type'} = 'user';
                   6450:             $data{'scope'} = [$1,$2];
                   6451:         } else {
1.581     raeburn  6452:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6453:         }
                   6454:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6455:     }
                   6456:     $middle=~s/\.+$//;
                   6457:     $middle=~s/^\.+//;
                   6458:     $data{'realm_type'}='all';
                   6459:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6460:         $data{'realm'} = $1;
                   6461:         $data{'realm_type'} = 'folder';
                   6462:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6463:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6464:     } elsif ($middle) {
1.560     damieng  6465:         $data{'realm'} = $middle;
                   6466:         $data{'realm_type'} = 'symb';
                   6467:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6468:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6469:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6470:     }
1.446     bisitz   6471: 
1.333     albertel 6472:     $data{'parameter_part'} = $part;
                   6473:     $data{'parameter_name'} = $name;
                   6474: 
                   6475:     return %data;
                   6476: }
                   6477: 
1.239     raeburn  6478: 
1.563     damieng  6479: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6480: sub header {
1.507     www      6481:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6482: }
1.193     albertel 6483: 
                   6484: 
                   6485: 
1.560     damieng  6486: ##################################################
                   6487: # MAIN MENU
                   6488: ##################################################
                   6489: 
1.563     damieng  6490: # Content and problem settings main menu.
                   6491: #
                   6492: # @param {Apache2::RequestRec} $r - the Apache request
                   6493: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6494: sub print_main_menu {
                   6495:     my ($r,$parm_permission)=@_;
                   6496:     #
1.414     droeschl 6497:     $r->print(&header());
1.507     www      6498:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6499:     my $crstype = &Apache::loncommon::course_type();
                   6500:     my $lc_crstype = lc($crstype);
                   6501: 
                   6502:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6503:     $r->print(<<ENDMAINFORMHEAD);
                   6504: <form method="post" enctype="multipart/form-data"
                   6505:       action="/adm/parmset" name="studentform">
                   6506: ENDMAINFORMHEAD
                   6507: #
1.195     albertel 6508:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6509:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6510:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6511:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6512:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6513:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6514:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6515:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6516:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6517:                                         '/'.$env{'request.course.sec'});
                   6518:     }
1.568     raeburn  6519:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6520:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6521:                                         '/'.$env{'request.course.sec'});
                   6522:     }
                   6523:     my (%linktext,%linktitle,%url);
                   6524:     if ($parm_permission->{'edit'}) {
                   6525:         %linktext = (
                   6526:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6527:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6528:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6529:                     );
                   6530:         %linktitle = (
                   6531:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6532:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6533:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6534:                      );
                   6535:     } else {
                   6536:         %linktext = (
                   6537:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6538:                      settable        => 'View Resource Parameters - Table Mode',
                   6539:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6540:                    );
                   6541:         %linktitle = (
                   6542:                      newoverview     => 'Display resource parameters in overview mode.',
                   6543:                      settable        => 'Display resource parameters in table mode.',
                   6544:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6545:                      );
                   6546:     }
                   6547:     if ($mgr) {
                   6548:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6549:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6550:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6551:     } elsif ($vgr) {
                   6552:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6553:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6554:         $url{'resettimes'} = '/adm/accesstimes';
                   6555:     }
1.193     albertel 6556:     my @menu =
1.507     www      6557:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6558:         items => [
                   6559:           { linktext => 'Portfolio Metadata',
                   6560:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6561:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6562:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6563:             icon =>'contact-new.png'   ,
                   6564:             },
1.568     raeburn  6565:           { linktext => $linktext{'resettimes'},
                   6566:             url => $url{'resettimes'},
                   6567:             permission => ($vgr || $mgr),
                   6568:             linktitle => $linktitle{'resettimes'},
                   6569:             icon => 'start-here.png',
1.473     amueller 6570:             },
1.520     raeburn  6571:           { linktext => 'Blocking Communication/Resource Access',
                   6572:             url => '/adm/setblock',
1.568     raeburn  6573:             permission => ($vcb || $dcm),
1.520     raeburn  6574:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6575:             icon => 'comblock.png',
                   6576:             },
1.473     amueller 6577:           { linktext => 'Set Parameter Setting Default Actions',
                   6578:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6579:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6580:             linktitle =>'Set default actions for parameters.'  ,
                   6581:             icon => 'folder-new.png'  ,
                   6582:             }]},
                   6583:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6584:         items => [
                   6585:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6586:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6587:             permission => $parm_permission->{'helper'},
1.473     amueller 6588:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6589:             icon => 'dialog-information.png'  ,
                   6590:             #help => 'Parameter_Helper',
                   6591:             },
1.568     raeburn  6592:           { linktext => $linktext{'newoverview'},
1.473     amueller 6593:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6594:             permission => $parm_permission->{'newoverview'},
                   6595:             linktitle => $linktitle{'newoverview'},
                   6596:             icon => 'edit-find.png',
1.473     amueller 6597:             #help => 'Parameter_Overview',
                   6598:             },
1.568     raeburn  6599:           { linktext => $linktext{'settable'},
1.473     amueller 6600:             url => '/adm/parmset?action=settable',
1.568     raeburn  6601:             permission => $parm_permission->{'settable'},
                   6602:             linktitle => $linktitle{'settable'},
                   6603:             icon => 'edit-copy.png',
1.473     amueller 6604:             #help => 'Table_Mode',
                   6605:             }]},
1.417     droeschl 6606:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6607:          items => [
1.570     raeburn  6608:           { linktext => $linktext{'setoverview'},
1.473     amueller 6609:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6610:             permission => $parm_permission->{'setoverview'},
                   6611:             linktitle => $linktitle{'setoverview'},
                   6612:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6613:             #help => 'Parameter_Overview',
                   6614:             },
                   6615:           { linktext => 'Change Log',
                   6616:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6617:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6618:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6619:             icon => 'document-properties.png',
1.473     amueller 6620:             }]}
1.193     albertel 6621:           );
1.414     droeschl 6622:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6623:     $r->print('</form>');
1.507     www      6624:     &endSettingsScreen($r);
1.539     raeburn  6625:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6626:     return;
                   6627: }
1.414     droeschl 6628: 
1.416     jms      6629: 
                   6630: 
1.560     damieng  6631: ##################################################
                   6632: # PORTFOLIO METADATA
                   6633: ##################################################
                   6634: 
1.563     damieng  6635: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6636: # It looks like field titles are not localized.
                   6637: #
                   6638: # @param {Apache2::RequestRec} $r - the Apache request
                   6639: # @param {string} $field_name - metadata field name
                   6640: # @param {string} $field_text - metadata field title, in English unless manually added
                   6641: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6642: sub output_row {
1.347     banghart 6643:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6644:     my $output;
1.263     banghart 6645:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6646:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6647:     if (!defined($options)) {
1.254     banghart 6648:         $options = 'active,stuadd';
1.261     banghart 6649:         $values = '';
1.252     banghart 6650:     }
1.337     banghart 6651:     if (!($options =~ /deleted/)) {
                   6652:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6653:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6654:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6655: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6656:         if ($added_flag) {
                   6657:             push @options,['deleted', 'Delete Metadata Field'];
                   6658:         }
1.351     banghart 6659:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6660:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6661:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6662:         foreach my $opt (@options) {
1.560     damieng  6663:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6664:             $output .= &Apache::loncommon::continue_data_table_row();
                   6665:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6666:                     <input type="checkbox" name="'.
                   6667:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6668:                     &mt($opt->[1]).'</label></td>';
                   6669:             $output .= &Apache::loncommon::end_data_table_row();
                   6670:         }
1.351     banghart 6671:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6672:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6673:         $output .= &Apache::loncommon::end_data_table_row();
                   6674:         my $multiple_checked;
                   6675:         my $single_checked;
                   6676:         if ($options =~ m/onlyone/) {
1.422     bisitz   6677:             $multiple_checked = '';
1.423     bisitz   6678:             $single_checked = ' checked="checked"';
1.351     banghart 6679:         } else {
1.423     bisitz   6680:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6681:             $single_checked = '';
1.351     banghart 6682:         }
1.560     damieng  6683:         $output .= &Apache::loncommon::continue_data_table_row();
                   6684:         $output .= '<td>'.('&nbsp;' x 10).'
                   6685:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6686:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6687:         $output .= &Apache::loncommon::end_data_table_row();
                   6688:         $output .= &Apache::loncommon::continue_data_table_row();
                   6689:         $output .= '<td>'.('&nbsp;' x 10).'
                   6690:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6691:                     '.&mt('Student may select only one choice from list').'</td>';
                   6692:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6693:     }
                   6694:     return ($output);
                   6695: }
1.416     jms      6696: 
                   6697: 
1.560     damieng  6698: # UI to order portfolio metadata fields.
1.563     damieng  6699: # Currently useless because addmetafield does not work.
                   6700: #
                   6701: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6702: sub order_meta_fields {
                   6703:     my ($r)=@_;
                   6704:     my $idx = 1;
                   6705:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6706:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6707:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6708:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6709:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6710:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6711:         text=>"Add Metadata Field"});
1.560     damieng  6712:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6713:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6714:         text=>"Restrict Metadata"},
                   6715:         {text=>"Order Metadata"});
1.345     banghart 6716:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6717:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6718:     if ($env{'form.storeorder'}) {
                   6719:         my $newpos = $env{'form.newpos'} - 1;
                   6720:         my $currentpos = $env{'form.currentpos'} - 1;
                   6721:         my @neworder = ();
1.548     raeburn  6722:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6723:         my $i;
1.341     banghart 6724:         if ($newpos > $currentpos) {
1.340     banghart 6725:         # moving stuff up
                   6726:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6727:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6728:             }
                   6729:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6730:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6731:             }
                   6732:             $neworder[$newpos]=$oldorder[$currentpos];
                   6733:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6734:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6735:             }
                   6736:         } else {
                   6737:         # moving stuff down
1.473     amueller 6738:             for ($i=0;$i<$newpos;$i++) {
                   6739:                 $neworder[$i]=$oldorder[$i];
                   6740:             }
                   6741:             $neworder[$newpos]=$oldorder[$currentpos];
                   6742:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6743:                 $neworder[$i]=$oldorder[$i-1];
                   6744:             }
                   6745:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6746:                 $neworder[$i]=$oldorder[$i];
                   6747:             }
1.340     banghart 6748:         }
1.560     damieng  6749:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6750:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6751:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6752:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6753:     }
1.357     raeburn  6754:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6755:     my $ordered_fields;
1.548     raeburn  6756:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6757:     if (!@fields_in_order) {
                   6758:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6759:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6760:             push @fields_in_order, $key;
1.341     banghart 6761:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6762:         }
1.341     banghart 6763:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6764:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6765:     }
1.340     banghart 6766:     $r->print('<table>');
                   6767:     my $num_fields = scalar(@fields_in_order);
                   6768:     foreach my $key (@fields_in_order) {
                   6769:         $r->print('<tr><td>');
                   6770:         $r->print('<form method="post" action="">');
1.537     bisitz   6771:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6772:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6773:             if ($i eq $idx) {
                   6774:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6775:             } else {
                   6776:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6777:             }
                   6778:         }
                   6779:         $r->print('</select></td><td>');
                   6780:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6781:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6782:         $r->print('</form>');
                   6783:         $r->print($$fields{$key}.'</td></tr>');
                   6784:         $idx ++;
                   6785:     }
                   6786:     $r->print('</table>');
1.507     www      6787:     &endSettingsScreen($r);
1.340     banghart 6788:     return 'ok';
                   6789: }
1.416     jms      6790: 
                   6791: 
1.563     damieng  6792: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6793: # @returns {string}
1.359     banghart 6794: sub continue {
                   6795:     my $output;
                   6796:     $output .= '<form action="" method="post">';
                   6797:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6798:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6799:     return ($output);
                   6800: }
1.416     jms      6801: 
                   6802: 
1.563     damieng  6803: # UI to add a metadata field.
                   6804: # Currenly does not work because of an HTML error (the field is not visible).
                   6805: #
                   6806: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6807: sub addmetafield {
                   6808:     my ($r)=@_;
1.414     droeschl 6809:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6810:         text=>"Add Metadata Field"});
1.334     banghart 6811:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6812:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6813:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6814:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6815:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6816:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6817:     if (exists($env{'form.undelete'})) {
1.358     banghart 6818:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6819:         foreach my $meta_field(@meta_fields) {
                   6820:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6821:             $options =~ s/deleted//;
                   6822:             $options =~ s/,,/,/;
                   6823:             my $put_result = &Apache::lonnet::put('environment',
                   6824:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6825: 
1.586     raeburn  6826:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6827:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6828:                           '</strong>',$put_result).
                   6829:                       '<br />');
1.339     banghart 6830:         }
1.359     banghart 6831:         $r->print(&continue());
1.339     banghart 6832:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6833:         my $meta_field = $env{'form.fieldname'};
                   6834:         my $display_field = $env{'form.fieldname'};
                   6835:         $meta_field =~ s/\W/_/g;
1.338     banghart 6836:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6837:         my $put_result = &Apache::lonnet::put('environment',
                   6838:                             {'metadata.'.$meta_field.'.values'=>"",
                   6839:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6840:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6841:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6842:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6843:                   '<br />');
1.359     banghart 6844:         $r->print(&continue());
1.335     banghart 6845:     } else {
1.357     raeburn  6846:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6847:         if ($fields) {
1.586     raeburn  6848:             $r->print(&mt('You may undelete previously deleted fields.').
                   6849:                       '<br />'.
                   6850:                       &mt('Check those you wish to undelete and click Undelete.').
                   6851:                       '<br />');
1.339     banghart 6852:             $r->print('<form method="post" action="">');
                   6853:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6854:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6855:             }
1.586     raeburn  6856:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6857:             $r->print('</form>');
                   6858:         }
1.586     raeburn  6859:         $r->print('<hr />'.
                   6860:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6861:                       '<strong>','</strong>').
1.581     raeburn  6862:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6863:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6864:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6865:         $r->print('</form>');
1.334     banghart 6866:     }
1.507     www      6867:     &endSettingsScreen($r);
1.334     banghart 6868: }
1.416     jms      6869: 
                   6870: 
                   6871: 
1.560     damieng  6872: # Display or save portfolio metadata.
1.563     damieng  6873: #
                   6874: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6875: sub setrestrictmeta {
1.240     banghart 6876:     my ($r)=@_;
1.242     banghart 6877:     my $next_meta;
1.244     banghart 6878:     my $output;
1.245     banghart 6879:     my $item_num;
1.246     banghart 6880:     my $put_result;
1.414     droeschl 6881:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6882:         text=>"Restrict Metadata"});
1.280     albertel 6883:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6884:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6885:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6886:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6887:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6888:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6889:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6890:     my $save_field = '';
1.586     raeburn  6891:     my %lt = &Apache::lonlocal::texthash(
                   6892:                                            addm => 'Add Metadata Field',
                   6893:                                            ordm => 'Order Metadata Fields',
                   6894:                                            save => 'Save',
                   6895:                                         );
1.259     banghart 6896:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6897:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6898:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6899:                 my $options;
1.252     banghart 6900:                 my $meta_field = $1;
                   6901:                 my $meta_key = $2;
1.253     banghart 6902:                 if ($save_field ne $meta_field) {
1.252     banghart 6903:                     $save_field = $meta_field;
1.473     amueller 6904:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6905:                         $options.='stuadd,';
                   6906:                     }
                   6907:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6908:                         $options.='choices,';
                   6909:                     }
                   6910:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6911:                         $options.='onlyone,';
                   6912:                     }
                   6913:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6914:                         $options.='active,';
                   6915:                     }
                   6916:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6917:                         $options.='deleted,';
                   6918:                     }
1.259     banghart 6919:                     my $name = $save_field;
1.560     damieng  6920:                     $put_result = &Apache::lonnet::put('environment',
                   6921:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6922:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6923:                         },$dom,$crs);
1.252     banghart 6924:                 }
                   6925:             }
                   6926:         }
                   6927:     }
1.296     albertel 6928:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6929:                        {'freshen_cache' => 1});
1.335     banghart 6930:     # Get the default metadata fields
1.258     albertel 6931:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6932:     # Now get possible added metadata fields
1.357     raeburn  6933:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6934:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6935:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6936:         if ($field ne 'courserestricted') {
1.586     raeburn  6937:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6938:         }
1.255     banghart 6939:     }
1.351     banghart 6940:     my $buttons = (<<ENDButtons);
1.586     raeburn  6941:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6942:         </form><br />
                   6943:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6944:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6945:         </form>
                   6946:         <br />
                   6947:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6948:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6949: ENDButtons
1.337     banghart 6950:     my $added_flag = 1;
1.335     banghart 6951:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6952:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6953:     }
1.347     banghart 6954:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6955:     $r->print(<<ENDenv);
1.259     banghart 6956:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6957:         $output
1.351     banghart 6958:         $buttons
1.340     banghart 6959:         </form>
1.244     banghart 6960: ENDenv
1.507     www      6961:     &endSettingsScreen($r);
1.280     albertel 6962:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6963:     return 'ok';
                   6964: }
1.416     jms      6965: 
                   6966: 
1.563     damieng  6967: # Returns metadata fields that have been manually added.
                   6968: #
                   6969: # @param {string} $cid - course id
                   6970: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6971: sub get_added_meta_fieldnames {
1.357     raeburn  6972:     my ($cid) = @_;
1.335     banghart 6973:     my %fields;
                   6974:     foreach my $key(%env) {
1.357     raeburn  6975:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6976:             my $field_name = $1;
                   6977:             my ($display_field_name) = $env{$key};
                   6978:             $fields{$field_name} = $display_field_name;
                   6979:         }
                   6980:     }
                   6981:     return \%fields;
                   6982: }
1.416     jms      6983: 
                   6984: 
1.563     damieng  6985: # Returns metadata fields that have been manually added and deleted.
                   6986: #
                   6987: # @param {string} $cid - course id
                   6988: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6989: sub get_deleted_meta_fieldnames {
1.357     raeburn  6990:     my ($cid) = @_;
1.339     banghart 6991:     my %fields;
                   6992:     foreach my $key(%env) {
1.357     raeburn  6993:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6994:             my $field_name = $1;
                   6995:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6996:                 my ($display_field_name) = $env{$key};
                   6997:                 $fields{$field_name} = $display_field_name;
                   6998:             }
                   6999:         }
                   7000:     }
                   7001:     return \%fields;
                   7002: }
1.560     damieng  7003: 
                   7004: 
                   7005: ##################################################
                   7006: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7007: ##################################################
                   7008: 
                   7009: # UI to change parameter setting default actions
1.563     damieng  7010: #
                   7011: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7012: sub defaultsetter {
1.280     albertel 7013:     my ($r) = @_;
                   7014: 
1.414     droeschl 7015:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7016:         text=>"Set Defaults"});
1.531     raeburn  7017:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7018:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7019:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7020:     my $start_page =
1.531     raeburn  7021:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7022:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7023:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7024:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7025:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7026: 
1.221     www      7027:     my @ids=();
                   7028:     my %typep=();
                   7029:     my %keyp=();
                   7030:     my %allparms=();
                   7031:     my %allparts=();
                   7032:     my %allmaps=();
                   7033:     my %mapp=();
                   7034:     my %symbp=();
                   7035:     my %maptitles=();
                   7036:     my %uris=();
                   7037:     my %keyorder=&standardkeyorder();
                   7038:     my %defkeytype=();
                   7039: 
1.446     bisitz   7040:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7041:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7042:                 \%keyorder,\%defkeytype);
1.224     www      7043:     if ($env{'form.storerules'}) {
1.560     damieng  7044:         my %newrules=();
                   7045:         my @delrules=();
                   7046:         my %triggers=();
                   7047:         foreach my $key (keys(%env)) {
1.225     albertel 7048:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7049:                 my $tempkey=$1;
                   7050:                 my $action=$env{$key};
1.226     www      7051:                 if ($action) {
1.560     damieng  7052:                     $newrules{$tempkey.'_action'}=$action;
                   7053:                     if ($action ne 'default') {
                   7054:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7055:                         $triggers{$whichparm}.=$tempkey.':';
                   7056:                     }
                   7057:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7058:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7059:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7060:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7061:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7062:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7063:                     } else {
                   7064:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7065:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7066:                     }
                   7067:                 } else {
                   7068:                     push(@delrules,$tempkey.'_action');
                   7069:                     push(@delrules,$tempkey.'_type');
                   7070:                     push(@delrules,$tempkey.'_hours');
                   7071:                     push(@delrules,$tempkey.'_min');
                   7072:                     push(@delrules,$tempkey.'_sec');
                   7073:                     push(@delrules,$tempkey.'_value');
                   7074:                 }
1.473     amueller 7075:             }
                   7076:         }
1.560     damieng  7077:         foreach my $key (keys(%allparms)) {
                   7078:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7079:         }
1.560     damieng  7080:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7081:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7082:         &resetrulescache();
1.224     www      7083:     }
1.227     www      7084:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7085:                        'hours' => 'Hours',
                   7086:                        'min' => 'Minutes',
                   7087:                        'sec' => 'Seconds',
                   7088:                        'yes' => 'Yes',
                   7089:                        'no' => 'No');
1.222     www      7090:     my @standardoptions=('','default');
                   7091:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7092:     my @dateoptions=('','default');
                   7093:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7094:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7095:         unless ($tempkey) { next; }
                   7096:         push @standardoptions,'when_setting_'.$tempkey;
                   7097:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7098:         if (&isdateparm($defkeytype{$tempkey})) {
                   7099:             push @dateoptions,'later_than_'.$tempkey;
                   7100:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7101:             push @dateoptions,'earlier_than_'.$tempkey;
                   7102:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7103:         }
1.222     www      7104:     }
1.563     damieng  7105:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7106:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7107:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7108:           &Apache::loncommon::start_data_table_header_row().
                   7109:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7110:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7111:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7112:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7113:         unless ($tempkey) { next; }
                   7114:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7115:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7116:         my $action=&rulescache($tempkey.'_action');
                   7117:         $r->print('<select name="'.$tempkey.'_action">');
                   7118:         if (&isdateparm($defkeytype{$tempkey})) {
                   7119:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7120:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7121:             $r->print("\n<option value='$dateoptions[$i]'".
                   7122:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7123:                 ">$datedisplay[$i]</option>");
                   7124:             }
                   7125:         } else {
                   7126:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7127:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7128:             $r->print("\n<option value='$standardoptions[$i]'".
                   7129:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7130:                 ">$standarddisplay[$i]</option>");
                   7131:             }
1.473     amueller 7132:         }
1.560     damieng  7133:         $r->print('</select>');
                   7134:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7135:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7136:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7137:         }
1.560     damieng  7138:         $r->print("\n</td><td>\n");
1.222     www      7139: 
1.221     www      7140:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7141:             my $days=&rulescache($tempkey.'_days');
                   7142:             my $hours=&rulescache($tempkey.'_hours');
                   7143:             my $min=&rulescache($tempkey.'_min');
                   7144:             my $sec=&rulescache($tempkey.'_sec');
                   7145:             $r->print(<<ENDINPUTDATE);
                   7146:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7147:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7148:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7149:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7150: ENDINPUTDATE
1.560     damieng  7151:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7152:                 my $yeschecked='';
                   7153:                 my $nochecked='';
                   7154:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7155:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7156: 
                   7157:             $r->print(<<ENDYESNO);
                   7158:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7159:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7160: ENDYESNO
1.221     www      7161:         } else {
1.560     damieng  7162:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7163:         }
1.318     albertel 7164:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7165:     }
1.318     albertel 7166:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7167:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7168:           &mt('Save').'" /></form>'."\n");
                   7169:     &endSettingsScreen($r);
                   7170:     $r->print(&Apache::loncommon::end_page());
1.220     www      7171:     return;
                   7172: }
1.193     albertel 7173: 
1.560     damieng  7174: ##################################################
                   7175: # PARAMETER CHANGES LOG
                   7176: ##################################################
                   7177: 
1.563     damieng  7178: # Returns some info for a parameter log entry.
                   7179: # Returned entries:
                   7180: # $realm - HTML title for the parameter level and resource
                   7181: # $section - parameter section
                   7182: # $name - parameter name
                   7183: # $part - parameter part
                   7184: # $what - $part.'.'.$name
                   7185: # $middle - resource symb ?
                   7186: # $uname - user name (same as given)
                   7187: # $udom - user domain (same as given)
                   7188: # $issection - section or group name
                   7189: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7190: #
                   7191: # @param {string} $key - parameter log key
                   7192: # @param {string} $uname - user name
                   7193: # @param {string} $udom - user domain
                   7194: # @param {boolean} $typeflag - .type log entry
                   7195: # @returns {Array}
1.290     www      7196: sub components {
1.581     raeburn  7197:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7198: 
                   7199:     if ($typeflag) {
1.560     damieng  7200:         $key=~s/\.type$//;
1.290     www      7201:     }
1.330     albertel 7202: 
                   7203:     my ($middle,$part,$name)=
1.572     damieng  7204:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7205:     my $issection;
1.330     albertel 7206: 
1.290     www      7207:     my $section=&mt('All Students');
                   7208:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7209:         $issection=$1;
                   7210:         $section=&mt('Group/Section').': '.$issection;
                   7211:         $middle=~s/^\[(.*)\]//;
1.290     www      7212:     }
                   7213:     $middle=~s/\.+$//;
                   7214:     $middle=~s/^\.+//;
1.291     www      7215:     if ($uname) {
1.560     damieng  7216:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7217:         $issection='';
1.291     www      7218:     }
1.316     albertel 7219:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7220:     my $realmdescription=&mt('all resources');
1.556     raeburn  7221:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7222:         my $mapurl = $1;
                   7223:         my $maplevel = $2;
                   7224:         my $leveltitle = &mt('Folder/Map');
                   7225:         if ($maplevel eq 'rec') {
                   7226:             $leveltitle = &mt('Recursive');
                   7227:         }
1.560     damieng  7228:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7229:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7230:             $mapurl.')</span></span>';
                   7231:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7232:     } elsif ($middle) {
                   7233:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7234:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7235:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7236:             ' in '.$map.' id: '.$id.')</span></span>';
                   7237:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7238:     }
1.291     www      7239:     my $what=$part.'.'.$name;
1.330     albertel 7240:     return ($realm,$section,$name,$part,
1.473     amueller 7241:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7242: }
1.293     www      7243: 
1.563     damieng  7244: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7245: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7246: 
1.563     damieng  7247: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7248: sub load_parameter_names {
1.583     raeburn  7249:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7250:     while (my $configline=<$config>) {
1.560     damieng  7251:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7252:         chomp($configline);
                   7253:         my ($short,$plain)=split(/:/,$configline);
                   7254:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7255:         if ($type eq 'display') {
                   7256:             $standard_parms{$name} = $plain;
1.469     raeburn  7257:         } elsif ($type eq 'type') {
1.560     damieng  7258:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7259:         }
1.328     albertel 7260:     }
                   7261:     close($config);
                   7262:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7263:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7264:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7265: }
                   7266: 
1.563     damieng  7267: # Returns a parameter title for standard parameters, the name for others.
                   7268: #
                   7269: # @param {string} $name - parameter name
                   7270: # @returns {string}
1.292     www      7271: sub standard_parameter_names {
                   7272:     my ($name)=@_;
1.328     albertel 7273:     if (!%standard_parms) {
1.560     damieng  7274:         &load_parameter_names();
1.328     albertel 7275:     }
1.292     www      7276:     if ($standard_parms{$name}) {
1.560     damieng  7277:         return $standard_parms{$name};
1.446     bisitz   7278:     } else {
1.560     damieng  7279:         return $name;
1.292     www      7280:     }
                   7281: }
1.290     www      7282: 
1.563     damieng  7283: # Returns a parameter type for standard parameters, undef for others.
                   7284: #
                   7285: # @param {string} $name - parameter name
                   7286: # @returns {string}
1.469     raeburn  7287: sub standard_parameter_types {
                   7288:     my ($name)=@_;
                   7289:     if (!%standard_parms_types) {
                   7290:         &load_parameter_names();
                   7291:     }
                   7292:     if ($standard_parms_types{$name}) {
                   7293:         return $standard_parms_types{$name};
                   7294:     }
                   7295:     return;
                   7296: }
1.309     www      7297: 
1.563     damieng  7298: # Returns a parameter level title (not localized) from the parameter level name.
                   7299: #
                   7300: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7301: # @returns {string}
1.557     raeburn  7302: sub standard_parameter_levels {
                   7303:     my ($name)=@_;
                   7304:     my %levels = (
                   7305:                     'resourcelevel'   => 'a single resource',
                   7306:                     'maplevel'        => 'the enclosing map/folder', 
                   7307:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7308:                     'courselevel'     => 'the general (course) level',
                   7309:                  );
                   7310:     if ($levels{$name}) {
                   7311:         return $levels{$name};
                   7312:     }
                   7313:     return;
                   7314: }
                   7315: 
1.560     damieng  7316: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7317: #
                   7318: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7319: sub parm_change_log {
1.568     raeburn  7320:     my ($r,$parm_permission)=@_;
1.531     raeburn  7321:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7322:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7323:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7324:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7325:     text=>"Parameter Change Log"});
1.522     raeburn  7326:     my $js = '<script type="text/javascript">'."\n".
                   7327:              '// <![CDATA['."\n".
                   7328:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7329:              '// ]]>'."\n".
                   7330:              '</script>'."\n";
                   7331:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7332:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7333:     &startSettingsScreen($r,'parmset',$crstype);
                   7334:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7335: 
1.301     www      7336:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7337: 
1.522     raeburn  7338:     $r->print('<div class="LC_left_float">'.
                   7339:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7340:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7341:                      method="post" name="parameterlog">');
1.446     bisitz   7342: 
1.311     albertel 7343:     my %saveable_parameters = ('show' => 'scalar',);
                   7344:     &Apache::loncommon::store_course_settings('parameter_log',
                   7345:                                               \%saveable_parameters);
                   7346:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7347:                                                 \%saveable_parameters);
1.522     raeburn  7348:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7349:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7350:               '</form></fieldset></div><br clear="all" />');
1.301     www      7351: 
1.568     raeburn  7352:     my $readonly = 1;
                   7353:     if ($parm_permission->{'edit'}) {
                   7354:         undef($readonly);
                   7355:     }
1.531     raeburn  7356:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7357:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7358:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7359:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7360:     unless ($readonly) {
                   7361:         $r->print('<th>'.&mt('Announce').'</th>');
                   7362:     }
                   7363:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7364:     my $shown=0;
1.349     www      7365:     my $folder='';
                   7366:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7367:         my $last='';
                   7368:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7369:                 &GDBM_READER(),0640)) {
                   7370:             $last=$hash{'last_known'};
                   7371:             untie(%hash);
                   7372:         }
                   7373:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7374:     }
1.595     raeburn  7375:     my $numgroups = 0;
                   7376:     my @groups;
                   7377:     if ($env{'request.course.groups'} ne '') {
                   7378:         @groups = split(/:/,$env{'request.course.groups'});
                   7379:         $numgroups = scalar(@groups);
                   7380:     }
1.560     damieng  7381:     foreach my $id (sort {
                   7382:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7383:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7384:                 }
                   7385:                 my $aid = (split('00000',$a))[-1];
                   7386:                 my $bid = (split('00000',$b))[-1];
                   7387:                 return $bid<=>$aid;
1.473     amueller 7388:             } (keys(%parmlog))) {
1.294     www      7389:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7390:         my $count = 0;
                   7391:         my $time =
                   7392:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7393:         my $plainname =
                   7394:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7395:                         $parmlog{$id}{'exe_udom'});
                   7396:         my $about_me_link =
                   7397:             &Apache::loncommon::aboutmewrapper($plainname,
                   7398:                             $parmlog{$id}{'exe_uname'},
                   7399:                             $parmlog{$id}{'exe_udom'});
                   7400:         my $send_msg_link='';
1.568     raeburn  7401:         if ((!$readonly) && 
                   7402:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7403:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7404:             $send_msg_link ='<br />'.
                   7405:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7406:                             $parmlog{$id}{'exe_uname'},
                   7407:                             $parmlog{$id}{'exe_udom'});
                   7408:         }
                   7409:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7410:         my $makenewrow=0;
                   7411:         my %istype=();
                   7412:         my $output;
                   7413:         foreach my $changed (reverse(sort(@changes))) {
                   7414:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7415:             my $typeflag = ($changed =~/\.type$/ &&
                   7416:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7417:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7418:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7419:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7420:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7421:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7422:                 if ($uname ne '') {
                   7423:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7424:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7425:                 }
                   7426:             }
                   7427:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7428:                 if ($folder) {
                   7429:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7430:                 }
                   7431:             }
                   7432:             if ($typeflag) {
                   7433:                 $istype{$parmname}=$value;
                   7434:                 if (!$env{'form.includetypes'}) { next; }
                   7435:             }
                   7436:             $count++;
                   7437:             if ($makenewrow) {
                   7438:                 $output .= $row_start;
                   7439:             } else {
                   7440:                 $makenewrow=1;
                   7441:             }
1.470     raeburn  7442:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7443:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7444:                 &mt($parmitem).'</td><td>'.
                   7445:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7446:             my $stillactive=0;
                   7447:             if ($parmlog{$id}{'delflag'}) {
                   7448:                 $output .= &mt('Deleted');
                   7449:             } else {
                   7450:                 if ($typeflag) {
1.470     raeburn  7451:                     my $parmitem = &standard_parameter_names($value); 
                   7452:                     $parmitem = &mt($parmitem);
1.560     damieng  7453:                     $output .= &mt('Type: [_1]',$parmitem);
                   7454:                 } else {
1.584     raeburn  7455:                     my $toolsymb;
                   7456:                     if ($middle =~ /ext\.tool$/) {
                   7457:                         $toolsymb = $middle;
                   7458:                     }
1.560     damieng  7459:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7460:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7461:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7462:                     my $showvalue = $value;
                   7463:                     if ($istype{$parmname} eq '') {
                   7464:                         my $type = &standard_parameter_types($parmname);
                   7465:                         if ($type ne '') {
                   7466:                             if (&isdateparm($type)) {
                   7467:                                 $showvalue =
                   7468:                                     &Apache::lonlocal::locallocaltime($value);
                   7469:                             }
                   7470:                         }
                   7471:                     } else {
1.560     damieng  7472:                         if (&isdateparm($istype{$parmname})) {
                   7473:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7474:                         }
1.469     raeburn  7475:                     }
                   7476:                     $output .= $showvalue;
1.560     damieng  7477:                     if ($value ne $all[$level]) {
                   7478:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7479:                     } else {
                   7480:                         $stillactive=1;
                   7481:                     }
                   7482:                 }
1.473     amueller 7483:             }
1.568     raeburn  7484:             $output .= '</td>';
                   7485: 
                   7486:             unless ($readonly) { 
                   7487:                 $output .= '<td>';
                   7488:                 if ($stillactive) {
                   7489:                     my $parmitem = &standard_parameter_names($parmname);
                   7490:                     $parmitem = &mt($parmitem);
                   7491:                     my $title=&mt('Changed [_1]',$parmitem);
                   7492:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7493:                         $parmitem,$realmdescription,
                   7494:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7495:                     if (($uname) && ($udom)) {
                   7496:                         $output .=
                   7497:                         &Apache::loncommon::messagewrapper('Notify User',
                   7498:                                                            $uname,$udom,$title,
                   7499:                                                            $description);
                   7500:                     } else {
                   7501:                         $output .=
                   7502:                             &Apache::lonrss::course_blog_link($id,$title,
                   7503:                                                               $description);
                   7504:                     }
1.560     damieng  7505:                 }
1.568     raeburn  7506:                 $output .= '</td>';
1.560     damieng  7507:             }
1.568     raeburn  7508:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7509:         }
1.560     damieng  7510:         if ($env{'form.displayfilter'} eq 'containing') {
                   7511:             my $wholeentry=$about_me_link.':'.
                   7512:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7513:             $output;
                   7514:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7515:         }
1.349     www      7516:         if ($count) {
1.560     damieng  7517:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7518:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7519:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7520:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7521:             $send_msg_link.'</td>'.$output);
                   7522:             $shown++;
                   7523:         }
                   7524:         if (!($env{'form.show'} eq &mt('all')
                   7525:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7526:     }
1.301     www      7527:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7528:     &endSettingsScreen($r);
1.284     www      7529:     $r->print(&Apache::loncommon::end_page());
                   7530: }
                   7531: 
1.560     damieng  7532: ##################################################
                   7533: # MISC !
                   7534: ##################################################
                   7535: 
1.563     damieng  7536: # Stores slot information.
1.560     damieng  7537: # Used by table UI
1.563     damieng  7538: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7539: #
                   7540: # @param {string} $slot_name - slot name
                   7541: # @param {string} $cdom - course domain
                   7542: # @param {string} $cnum - course number
                   7543: # @param {string} $symb - resource symb
                   7544: # @param {string} $uname - user name
                   7545: # @param {string} $udom - user domain
                   7546: # @returns {string} - 'ok' or error name
1.437     raeburn  7547: sub update_slots {
                   7548:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7549:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7550:     if (!keys(%slot)) {
                   7551:         return 'error: slot does not exist';
                   7552:     }
                   7553:     my $max=$slot{'maxspace'};
                   7554:     if (!defined($max)) { $max=99999; }
                   7555: 
                   7556:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7557:                                        "^$slot_name\0");
                   7558:     my ($tmp)=%consumed;
                   7559:     if ($tmp=~/^error: 2 / ) {
                   7560:         return 'error: unable to determine current slot status';
                   7561:     }
                   7562:     my $last=0;
                   7563:     foreach my $key (keys(%consumed)) {
                   7564:         my $num=(split('\0',$key))[1];
                   7565:         if ($num > $last) { $last=$num; }
                   7566:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7567:             return 'ok';
                   7568:         }
                   7569:     }
                   7570: 
                   7571:     if (scalar(keys(%consumed)) >= $max) {
                   7572:         return 'error: no space left in slot';
                   7573:     }
                   7574:     my $wanted=$last+1;
                   7575: 
                   7576:     my %reservation=('name'      => $uname.':'.$udom,
                   7577:                      'timestamp' => time,
                   7578:                      'symb'      => $symb);
                   7579: 
                   7580:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7581:                                         {"$slot_name\0$wanted" =>
                   7582:                                              \%reservation},
                   7583:                                         $cdom, $cnum);
1.438     raeburn  7584:     if ($success eq 'ok') {
                   7585:         my %storehash = (
                   7586:                           symb    => $symb,
                   7587:                           slot    => $slot_name,
                   7588:                           action  => 'reserve',
                   7589:                           context => 'parameter',
                   7590:                         );
1.526     raeburn  7591:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7592:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7593: 
1.526     raeburn  7594:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7595:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7596:     }
1.437     raeburn  7597:     return $success;
                   7598: }
                   7599: 
1.563     damieng  7600: # Deletes a slot reservation.
1.560     damieng  7601: # Used by table UI
1.563     damieng  7602: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7603: #
                   7604: # @param {string} $slot_name - slot name
                   7605: # @param {string} $cdom - course domain
                   7606: # @param {string} $cnum - course number
                   7607: # @param {string} $uname - user name
                   7608: # @param {string} $udom - user domain
                   7609: # @param {string} $symb - resource symb
                   7610: # @returns {string} - 'ok' or error name
1.437     raeburn  7611: sub delete_slots {
                   7612:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7613:     my $delresult;
                   7614:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7615:                                          $cnum, "^$slot_name\0");
                   7616:     if (&Apache::lonnet::error(%consumed)) {
                   7617:         return 'error: unable to determine current slot status';
                   7618:     }
                   7619:     my ($tmp)=%consumed;
                   7620:     if ($tmp=~/^error: 2 /) {
                   7621:         return 'error: unable to determine current slot status';
                   7622:     }
                   7623:     foreach my $key (keys(%consumed)) {
                   7624:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7625:             my $num=(split('\0',$key))[1];
                   7626:             my $entry = $slot_name.'\0'.$num;
                   7627:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7628:                                               $cdom,$cnum);
                   7629:             if ($delresult eq 'ok') {
                   7630:                 my %storehash = (
                   7631:                                   symb    => $symb,
                   7632:                                   slot    => $slot_name,
                   7633:                                   action  => 'release',
                   7634:                                   context => 'parameter',
                   7635:                                 );
1.526     raeburn  7636:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7637:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7638:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7639:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7640:             }
                   7641:         }
                   7642:     }
                   7643:     return $delresult;
                   7644: }
                   7645: 
1.563     damieng  7646: # Returns true if there is a current course.
1.560     damieng  7647: # Used by handler
1.563     damieng  7648: #
                   7649: # @returns {boolean}
1.355     albertel 7650: sub check_for_course_info {
                   7651:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7652:     return 1 if ($navmap);
                   7653:     return 0;
                   7654: }
                   7655: 
1.563     damieng  7656: # Returns the current course host and host LON-CAPA version.
                   7657: #
                   7658: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7659: sub parameter_release_vars { 
1.504     raeburn  7660:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7661:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7662:    my $chostname = &Apache::lonnet::hostname($chome);
                   7663:    my ($cmajor,$cminor) = 
                   7664:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7665:    return ($chostname,$cmajor,$cminor);
                   7666: }
                   7667: 
1.563     damieng  7668: # Checks if the course host version can handle a parameter required version,
                   7669: # and if it does, stores the release needed for the course.
                   7670: #
                   7671: # @param {string} $name - parameter name
                   7672: # @param {string} $value - parameter value
                   7673: # @param {string} $valmatch - name of the test used for checking the value
                   7674: # @param {string} $namematch - name of the test used for checking the name
                   7675: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7676: # @param {integer} $cmajor - course major version number
                   7677: # @param {integer} $cminor - course minor version number
                   7678: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7679: sub parameter_releasecheck {
1.557     raeburn  7680:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7681:     my $needsnewer;
                   7682:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7683:     if (($cmajor < $needsmajor) || 
                   7684:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7685:         $needsnewer = 1;
1.557     raeburn  7686:     } elsif ($name) {
                   7687:         if ($valmatch) {
                   7688:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7689:         } elsif ($value) { 
                   7690:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7691:         }
                   7692:     } elsif ($namematch) {
                   7693:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7694:     }
                   7695:     return $needsnewer;
                   7696: }
                   7697: 
1.568     raeburn  7698: sub get_permission {
                   7699:     my %permission;
                   7700:     my $allowed = 0;
                   7701:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7702:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7703:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7704:                   $env{'request.course.sec'}))) {
                   7705:         %permission= (
                   7706:                        'edit'               => 1,
                   7707:                        'set'                => 1,
                   7708:                        'setoverview'        => 1,
                   7709:                        'addmetadata'        => 1,
                   7710:                        'ordermetadata'      => 1,
                   7711:                        'setrestrictmeta'    => 1,
                   7712:                        'newoverview'        => 1,
                   7713:                        'setdefaults'        => 1,
                   7714:                        'settable'           => 1,
                   7715:                        'parameterchangelog' => 1,
                   7716:                        'cleanparameters'    => 1,
                   7717:                        'dateshift1'         => 1,
                   7718:                        'dateshift2'         => 1,
                   7719:                        'helper'             => 1,
                   7720:          );
                   7721:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7722:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7723:                   $env{'request.course.sec'}))) {
                   7724:         %permission = (
                   7725:                        'set'                => 1,
                   7726:                        'settable'           => 1,
                   7727:                        'newoverview'        => 1,
                   7728:                        'setoverview'        => 1,
                   7729:                        'parameterchangelog' => 1,
                   7730:                       );
                   7731:     }
                   7732:     foreach my $perm (values(%permission)) {
                   7733:         if ($perm) { $allowed=1; last; }
                   7734:     }
                   7735:     return (\%permission,$allowed);
                   7736: }
                   7737: 
1.560     damieng  7738: ##################################################
                   7739: # HANDLER
                   7740: ##################################################
                   7741: 
                   7742: # Main handler for lonparmset.
                   7743: # Sub called based on request parameters action and command:
                   7744: # no command or action: print_main_menu
                   7745: # command 'set': assessparms (direct access to table mode for a resource)
                   7746: #                (this can also be accessed simply with the symb parameter)
                   7747: # action 'setoverview': overview (display all existing parameter settings)
                   7748: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7749: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7750: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7751: # action 'newoverview': newoverview (overview mode)
                   7752: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7753: # action 'settable': assessparms (table mode)
                   7754: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7755: #                              blog postings, user notification changes)
                   7756: # action 'cleanparameters': clean_parameters (unused)
                   7757: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7758: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7759: sub handler {
1.43      albertel 7760:     my $r=shift;
1.30      www      7761: 
1.376     albertel 7762:     &reset_caches();
                   7763: 
1.414     droeschl 7764:     &Apache::loncommon::content_type($r,'text/html');
                   7765:     $r->send_http_header;
                   7766:     return OK if $r->header_only;
                   7767: 
1.193     albertel 7768:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7769:                         ['action','state',
1.205     www      7770:                                              'pres_marker',
                   7771:                                              'pres_value',
1.206     www      7772:                                              'pres_type',
1.506     www      7773:                                              'filter','part',
1.390     www      7774:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7775: 
1.83      bowersj2 7776: 
1.193     albertel 7777:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7778:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7779:                         text=>"Content and Problem Settings",
1.473     amueller 7780:                         faq=>10,
                   7781:                         bug=>'Instructor Interface',
1.442     droeschl 7782:                                             help =>
                   7783:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7784: 
1.30      www      7785: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7786:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7787:     my $exists = &check_for_course_info();
                   7788: 
1.568     raeburn  7789:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7790:         #
                   7791:         # Main switch on form.action and form.state, as appropriate
                   7792:         #
                   7793:         # Check first if coming from someone else headed directly for
                   7794:         #  the table mode
1.568     raeburn  7795:         if (($parm_permission->{'set'}) && 
                   7796:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7797:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7798:             &assessparms($r,$parm_permission);
1.193     albertel 7799:         } elsif (! exists($env{'form.action'})) {
                   7800:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7801:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7802:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7803:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7804:             &overview($r,$parm_permission);
1.560     damieng  7805:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7806:             &addmetafield($r);
                   7807:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7808:             &order_meta_fields($r);
1.414     droeschl 7809:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7810:             &setrestrictmeta($r);
1.414     droeschl 7811:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7812:             &newoverview($r,$parm_permission);
1.414     droeschl 7813:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7814:             &defaultsetter($r);
                   7815:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7816:             &assessparms($r,$parm_permission);
1.414     droeschl 7817:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7818:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7819:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7820:             &clean_parameters($r);
1.414     droeschl 7821:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7822:             &date_shift_one($r);
1.414     droeschl 7823:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7824:             &date_shift_two($r);
1.446     bisitz   7825:         }
1.43      albertel 7826:     } else {
1.1       www      7827: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7828:         if ($exists) {
                   7829:             $env{'user.error.msg'}=
                   7830:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7831:         } else {
                   7832:             $env{'user.error.msg'}=
                   7833:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7834:         }
                   7835:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7836:     }
1.376     albertel 7837:     &reset_caches();
                   7838: 
1.43      albertel 7839:     return OK;
1.1       www      7840: }
                   7841: 
                   7842: 1;
                   7843: __END__
                   7844: 
                   7845: 

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