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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.616   ! raeburn     4: # $Id: lonparmset.pm,v 1.615 2022/07/03 04:31:07 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.613     raeburn  1255:     var dlTargetRegExp = /^deeplink_target_/;
1.616   ! raeburn  1256:     var dlExitRegExp = /^deeplink_exit_/;
        !          1257:     var dlExitTextRegExp = /^deeplink_exittext_/;
1.549     raeburn  1258:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
1.616   ! raeburn  1259:     var numelements = document.parmform.elements.length;
        !          1260:     if ((typeof(numelements) != 'undefined') && (numelements != null)) {
        !          1261:         if (numelements) {
        !          1262:             for (i=0; i<numelements; i++) {
1.549     raeburn  1263:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1264:                 if (textRegExp.test(name)) {
1.549     raeburn  1265:                     var identifier = name.replace(textRegExp,'');
                   1266:                     if (tailLenient.test(identifier)) {
                   1267:                         if (document.parmform.elements['set_'+identifier].length) {
                   1268:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1269:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1270:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1271:                                         var relweight = document.parmform.elements[i].value;
                   1272:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1273:                                         if (!patternRelWeight.test(relweight)) {
                   1274:                                             relweight = '0.0';
                   1275:                                         }
                   1276:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1277:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1278:                                         } else {
                   1279:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1280:                                         }
                   1281:                                     }
                   1282:                                     break;
                   1283:                                 }
                   1284:                             }
                   1285:                         }
                   1286:                     }
1.597     raeburn  1287:                 } else if (ipRegExp.test(name)) {
                   1288:                     if (ipallowRegExp.test(name)) {
                   1289:                         var identifier = name.replace(ipallowRegExp,'');
                   1290:                         var possallow = document.parmform.elements[i].value;
                   1291:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1292:                         if (patternIP.test(possallow)) {
                   1293:                             if (document.parmform.elements['set_'+identifier].value) {
                   1294:                                 possallow = ','+possallow;
                   1295:                             }
                   1296:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1297:                         }
                   1298:                     } else if (ipdenyRegExp.test(name)) {
                   1299:                         var identifier = name.replace(ipdenyRegExp,'');
                   1300:                         var possdeny = document.parmform.elements[i].value;
                   1301:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1302:                         if (patternIP.test(possdeny)) {
                   1303:                             possdeny = '!'+possdeny;
                   1304:                             if (document.parmform.elements['set_'+identifier].value) {
                   1305:                                 possdeny = ','+possdeny;
                   1306:                             }
                   1307:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1308:                         }
                   1309:                     }
                   1310:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1311:                     if (dlListScopeRegExp.test(name)) {
                   1312:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1313:                         var idx = document.parmform.elements[i].selectedIndex;
                   1314:                         if (idx > 0) { 
                   1315:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1316:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1317:                             if (document.parmform.elements['set_'+identifier].value) {
                   1318:                                 possdeeplink = ','+possdeeplink;
                   1319:                             }
                   1320:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1321:                         }
1.601     raeburn  1322:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1323:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1324:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1325:                             var posslinkurl = document.parmform.elements[i].value;
                   1326:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1327:                             if (document.parmform.elements['set_'+identifier].value) {
                   1328:                                 posslinkurl = ','+posslinkurl;
                   1329:                             }
                   1330:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1331:                         }
1.601     raeburn  1332:                     } else if (dlLtidRegExp.test(name)) {
                   1333:                         var identifier = name.replace(dlLtidRegExp,'');
                   1334:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1335:                             var possltid = document.parmform.elements[i].value;
                   1336:                             possltid = possltid.replace(/\D+/g,'');
                   1337:                             if (possltid.length) {
1.597     raeburn  1338:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1339:                                     possltid = ':'+possltid;
1.597     raeburn  1340:                                 }
1.601     raeburn  1341:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1342:                             } else {
                   1343:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1344:                                 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  1345:                                 return false;  
                   1346:                             }
                   1347:                         }
1.601     raeburn  1348:                     } else if (dlLticRegExp.test(name)) {
                   1349:                         var identifier = name.replace(dlLticRegExp,'');
                   1350:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1351:                             var possltic = document.parmform.elements[i].value;
                   1352:                             possltic = possltic.replace(/\D+/g,'');
                   1353:                             if (possltic.length) {
                   1354:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1355:                                     possltic = ':'+possltic;
                   1356:                                 }
                   1357:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1358:                             } else {
                   1359:                                 document.parmform.elements['set_'+identifier].value = '';
                   1360:                                 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.");
                   1361:                                 return false;
                   1362:                             }
                   1363:                         }
1.597     raeburn  1364:                     } else if (dlKeyRegExp.test(name)) {
                   1365:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1366:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1367:                             var posskey = document.parmform.elements[i].value;
                   1368:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1369:                             var origlength = posskey.length;
                   1370:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1371:                             var newlength = posskey.length;
                   1372:                             if (newlength > 0) {
                   1373:                                 var change = origlength - newlength;
                   1374:                                 if (change) {
                   1375:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1376:                                 }
                   1377:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1378:                                     posskey = ':'+posskey;
                   1379:                                 }
                   1380:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1381:                             } else {
                   1382:                                 document.parmform.elements['set_'+identifier].value = '';
                   1383:                                 if (newlength < origlength) {
                   1384:                                     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_.!@#$%^&*()+=-");
                   1385:                                 } else {
                   1386:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1387:                                 }
                   1388:                                 return false;
                   1389:                             }
                   1390:                         }
                   1391:                     } else if (dlMenusRegExp.test(name)) {
                   1392:                         if (document.parmform.elements[i].checked) {
                   1393:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1394:                             var posslinkmenu = document.parmform.elements[i].value;
                   1395:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1396:                             if (posslinkmenu == 'std') {
                   1397:                                 posslinkmenu = '0';
                   1398:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1399:                                     posslinkmenu = ','+posslinkmenu;
                   1400:                                 }
                   1401:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1402:                             }
                   1403:                         }
                   1404:                     } else if (dlCollsRegExp.test(name)) {
                   1405:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1406:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1407:                             var posslinkmenu = document.parmform.elements[i].value;
                   1408:                             if (document.parmform.elements['set_'+identifier].value) {
                   1409:                                 posslinkmenu = ','+posslinkmenu;
                   1410:                             }
                   1411:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1412:                         }
1.614     raeburn  1413:                     } else if (dlTargetRegExp.test(name)) {
                   1414:                         var identifier =  name.replace(dlTargetRegExp,'');
1.613     raeburn  1415:                         var idx = document.parmform.elements[i].selectedIndex;
                   1416:                         if (idx > 0) {
1.616   ! raeburn  1417:                             var linktarget = document.parmform.elements[i].options[idx].value
        !          1418:                             linktarget = linktarget.replace(/^\s+|\s+$/g,'');
        !          1419:                             if (document.parmform.elements['set_'+identifier].value) {
        !          1420:                                 linktarget = ','+linktarget;
        !          1421:                             }
        !          1422:                             document.parmform.elements['set_'+identifier].value += linktarget;
        !          1423:                         }
        !          1424:                     } else if (dlExitRegExp.test(name)) {
        !          1425:                         if (document.parmform.elements[i].checked) {
        !          1426:                             var identifier =  name.replace(dlExitRegExp,'');
        !          1427:                             var posslinkexit = document.parmform.elements[i].value;
        !          1428:                             posslinkexit = posslinkexit.replace(/^\s+|\s+$/g,'');
1.613     raeburn  1429:                             if (document.parmform.elements['set_'+identifier].value) {
1.616   ! raeburn  1430:                                 posslinkexit = ','+posslinkexit;
        !          1431:                             }
        !          1432:                             document.parmform.elements['set_'+identifier].value += posslinkexit;
        !          1433:                         }
        !          1434:                     } else if (dlExitTextRegExp.test(name)) {
        !          1435:                         var identifier = name.replace(dlExitTextRegExp,'');
        !          1436:                         if ((isRadioSet('deeplink_exit_'+identifier,'yes')) ||
        !          1437:                             (isRadioSet('deeplink_exit_'+identifier,'url'))) {
        !          1438:                             var posstext = document.parmform.elements[i].value;
        !          1439:                             posstext = posstext.replace(/^\s+|\s+$/g,'');
        !          1440:                             var origlength = posstext.length;
        !          1441:                             posstext = posstext.replace(/[:;'",]/g,'');
        !          1442:                             var newlength = posstext.length;
        !          1443:                             if (newlength > 0) {
        !          1444:                                 var change = origlength - newlength;
        !          1445:                                 if (change) {
        !          1446:                                     alert(change+' disallowed character(s) removed from Exit Button text');
        !          1447:                                 }
        !          1448:                                 if (posstext !== 'Exit Tool') {
        !          1449:                                     posstext = ':'+posstext;
        !          1450:                                     document.parmform.elements['set_'+identifier].value += posstext;
        !          1451:                                 }
        !          1452:                             } else {
        !          1453:                                 document.parmform.elements['set_'+identifier].value = '';
        !          1454:                                 if (newlength < origlength) {
        !          1455:                                     alert("An exit link type of 'In use' was selected but the button text value was blank, after removing disallowed characters.\nDisallowed characters are ,\":;'");
        !          1456:                                 } else {
        !          1457:                                     alert("An exit link type of 'In use' was selected but the button text value was blank.\nPlease enter the text to use.");
        !          1458:                                 }
        !          1459:                                 return false;
1.613     raeburn  1460:                             }
                   1461:                         }
1.549     raeburn  1462:                     }
                   1463:                 }
                   1464:             }
                   1465:         }
                   1466:     }
                   1467:     return true;
                   1468: }
                   1469: 
1.597     raeburn  1470: function isRadioSet(name,expected) {
                   1471:     var menuitems = document.getElementsByName(name);
                   1472:     var radioLength = menuitems.length;
                   1473:     result = false;
                   1474:     if (radioLength  > 1) {
                   1475:         for (var j=0; j<radioLength; j++) {
                   1476:             if (menuitems[j].checked) {
                   1477:                 if (menuitems[j].value == expected) {
                   1478:                     result = true;
                   1479:                     break;
                   1480:                 }
                   1481:             }
                   1482:         }
                   1483:     }
                   1484:     return result;
                   1485: }
                   1486: 
1.549     raeburn  1487: ENDSCRIPT
                   1488: }
                   1489: 
1.561     damieng  1490: # Javascript initialization, for overview mode
1.549     raeburn  1491: sub ipacc_boxes_js  {
                   1492:     my $remove = &mt('Remove');
                   1493:     return <<"END";
                   1494: \$(document).ready(function() {
                   1495:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1496:     var add_button      = \$(".LC_add_ipacc_button");
                   1497:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1498: 
                   1499:     \$(add_button).click(function(e){
                   1500:         e.preventDefault();
                   1501:         var identifier = \$(this).closest("div").attr("id");
                   1502:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1503:         \$(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  1504:     });
                   1505: 
                   1506:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1507:         e.preventDefault(); \$(this).closest("div").remove();
                   1508:     })
                   1509: });
                   1510: 
                   1511: 
                   1512: END
                   1513: }
                   1514: 
1.561     damieng  1515: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1516: sub done_proctor_js {
1.611     raeburn  1517:     my $defaultdone = &mt('Done');
                   1518:     &js_escape(\$defaultdone);
1.558     raeburn  1519:     return <<"END";
                   1520: function toggleSecret(form,radio,key) {
                   1521:     var radios = form[radio+key];
                   1522:     if (radios.length) {
                   1523:         for (var i=0; i<radios.length; i++) {
                   1524:             if (radios[i].checked) {
                   1525:                 if (radios[i].value == '_done_proctor') {
                   1526:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1527:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1528:                     }
                   1529:                 } else {
                   1530:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1531:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1532:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1533:                     }
                   1534:                 }
1.611     raeburn  1535:                 if (document.getElementById('done_'+key+'_buttontext')) {
                   1536:                     if (radios[i].value == '') {
                   1537:                         document.getElementById('done_'+key+'_buttontext').value = '';
                   1538:                     } else {
                   1539:                         if (document.getElementById('done_'+key+'_buttontext').value == '') {
                   1540:                             document.getElementById('done_'+key+'_buttontext').value = '$defaultdone';
                   1541:                         }
                   1542:                     }
                   1543:                 }
1.558     raeburn  1544:             }
                   1545:         }
                   1546:     }
                   1547: }
                   1548: END
                   1549: 
                   1550: }
                   1551: 
1.588     raeburn  1552: # Javascript function toggle
                   1553: sub deeplink_js {
                   1554:     return <<"END";
                   1555: function toggleDeepLink(form,item,key) {
                   1556:     var radios = form['deeplink_'+item+'_'+key];
                   1557:     if (radios.length) {
                   1558:         var keybox;
                   1559:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1560:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1561:         }
1.601     raeburn  1562:         var divoptions = new Array();
                   1563:         if (item == 'protect') {
                   1564:             divoptions = ['ltic','ltid'];
1.597     raeburn  1565:         } else {
                   1566:             if (item == 'menus') {
1.601     raeburn  1567:                 divoptions = ['colls'];
1.597     raeburn  1568:             }
                   1569:         }
1.601     raeburn  1570:         var seldivs = new Array();
                   1571:         if ((item == 'protect') || (item == 'menus')) {
                   1572:             for (var i=0; i<divoptions.length; i++) {
                   1573:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1574:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1575:                 } else {
                   1576:                     seldivs[i] = '';
                   1577:                 }
                   1578:             }
1.588     raeburn  1579:         }
                   1580:         for (var i=0; i<radios.length; i++) {
                   1581:             if (radios[i].checked) {
1.601     raeburn  1582:                 if ((item == 'protect') || (item == 'menus')) {
                   1583:                     for (var j=0; j<seldivs.length; j++) {
                   1584:                         if (radios[i].value == divoptions[j]) {
                   1585:                             if (seldivs[j] != '') {
                   1586:                                 seldivs[j].style.display = 'inline-block';
                   1587:                             }
                   1588:                             if (item == 'protect') {
                   1589:                                 keybox.type = 'hidden';
                   1590:                                 keybox.value = '';
                   1591:                             }
                   1592:                         } else {
                   1593:                             if (seldivs[j] != '') {
                   1594:                                 seldivs[j].style.display = 'none';
                   1595:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1596:                             }
                   1597:                         }
1.597     raeburn  1598:                     }
1.601     raeburn  1599:                     if (item == 'protect') {
1.597     raeburn  1600:                         if (radios[i].value == 'key') {
                   1601:                             keybox.type = 'text';
                   1602:                         } else {
                   1603:                             keybox.type = 'hidden';
                   1604:                         }
1.588     raeburn  1605:                     }
1.616   ! raeburn  1606:                 } else if (item == 'exit') {
        !          1607:                     if (document.getElementById('deeplinkdiv_'+item+'_'+key)) {
        !          1608:                         if (radios[i].value == 'no') {
        !          1609:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'none';          
        !          1610:                             if (document.getElementById('deeplink_exittext_'+key)) {
        !          1611:                                 if (document.getElementById('deeplink_exittext_'+key).value != '') {
        !          1612:                                     document.getElementById('deeplink_exittext_'+key).value = '';    
        !          1613:                                 }
        !          1614:                             }
        !          1615:                         } else {
        !          1616:                             document.getElementById('deeplinkdiv_'+item+'_'+key).style.display = 'inline-block';
        !          1617:                             if (document.getElementById('deeplink_exittext_'+key)) {
        !          1618:                                 if (document.getElementById('deeplink_exittext_'+key).value == '') {
        !          1619:                                     document.getElementById('deeplink_exittext_'+key).value = 'Exit Tool';
        !          1620:                                 }
        !          1621:                             }
        !          1622:                         }
        !          1623:                     }
1.588     raeburn  1624:                 }
                   1625:             }
                   1626:         }
                   1627:     }
                   1628: }
                   1629: END
                   1630: 
                   1631: }
                   1632: 
1.561     damieng  1633: # Prints HTML page start for table mode.
                   1634: # @param {Apache2::RequestRec} $r - the Apache request
                   1635: # @param {string} $psymb - resource symb
                   1636: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1637: sub startpage {
1.531     raeburn  1638:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1639: 
1.515     raeburn  1640:     my %loaditems = (
                   1641:                       'onload'   => "group_or_section('cgroup')",
                   1642:                     );
                   1643:     if (!$psymb) {
1.523     raeburn  1644:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1645:     }
1.280     albertel 1646: 
1.560     damieng  1647:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1648:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1649:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1650:             text=>"Problem Parameters"});
1.414     droeschl 1651:     } else {
1.560     damieng  1652:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1653:             text=>"Table Mode",
                   1654:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1655:     }
1.523     raeburn  1656:     my $js = &page_js().'
                   1657: <script type="text/javascript">
                   1658: // <![CDATA[
                   1659: '.
                   1660:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1661: // ]]>
                   1662: </script>
                   1663: ';
1.446     bisitz   1664:     my $start_page =
1.523     raeburn  1665:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1666:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1667:     my $breadcrumbs =
1.473     amueller 1668:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1669:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1670:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1671:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1672:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1673:     $r->print(<<ENDHEAD);
1.193     albertel 1674: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1675: <input type="hidden" value="" name="pres_value" />
                   1676: <input type="hidden" value="" name="pres_type" />
                   1677: <input type="hidden" value="" name="pres_marker" />
                   1678: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1679: <input type="hidden" value="$escfilter" name="filter" />
                   1680: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1681: ENDHEAD
                   1682: }
                   1683: 
1.209     www      1684: 
1.561     damieng  1685: # Prints a row for table mode (except for the tr start).
                   1686: # Every time a hash reference is passed, a single entry is used, so print_row
                   1687: # could just use these values, but why make it simple when it can be complicated ?
                   1688: #
                   1689: # @param {Apache2::RequestRec} $r - the Apache request
                   1690: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1691: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1692: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1693: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1694: # @param {string} $rid - resource id
                   1695: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1696: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1697: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1698: # @param {string} $defbgone - user level and other levels background color
                   1699: # @param {string} $defbgtwo - section level background color, also used for part number
                   1700: # @param {string} $defbgthree - group level background color
                   1701: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1702: # @param {string} $uname - user name
                   1703: # @param {string} $udom - user domain
                   1704: # @param {string} $csec - section name
                   1705: # @param {string} $cgroup - group name
                   1706: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1707: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1708: # @param {boolean} $readonly - true if no editing allowed.
                   1709: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1710: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1711: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1712: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1713: sub print_row {
1.201     www      1714:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1715:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1716:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1717:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1718:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1719:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1720:     my $numlinks = 0;
1.553     raeburn  1721: 
1.560     damieng  1722:     # get the values for the parameter in cascading order
                   1723:     # empty levels will remain empty
1.44      albertel 1724:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1725:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1726:     # get the type for the parameters
                   1727:     # problem: these may not be set for all levels
1.66      www      1728:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1729:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1730:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1731:     # cascade down manually
1.182     albertel 1732:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1733:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1734:         if ($typeoutpar[$i]) {
1.66      www      1735:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1736:         } else {
1.66      www      1737:             $typeoutpar[$i]=$cascadetype;
                   1738:         }
                   1739:     }
1.57      albertel 1740:     my $parm=$$display{$which};
                   1741: 
1.203     www      1742:     if ($parmlev eq 'full') {
1.419     bisitz   1743:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1744:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1745:     } else {
1.57      albertel 1746:         $parm=~s|\[.*\]\s||g;
                   1747:     }
1.231     www      1748:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1749:     if ($automatic) {
1.560     damieng  1750:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1751:     }
1.427     bisitz   1752:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1753: 
1.44      albertel 1754:     my $thismarker=$which;
                   1755:     $thismarker=~s/^parameter\_//;
                   1756:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1757:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1758:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1759:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1760:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1761:         if ($result eq '') {
                   1762:             $recurse_check = 1;
                   1763:         } elsif (($uname ne '') && ($result > 3)) {
                   1764:             $recurse_check = 1;
                   1765:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1766:             $recurse_check = 1;
                   1767:         } elsif (($csec ne '') && ($result > 11)) {
                   1768:             $recurse_check = 1;
                   1769:         } elsif ($result > 17) {
                   1770:             $recurse_check = 1;
                   1771:         }
                   1772:         if ($recurse_check) {
                   1773:             my $what = $$part{$which}.'.'.$$name{$which};
                   1774:             my $prefix;
                   1775:             if (($uname ne '') && ($udom ne '')) {
                   1776:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1777:                 $prefix = $env{'request.course.id'};
                   1778:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1779:                 if (ref($recursinfo) eq 'ARRAY') {
                   1780:                     $effparm_rec = 1;
                   1781:                     $effparm_level = &mt('user: [_1]',$uname);
                   1782:                 }
                   1783:             }
                   1784:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1785:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1786:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1787:                 if (ref($recursinfo) eq 'ARRAY') {
                   1788:                     $effparm_rec = 1;
                   1789:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1790:                 }
                   1791:             }
                   1792:             if (($csec ne '') && (!$effparm_rec)) {
                   1793:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1794:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1795:                 if (ref($recursinfo) eq 'ARRAY') {
                   1796:                     $effparm_rec = 1;
                   1797:                     $effparm_level = &mt('section: [_1]',$csec);
                   1798:                 }
                   1799:             }
                   1800:             if (!$effparm_rec) {
                   1801:                 $prefix = $env{'request.course.id'};
                   1802:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1803:                 if (ref($recursinfo) eq 'ARRAY') {
                   1804:                     $effparm_rec = 1;
                   1805:                 }
                   1806:             }
                   1807:         }
                   1808:     }
                   1809:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1810:         $effparm_rec = 1;
                   1811:     }
                   1812:     if ((!$effparm_rec) && 
                   1813:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1814:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1815:         $effparm_rec = 1;
                   1816:     }
1.588     raeburn  1817:     if ($parmname eq 'deeplink') {
1.601     raeburn  1818:         my ($domltistr,$crsltistr);
1.588     raeburn  1819:         my %lti =
                   1820:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1821:                                             'linkprot');
1.601     raeburn  1822:         if (keys(%lti)) {
                   1823:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1824:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1825:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1826:                 }
                   1827:             }
1.601     raeburn  1828:             $domltistr =~ s/,$//;
                   1829:             if ($domltistr) {
                   1830:                 $extra = 'ltid_'.$domltistr;
                   1831:             }
1.588     raeburn  1832:         }
1.601     raeburn  1833:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1834:         if (keys(%courselti)) {
                   1835:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1836:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1837:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1838:                 }
                   1839:             }
                   1840:             $crsltistr =~ s/,$//;
                   1841:             if ($crsltistr) {
                   1842:                 if ($extra) {
                   1843:                     $extra .= '&';
                   1844:                 }
                   1845:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1846:             }
                   1847:         }
1.597     raeburn  1848:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1849:             my @colls;
                   1850:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1851:                 my ($num,$value) = split(/\%/,$item);
                   1852:                 if ($num =~ /^\d+$/) {
                   1853:                     push(@colls,$num);
                   1854:                 }
                   1855:             }
                   1856:             if (@colls) {
                   1857:                 if ($extra) {
                   1858:                     $extra .= '&';
                   1859:                 }
                   1860:                 $extra .= 'menus_'.join(',',@colls);
                   1861:             }
                   1862:         }
1.588     raeburn  1863:     }
1.57      albertel 1864:     if ($parmlev eq 'general') {
                   1865:         if ($uname) {
1.588     raeburn  1866:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1867:         } elsif ($cgroup) {
1.588     raeburn  1868:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1869:         } elsif ($csec) {
1.588     raeburn  1870:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1871:         } else {
1.588     raeburn  1872:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1873:         }
                   1874:     } elsif ($parmlev eq 'map') {
                   1875:         if ($uname) {
1.588     raeburn  1876:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1877:         } elsif ($cgroup) {
1.588     raeburn  1878:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1879:         } elsif ($csec) {
1.588     raeburn  1880:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1881:         } else {
1.588     raeburn  1882:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1883:         }
                   1884:     } else {
1.275     raeburn  1885:         if ($uname) {
                   1886:             if (@{$usersgroups} > 1) {
1.582     raeburn  1887:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1888:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1889:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1890:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1891:                     if (defined($controlgrp)) {
                   1892:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1893:                             $eff_groupparm = $grp_parm;
                   1894:                             undef($result);
                   1895:                             undef($effparm_rec);
                   1896:                             if ($grp_is_rec) {
                   1897:                                  $effparm_rec = 1;
                   1898:                             }
1.275     raeburn  1899:                         }
                   1900:                     }
                   1901:                 }
                   1902:             }
                   1903:         }
1.57      albertel 1904: 
1.588     raeburn  1905:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1906:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1907:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1908:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1909:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1910: 
                   1911:         if ($csec) {
1.588     raeburn  1912:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1913:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1914:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1915:         }
1.269     raeburn  1916: 
                   1917:         if ($cgroup) {
1.588     raeburn  1918:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1919:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1920:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1921:         }
1.446     bisitz   1922: 
1.548     raeburn  1923:         if ($uname) {
1.275     raeburn  1924:             if ($othergrp) {
                   1925:                 $r->print($othergrp);
                   1926:             }
1.588     raeburn  1927:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1928:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1929:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1930:         }
1.57      albertel 1931:     } # end of $parmlev if/else
1.582     raeburn  1932:     if (ref($recursinfo) eq 'ARRAY') {
                   1933:         my $rectitle = &mt('recursive');
                   1934:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1935:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1936:                 $rectitle = &mt('set in: [_1]','"'.
                   1937:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1938:                                                               "'$parmname','$$part{$which}'".');">'.
                   1939:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1940:               
                   1941:                 $numlinks ++;
                   1942:             }
                   1943:         }
                   1944:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1945:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1946:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1947:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1948:                   $effparm_level.'</span></td>');
                   1949:     } else {
                   1950:         if ($result) {
1.593     raeburn  1951:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1952:         }
                   1953:         if ($eff_groupparm) {
                   1954:             $effective_parm = $eff_groupparm;
                   1955:         }
                   1956:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1957:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1958:                                 '</span>':'').'</td>');
                   1959:     }
1.203     www      1960:     if ($parmlev eq 'full') {
1.136     albertel 1961:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1962:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1963:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1964:         if (!defined($sessionvaltype)) {
                   1965:             $sessionvaltype=$$defaulttype{$which};
                   1966:         }
1.419     bisitz   1967:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1968:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1969:                   '</font></td>');
1.136     albertel 1970:     }
1.44      albertel 1971:     $r->print('</tr>');
1.57      albertel 1972:     $r->print("\n");
1.582     raeburn  1973:     if (($numlinks) && (ref($reclinks))) {
                   1974:         $$reclinks = $numlinks;
                   1975:     }
1.44      albertel 1976: }
1.59      matthew  1977: 
1.561     damieng  1978: # Prints a cell for table mode.
                   1979: #
                   1980: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1981: # Also, it would make more sense to pass the display for this cell rather
                   1982: # than the full display hash and the key to use.
                   1983: #
                   1984: # @param {Apache2::RequestRec} $r - the Apache request
                   1985: # @param {integer} $which - level
                   1986: # @param {string} $defbg - cell background color
                   1987: # @param {integer} $result - the most specific level that is defined for that parameter
                   1988: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1989: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1990: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1991: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1992: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1993: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1994: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1995: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1996: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1997: sub print_td {
1.578     raeburn  1998:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1999:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  2000:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   2001:     $ineffect = 0;
                   2002:     $currval = $$outpar[$which];
                   2003:     $currtype = $$typeoutpar[$which];
                   2004:     $currlevel = $which;
                   2005:     if (($result) && ($result == $which)) {
                   2006:         $ineffect = 1;
                   2007:     } 
                   2008:     if ($ismaplevel) {
                   2009:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   2010:             if (($result) && ($result == $which)) {
                   2011:                 $recursive = 1;
                   2012:             }
                   2013:         } elsif ($$outpar[$which+1] ne '') {
                   2014:             $recursive = 1;
                   2015:             $currlevel = $which+1;
                   2016:             $currval = $$outpar[$currlevel];
                   2017:             $currtype = $$typeoutpar[$currlevel];
                   2018:             if (($result) && ($result == $currlevel)) {
                   2019:                 $ineffect = 1;
                   2020:             }
                   2021:         }
                   2022:     }
                   2023:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   2024:               ';" align="center">');
1.437     raeburn  2025:     my $nolink = 0;
1.568     raeburn  2026:     if ($readonly) {
1.552     raeburn  2027:         $nolink = 1;
1.568     raeburn  2028:     } else { 
1.578     raeburn  2029:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  2030:             $nolink = 1;
1.568     raeburn  2031:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  2032:             $nolink = 1;
1.568     raeburn  2033:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   2034:             if ($noeditgrp) {
                   2035:                 $nolink = 1;
                   2036:             }
                   2037:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  2038:             $nolink = 1;
1.568     raeburn  2039:         } elsif ($mprefix =~ /examcode\&$/) {
                   2040:             unless ($which == 2) {
                   2041:                 $nolink = 1;
                   2042:             }
1.533     raeburn  2043:         }
1.437     raeburn  2044:     }
                   2045:     if ($nolink) {
1.577     raeburn  2046:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  2047:         $r->print(&valout($currval,$currtype));
1.114     www      2048:     } else {
1.578     raeburn  2049:         $r->print(&plink($currtype,
                   2050:                          $$display{$value},$currval,
1.588     raeburn  2051:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   2052:                          $extra));
1.114     www      2053:     }
                   2054:     $r->print('</td>'."\n");
1.57      albertel 2055: }
                   2056: 
1.561     damieng  2057: # Returns HTML and other info for the cell added when a user is selected
                   2058: # and that user is in several groups. This is the cell with the title "Control by other group".
                   2059: #
                   2060: # @param {string} $what - parameter part.'.'.parameter name
                   2061: # @param {string} $rid - resource id
                   2062: # @param {string} $cgroup - group name
                   2063: # @param {string} $defbg - cell background color
                   2064: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2065: # @param {integer} $result - level
                   2066: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  2067: # @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  2068: sub check_other_groups {
                   2069:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  2070:     my $courseid = $env{'request.course.id'};
                   2071:     my $output;
                   2072:     my $symb = &symbcache($rid);
                   2073:     my $symbparm=$symb.'.'.$what;
                   2074:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  2075:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  2076:     my $mapparm=$map.'___(all).'.$what;
                   2077:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  2078:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   2079:                               $recurseparm,$what,$courseopt);
1.275     raeburn  2080:     my $bgcolor = $defbg;
1.582     raeburn  2081:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2082:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2083:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2084:         if ($result > 3) {
1.419     bisitz   2085:             $bgcolor = '#AAFFAA';
1.275     raeburn  2086:         }
1.593     raeburn  2087:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2088:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2089:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2090:             if ($resultlevel eq 'recursive') {
                   2091:                 $resultlevel = 'map/folder';
                   2092:                 $grp_is_rec = 1;
                   2093:             }
                   2094:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2095:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2096:              
1.275     raeburn  2097:         } else {
                   2098:             $output .= '&nbsp;';
                   2099:         }
                   2100:         $output .= '</td>';
                   2101:     } else {
1.419     bisitz   2102:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2103:     }
1.582     raeburn  2104:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2105: }
                   2106: 
1.561     damieng  2107: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2108: # Used by check_other_groups.
1.561     damieng  2109: #
                   2110: # @param {string} $courseid - the course id
                   2111: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2112: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2113: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2114: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2115: # @param {string} $what - parameter part.'.'.parameter name
                   2116: # @param {hash reference} $courseopt - course parameters hash
                   2117: # @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  2118: sub parm_control_group {
1.556     raeburn  2119:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2120:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2121:     my $grpfound = 0;
1.556     raeburn  2122:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2123:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2124:     foreach my $group (@{$usersgroups}) {
                   2125:         if ($grpfound) { last; }
                   2126:         for (my $i=0; $i<@levels; $i++) {
                   2127:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2128:             if (defined($$courseopt{$item})) {
                   2129:                 $coursereply = $$courseopt{$item};
                   2130:                 $resultitem = $item;
                   2131:                 $resultgroup = $group;
                   2132:                 $resultlevel = $levelnames[$i];
                   2133:                 $resulttype = $$courseopt{$item.'.type'};
                   2134:                 $grpfound = 1;
                   2135:                 last;
                   2136:             }
                   2137:         }
                   2138:     }
                   2139:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2140: }
1.201     www      2141: 
1.63      bowersj2 2142: 
                   2143: 
1.562     damieng  2144: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2145: # All the parameters are references and are filled by the sub.
                   2146: #
1.566     damieng  2147: # @param {array reference} $ids - resource and map ids
                   2148: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2149: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2150: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2151: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2152: # @param {hash reference} $allmaps - hash map pc -> map src
                   2153: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2154: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2155: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2156: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2157: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2158: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.608     raeburn  2159: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.63      bowersj2 2160: sub extractResourceInformation {
                   2161:     my $ids = shift;
                   2162:     my $typep = shift;
                   2163:     my $keyp = shift;
                   2164:     my $allparms = shift;
                   2165:     my $allparts = shift;
                   2166:     my $allmaps = shift;
                   2167:     my $mapp = shift;
                   2168:     my $symbp = shift;
1.82      www      2169:     my $maptitles=shift;
1.196     www      2170:     my $uris=shift;
1.210     www      2171:     my $keyorder=shift;
1.211     www      2172:     my $defkeytype=shift;
1.603     raeburn  2173:     my $pssymb=shift;
1.196     www      2174: 
1.210     www      2175:     my $keyordercnt=100;
1.63      bowersj2 2176: 
1.196     www      2177:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2178:     return unless(ref($navmap));
                   2179:     my @allres;
                   2180:     if ($pssymb ne '') {
                   2181:         my $res = $navmap->getBySymb($pssymb);
                   2182:         if (ref($res)) {
                   2183:             @allres = ($res);
                   2184:         }
                   2185:     }
                   2186:     if (!@allres) { 
                   2187:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2188:     }
1.196     www      2189:     foreach my $resource (@allres) {
1.480     amueller 2190:         my $id=$resource->id();
1.196     www      2191:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2192:         if ($mapid eq '0') { next; }
                   2193:         $$ids[$#$ids+1]=$id;
                   2194:         my $srcf=$resource->src();
                   2195:         $srcf=~/\.(\w+)$/;
                   2196:         $$typep{$id}=$1;
1.584     raeburn  2197:         my $toolsymb;
                   2198:         if ($srcf =~ /ext\.tool$/) {
                   2199:             $toolsymb = $resource->symb();
                   2200:         }
1.480     amueller 2201:         $$keyp{$id}='';
1.196     www      2202:         $$uris{$id}=$srcf;
1.512     foxr     2203: 
1.584     raeburn  2204:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2205:             next if ($key!~/^parameter_/);
1.363     albertel 2206: 
1.209     www      2207: # Hidden parameters
1.584     raeburn  2208:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2209: #
                   2210: # allparms is a hash of parameter names
                   2211: #
1.584     raeburn  2212:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2213:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2214:                 my ($display,$parmdis);
                   2215:                 $display = &standard_parameter_names($name);
                   2216:                 if ($display eq '') {
1.584     raeburn  2217:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2218:                     $parmdis = $display;
                   2219:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2220:                 } else {
                   2221:                     $parmdis = &mt($display);
                   2222:                 }
                   2223:                 $$allparms{$name}=$parmdis;
                   2224:                 if (ref($defkeytype)) {
                   2225:                     $$defkeytype{$name}=
1.584     raeburn  2226:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2227:                 }
                   2228:             }
1.363     albertel 2229: 
1.209     www      2230: #
                   2231: # allparts is a hash of all parts
                   2232: #
1.584     raeburn  2233:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2234:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2235: #
                   2236: # Remember all keys going with this resource
                   2237: #
1.480     amueller 2238:             if ($$keyp{$id}) {
                   2239:                 $$keyp{$id}.=','.$key;
                   2240:             } else {
                   2241:                 $$keyp{$id}=$key;
                   2242:             }   
1.210     www      2243: #
                   2244: # Put in order
1.446     bisitz   2245: #
1.480     amueller 2246:             unless ($$keyorder{$key}) {
                   2247:                 $$keyorder{$key}=$keyordercnt;
                   2248:                 $keyordercnt++;
                   2249:             }
1.473     amueller 2250:         }
                   2251: 
                   2252: 
1.480     amueller 2253:         if (!exists($$mapp{$mapid})) {
                   2254:             $$mapp{$id}=
                   2255:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2256:             $$mapp{$mapid}=$$mapp{$id};
                   2257:             $$allmaps{$mapid}=$$mapp{$id};
                   2258:             if ($mapid eq '1') {
1.532     raeburn  2259:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2260:             } else {
                   2261:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2262:             }
                   2263:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2264:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2265:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2266:                                                      # are commented out in rev. 1.57
1.473     amueller 2267:         } else {
1.480     amueller 2268:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2269:         }
1.480     amueller 2270:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2271:     }
                   2272: }
                   2273: 
1.582     raeburn  2274: sub get_recursive {
                   2275:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2276:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2277:         foreach my $item (@{$recurseup}) {
                   2278:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2279:             if (defined($resdata->{$norecursechk})) {
                   2280:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2281:                     my $type = $resdata->{$norecursechk.'.type'};
                   2282:                     return [$resdata->{$norecursechk},$type,$item];
                   2283:                 } else {
                   2284:                     last;
                   2285:                 }
                   2286:             }
                   2287:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2288:             if (defined($resdata->{$recursechk})) {
                   2289:                 my $type = $resdata->{$recursechk.'.type'};
                   2290:                 return [$resdata->{$recursechk},$type,$item];
                   2291:             }
                   2292:         }
                   2293:     }
                   2294:     return;
                   2295: }
                   2296: 
1.208     www      2297: 
1.562     damieng  2298: # Tells if a parameter type is a date.
                   2299: #
                   2300: # @param {string} type - parameter type
                   2301: # @returns{boolean} - true if it is a date
1.213     www      2302: sub isdateparm {
                   2303:     my $type=shift;
                   2304:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2305: }
                   2306: 
1.589     raeburn  2307: # Determine if parameter type is specialized string type (i.e.,
                   2308: # not just string or string_yesno.  
                   2309: 
                   2310: sub is_specialstring {
                   2311:     my $type=shift;
1.603     raeburn  2312:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2313: }
                   2314: 
1.562     damieng  2315: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2316: #
1.581     raeburn  2317: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2318: sub parmmenu {
1.581     raeburn  2319:     my ($r)=@_;
1.208     www      2320:     $r->print(<<ENDSCRIPT);
                   2321: <script type="text/javascript">
1.454     bisitz   2322: // <![CDATA[
1.208     www      2323:     function checkall(value, checkName) {
1.453     schualex 2324: 
                   2325:         var li = "_li";
                   2326:         var displayOverview = "";
                   2327:         
                   2328:         if (value == false) {
                   2329:             displayOverview = "none"
                   2330:         }
                   2331: 
1.562     damieng  2332:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2333:             ele = document.forms.parmform.elements[i];
                   2334:             if (ele.name == checkName) {
                   2335:                 document.forms.parmform.elements[i].checked=value;
                   2336:             }
                   2337:         }
                   2338:     }
1.210     www      2339: 
                   2340:     function checkthis(thisvalue, checkName) {
1.562     damieng  2341:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2342:             ele = document.forms.parmform.elements[i];
                   2343:             if (ele.name == checkName) {
1.562     damieng  2344:                 if (ele.value == thisvalue) {
                   2345:                     document.forms.parmform.elements[i].checked=true;
                   2346:                 }
1.210     www      2347:             }
                   2348:         }
                   2349:     }
                   2350: 
                   2351:     function checkdates() {
1.562     damieng  2352:         checkthis('duedate','pscat');
                   2353:         checkthis('opendate','pscat');
                   2354:         checkthis('answerdate','pscat');
1.218     www      2355:     }
                   2356: 
                   2357:     function checkdisset() {
1.562     damieng  2358:         checkthis('discussend','pscat');
                   2359:         checkthis('discusshide','pscat');
                   2360:         checkthis('discussvote','pscat');
1.218     www      2361:     }
                   2362: 
                   2363:     function checkcontdates() {
1.562     damieng  2364:         checkthis('contentopen','pscat');
                   2365:         checkthis('contentclose','pscat');
1.218     www      2366:     }
1.446     bisitz   2367: 
1.210     www      2368:     function checkvisi() {
1.562     damieng  2369:         checkthis('hiddenresource','pscat');
                   2370:         checkthis('encrypturl','pscat');
                   2371:         checkthis('problemstatus','pscat');
                   2372:         checkthis('contentopen','pscat');
                   2373:         checkthis('opendate','pscat');
1.210     www      2374:     }
                   2375: 
                   2376:     function checkparts() {
1.562     damieng  2377:         checkthis('hiddenparts','pscat');
                   2378:         checkthis('display','pscat');
                   2379:         checkthis('ordered','pscat');
1.210     www      2380:     }
                   2381: 
                   2382:     function checkstandard() {
                   2383:         checkall(false,'pscat');
1.562     damieng  2384:         checkdates();
                   2385:         checkthis('weight','pscat');
                   2386:         checkthis('maxtries','pscat');
                   2387:         checkthis('type','pscat');
                   2388:         checkthis('problemstatus','pscat');
1.210     www      2389:     }
                   2390: 
1.454     bisitz   2391: // ]]>
1.208     www      2392: </script>
                   2393: ENDSCRIPT
1.453     schualex 2394: 
1.491     bisitz   2395:     $r->print('<hr />');
1.581     raeburn  2396:     &shortCuts($r);
1.491     bisitz   2397:     $r->print('<hr />');
1.453     schualex 2398: }
1.562     damieng  2399: 
                   2400: # Returns parameter categories.
                   2401: #
                   2402: # @returns {hash} - category name -> title in English
1.465     amueller 2403: sub categories {
                   2404:     return ('time_settings' => 'Time Settings',
                   2405:     'grading' => 'Grading',
                   2406:     'tries' => 'Tries',
                   2407:     'problem_appearance' => 'Problem Appearance',
                   2408:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2409:     'hiding' => 'Hiding',
                   2410:     'high_level_randomization' => 'High Level Randomization',
                   2411:     'slots' => 'Slots',
                   2412:     'file_submission' => 'File Submission',
                   2413:     'misc' => 'Miscellaneous' ); 
                   2414: }
                   2415: 
1.562     damieng  2416: # Returns the category for each parameter.
                   2417: #
                   2418: # @returns {hash} - parameter name -> category name
1.465     amueller 2419: sub lookUpTableParameter {
                   2420:  
                   2421:     return ( 
                   2422:         'opendate' => 'time_settings',
                   2423:         'duedate' => 'time_settings',
                   2424:         'answerdate' => 'time_settings',
                   2425:         'interval' => 'time_settings',
                   2426:         'contentopen' => 'time_settings',
                   2427:         'contentclose' => 'time_settings',
                   2428:         'discussend' => 'time_settings',
1.560     damieng  2429:         'printstartdate' => 'time_settings',
                   2430:         'printenddate' => 'time_settings',
1.465     amueller 2431:         'weight' => 'grading',
                   2432:         'handgrade' => 'grading',
                   2433:         'maxtries' => 'tries',
                   2434:         'hinttries' => 'tries',
1.503     raeburn  2435:         'randomizeontries' => 'tries',
1.465     amueller 2436:         'type' => 'problem_appearance',
                   2437:         'problemstatus' => 'problem_appearance',
                   2438:         'display' => 'problem_appearance',
                   2439:         'ordered' => 'problem_appearance',
                   2440:         'numbubbles' => 'problem_appearance',
                   2441:         'tol' => 'behaviour_of_input_fields',
                   2442:         'sig' => 'behaviour_of_input_fields',
                   2443:         'turnoffunit' => 'behaviour_of_input_fields',
                   2444:         'hiddenresource' => 'hiding',
                   2445:         'hiddenparts' => 'hiding',
                   2446:         'discusshide' => 'hiding',
                   2447:         'buttonshide' => 'hiding',
                   2448:         'turnoffeditor' => 'hiding',
                   2449:         'encrypturl' => 'hiding',
1.587     raeburn  2450:         'deeplink' => 'hiding',
1.465     amueller 2451:         'randomorder' => 'high_level_randomization',
                   2452:         'randompick' => 'high_level_randomization',
                   2453:         'available' => 'slots',
                   2454:         'useslots' => 'slots',
                   2455:         'availablestudent' => 'slots',
                   2456:         'uploadedfiletypes' => 'file_submission',
                   2457:         'maxfilesize' => 'file_submission',
                   2458:         'cssfile' => 'misc',
                   2459:         'mapalias' => 'misc',
                   2460:         'acc' => 'misc',
                   2461:         'maxcollaborators' => 'misc',
                   2462:         'scoreformat' => 'misc',
1.514     raeburn  2463:         'lenient' => 'grading',
1.519     raeburn  2464:         'retrypartial' => 'tries',
1.521     raeburn  2465:         'discussvote'  => 'misc',
1.584     raeburn  2466:         'examcode' => 'high_level_randomization',
1.575     raeburn  2467:     );
1.465     amueller 2468: }
                   2469: 
1.562     damieng  2470: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2471: #
                   2472: # @param {string} $name - parameter name
                   2473: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2474: sub whatIsMyCategory {
                   2475:     my $name = shift;
                   2476:     my $catList = shift;
                   2477:     my @list;
                   2478:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2479:     my $cat = $lookUpList{$name};
                   2480:     if (defined($cat)) {
                   2481:         if (!defined($$catList{$cat})){
                   2482:             push @list, ($name);
                   2483:             $$catList{$cat} = \@list;
                   2484:         } else {
                   2485:             push @{${$catList}{$cat}}, ($name);     
                   2486:         }
                   2487:     } else {
                   2488:         if (!defined($$catList{'misc'})){
                   2489:             push @list, ($name);
                   2490:             $$catList{'misc'} = \@list;
                   2491:         } else {
                   2492:             push @{${$catList}{'misc'}}, ($name);     
                   2493:         }
                   2494:     }        
                   2495: }
                   2496: 
1.562     damieng  2497: # Sorts parameter names based on appearance order.
                   2498: #
                   2499: # @param {array reference} name - array reference of parameter names
                   2500: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2501: # @returns {Array} - array of parameter names
1.465     amueller 2502: sub keysindisplayorderCategory {
                   2503:     my ($name,$keyorder)=@_;
                   2504:     return sort {
1.473     amueller 2505:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2506:     } ( @{$name});
                   2507: }
                   2508: 
1.562     damieng  2509: # Returns a hash category name -> order, starting at 1 (integer)
                   2510: #
                   2511: # @returns {hash}
1.467     amueller 2512: sub category_order {
                   2513:     return (
                   2514:         'time_settings' => 1,
                   2515:         'grading' => 2,
                   2516:         'tries' => 3,
                   2517:         'problem_appearance' => 4,
                   2518:         'hiding' => 5,
                   2519:         'behaviour_of_input_fields' => 6,
                   2520:         'high_level_randomization'  => 7,
                   2521:         'slots' => 8,
                   2522:         'file_submission' => 9,
                   2523:         'misc' => 10
                   2524:     );
                   2525: 
                   2526: }
1.453     schualex 2527: 
1.562     damieng  2528: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2529: #
                   2530: # @param {Apache2::RequestRec} $r - the Apache request
                   2531: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2532: # @param {array reference} $pscat - list of selected parameter names
                   2533: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2534: sub parmboxes {
                   2535:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2536:     my %categories = &categories();
1.467     amueller 2537:     my %category_order = &category_order();
1.465     amueller 2538:     my %categoryList = (
                   2539:         'time_settings' => [],
                   2540:         'grading' => [],
                   2541:         'tries' => [],
                   2542:         'problem_appearance' => [],
                   2543:         'behaviour_of_input_fields' => [],
                   2544:         'hiding' => [],
                   2545:         'high_level_randomization' => [],
                   2546:         'slots' => [],
                   2547:         'file_submission' => [],
                   2548:         'misc' => [],
1.489     bisitz   2549:     );
1.510     www      2550: 
1.548     raeburn  2551:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2552:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2553:     }
1.453     schualex 2554:     #part to print the parm-list
1.536     raeburn  2555:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2556:         next if (@{$categoryList{$key}} == 0);
                   2557:         next if ($key eq '');
                   2558:         $r->print('<div class="LC_Box LC_400Box">'
                   2559:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2560:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2561:             next if ($tempkey eq '');
1.536     raeburn  2562:             $r->print('<span class="LC_nobreak">'
                   2563:                      .'<label><input type="checkbox" name="pscat" '
                   2564:                      .'value="'.$tempkey.'" ');
                   2565:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2566:                 $r->print( ' checked="checked"');
                   2567:             }
                   2568:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2569:                                                       : $tempkey)
1.536     raeburn  2570:                      .'</label></span><br />'."\n");
1.465     amueller 2571:         }
1.536     raeburn  2572:         $r->print('</div>');
1.465     amueller 2573:     }
1.536     raeburn  2574:     $r->print("\n");
1.453     schualex 2575: }
1.562     damieng  2576: 
                   2577: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2578: #
1.562     damieng  2579: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2580: sub shortCuts {
1.581     raeburn  2581:     my ($r)=@_;
1.453     schualex 2582: 
1.491     bisitz   2583:     # Parameter Selection
                   2584:     $r->print(
                   2585:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2586:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2587:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2588:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2589:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2590:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2591:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2592:        .&Apache::lonhtmlcommon::end_funclist()
                   2593:     );
                   2594: 
                   2595:     # Add Selection for...
                   2596:     $r->print(
                   2597:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2598:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2599:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2600:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2601:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2602:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2603:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2604:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2605:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2606:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2607:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2608:        .&Apache::lonhtmlcommon::end_funclist()
                   2609:     );
1.208     www      2610: }
                   2611: 
1.562     damieng  2612: # Prints HTML to select parts to view (except for the title).
                   2613: # Used by table and overview modes.
                   2614: #
                   2615: # @param {Apache2::RequestRec} $r - the Apache request
                   2616: # @param {hash reference} $allparts - hash parameter part -> part title
                   2617: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2618: sub partmenu {
1.446     bisitz   2619:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2620:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2621:     if ($selsize > 8) {
                   2622:         $selsize = 8;
                   2623:     }
1.446     bisitz   2624: 
1.523     raeburn  2625:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2626:     $r->print('<option value="all"');
1.562     damieng  2627:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2628:     $r->print('>'.&mt('All Parts').'</option>');
                   2629:     my %temphash=();
                   2630:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2631:     foreach my $tempkey (sort {
1.560     damieng  2632:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2633:             } keys(%{$allparts})) {
                   2634:         unless ($tempkey =~ /\./) {
                   2635:             $r->print('<option value="'.$tempkey.'"');
                   2636:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2637:                 $r->print(' selected="selected"');
                   2638:             }
                   2639:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2640:         }
1.208     www      2641:     }
1.446     bisitz   2642:     $r->print('</select>');
1.209     www      2643: }
                   2644: 
1.562     damieng  2645: # Prints HTML to select a user and/or a group.
                   2646: # Used by table mode.
                   2647: #
                   2648: # @param {Apache2::RequestRec} $r - the Apache request
                   2649: # @param {string} $uname - selected user name
                   2650: # @param {string} $id - selected Student/Employee ID
                   2651: # @param {string} $udom - selected user domain
                   2652: # @param {string} $csec - selected section name
                   2653: # @param {string} $cgroup - selected group name
                   2654: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2655: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2656: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2657: sub usermenu {
1.553     raeburn  2658:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2659:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2660:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2661:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2662: function setCourseadv(form,caller) {
                   2663:     if (caller.value == 'st') {
                   2664:         form.courseadv.value = 'none';
                   2665:     } else {
                   2666:         form.courseadv.value = '';
                   2667:     }
                   2668:     return;
                   2669: }
                   2670: ENDJS
1.412     bisitz   2671: 
1.596     raeburn  2672:     my (%chkroles,$stuonly,$courseadv);
                   2673:     if ($env{'form.userroles'} eq 'any') {
                   2674:         $chkroles{'any'} = ' checked="checked"';
                   2675:     } else {
                   2676:         $chkroles{'st'} = ' checked="checked"';
                   2677:         $courseadv = 'none';
                   2678:     }
                   2679:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2680:     if ($crstype eq 'Community') {
                   2681:         $stuonly = &mt('member only');
                   2682:     } else {
                   2683:         $stuonly = &mt('student only');
                   2684:     }
                   2685:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2686:                   &mt("User's role").':&nbsp;'.
                   2687:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2688:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2689:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2690:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2691:     my $sections='';
1.300     albertel 2692:     my %sectionhash = &Apache::loncommon::get_sections();
                   2693: 
1.269     raeburn  2694:     my $groups;
1.553     raeburn  2695:     my %grouphash;
                   2696:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2697:         %grouphash = &Apache::longroup::coursegroups();
                   2698:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2699:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2700:     }
1.299     albertel 2701: 
1.412     bisitz   2702:     my $g_s_header='';
                   2703:     my $g_s_footer='';
1.446     bisitz   2704: 
1.552     raeburn  2705:     my $currsec = $env{'request.course.sec'};
                   2706:     if ($currsec) {
                   2707:         $sections=&mt('Section:').' '.$currsec;
                   2708:         if (%grouphash) {
                   2709:             $sections .= ';'.('&nbsp;' x2);
                   2710:         }
                   2711:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2712:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2713:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2714:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2715:         }
                   2716:         $sections .= '>';
1.548     raeburn  2717:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2718:         $sections.='<option value="'.$section.'" '.
                   2719:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2720:                                                               '</option>';
1.209     www      2721:         }
                   2722:         $sections.='</select>';
1.269     raeburn  2723:     }
1.412     bisitz   2724: 
1.552     raeburn  2725:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2726:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2727:         $sections .= qq|
                   2728: <script type="text/javascript">
1.454     bisitz   2729: // <![CDATA[
1.269     raeburn  2730: function group_or_section(caller) {
                   2731:    if (caller == "cgroup") {
                   2732:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2733:            document.parmform.csec.selectedIndex = 0;
                   2734:        }
                   2735:    } else {
                   2736:        if (document.parmform.csec.selectedIndex != 0) {
                   2737:            document.parmform.cgroup.selectedIndex = 0;
                   2738:        }
                   2739:    }
                   2740: }
1.454     bisitz   2741: // ]]>
1.269     raeburn  2742: </script>
                   2743: |;
1.554     raeburn  2744:     } else {
1.269     raeburn  2745:         $sections .= qq|
                   2746: <script type="text/javascript">
1.454     bisitz   2747: // <![CDATA[
1.269     raeburn  2748: function group_or_section(caller) {
                   2749:     return;
                   2750: }
1.454     bisitz   2751: // ]]>
1.269     raeburn  2752: </script>
                   2753: |;
1.446     bisitz   2754:     }
1.299     albertel 2755: 
                   2756:     if (%grouphash) {
1.597     raeburn  2757:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2758:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2759:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2760:         }
                   2761:         $groups .= '>';
1.548     raeburn  2762:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2763:             $groups.='<option value="'.$grp.'" ';
                   2764:             if ($grp eq $cgroup) {
                   2765:                 unless ((defined($uname)) && ($grp eq '')) {
                   2766:                     $groups .=  'selected="selected" ';
                   2767:                 }
                   2768:             } elsif (!defined($cgroup)) {
                   2769:                 if (@{$usersgroups} == 1) {
                   2770:                     if ($grp eq $$usersgroups[0]) {
                   2771:                         $groups .=  'selected="selected" ';
                   2772:                     }
                   2773:                 }
                   2774:             }
                   2775:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2776:         }
                   2777:         $groups.='</select>';
                   2778:     }
1.412     bisitz   2779: 
1.445     neumanie 2780:     if (%sectionhash || %grouphash) {
1.446     bisitz   2781:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2782:         $r->print($sections.$groups);
1.448     bisitz   2783:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2784:     } else {
                   2785:         $r->print($sections); 
1.445     neumanie 2786:     }
1.446     bisitz   2787: 
                   2788:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2789:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2790:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2791:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2792:                  ,$chooseopt));
1.209     www      2793: }
                   2794: 
1.562     damieng  2795: # Prints HTML to select parameters from a list of all parameters.
                   2796: # Uses parmmenu and parmboxes.
                   2797: # Used by table and overview modes.
1.468     amueller 2798: #
1.562     damieng  2799: # @param {Apache2::RequestRec} $r - the Apache request
                   2800: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2801: # @param {array reference} $pscat - list of selected parameter names
                   2802: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2803: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2804: sub displaymenu {
1.581     raeburn  2805:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2806: 
1.445     neumanie 2807:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2808:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2809: 
1.581     raeburn  2810:     &parmmenu($r);
1.536     raeburn  2811:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2812:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2813:     $r->print(&Apache::loncommon::end_scrollbox());
                   2814: 
                   2815:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2816:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2817:  
1.209     www      2818: }
                   2819: 
1.562     damieng  2820: # Prints HTML to select a map.
                   2821: # Used by table mode and overview mode.
                   2822: #
                   2823: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2824: # @param {hash reference} $allmaps - hash map pc -> map src
                   2825: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2826: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2827: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.610     raeburn  2828: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
1.445     neumanie 2829: sub mapmenu {
1.610     raeburn  2830:     my ($r,$allmaps,$pschp,$maptitles,$symbp,$parmlev)=@_;
1.468     amueller 2831:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2832:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2833:     my $tree=[];
                   2834:     my $treeinfo={};
                   2835:     if (defined($navmap)) {
1.499     raeburn  2836:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2837:         my $curRes;
                   2838:         my $depth = 0;
1.468     amueller 2839:         my %parent = ();
                   2840:         my $startcount = 5;
                   2841:         my $lastcontainer = $startcount;
                   2842: # preparing what is to show ...
1.461     neumanie 2843:         while ($curRes = $it->next()) {
                   2844:             if ($curRes == $it->BEGIN_MAP()) {
                   2845:                 $depth++;
1.468     amueller 2846:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2847:             }
                   2848:             if ($curRes == $it->END_MAP()) {
                   2849:                 $depth--;
1.468     amueller 2850:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2851:             }
                   2852:             if (ref($curRes)) {
1.468     amueller 2853:                 my $symb = $curRes->symb();
                   2854:                 my $ressymb = $symb;
1.461     neumanie 2855:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2856:                     my $type = 'sequence';
                   2857:                     if ($curRes->is_page()) {
                   2858:                         $type = 'page';
                   2859:                     }
                   2860:                     my $id= $curRes->id();
1.468     amueller 2861:                     my $srcf = $curRes->src();
                   2862:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2863:                     if(!exists($treeinfo->{$id})) {
                   2864:                         push(@$tree,$id);
1.473     amueller 2865:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2866:                         $treeinfo->{$id} = {
1.461     neumanie 2867:                                     depth => $depth,
                   2868:                                     type  => $type,
1.468     amueller 2869:                                     name  => $resource_name,
                   2870:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2871:                                     };
1.462     neumanie 2872:                     }
1.461     neumanie 2873:                 }
                   2874:             }
                   2875:         }
1.462     neumanie 2876:     }
1.473     amueller 2877: # Show it ...    
1.610     raeburn  2878:     my $rowattr = ' id="mapmenu"';
                   2879:     if ($parmlev eq 'general') {
                   2880:         $rowattr .= ' style="display:none"';
                   2881:     }
                   2882:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',$rowattr));
1.461     neumanie 2883:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2884:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2885:         my $whitespace =
                   2886:             '<img src="'
                   2887:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2888:            .'" alt="" />';
                   2889: 
1.498     bisitz   2890:         # Info about selectable folders/maps
                   2891:         $r->print(
                   2892:             '<div class="LC_info">'
1.508     www      2893:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2894:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2895:            .'</div>'
                   2896:         );
                   2897: 
1.536     raeburn  2898:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2899:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2900: 
1.498     bisitz   2901:         # Display row: "All Maps or Folders"
                   2902:         $r->print(
1.523     raeburn  2903:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2904:            .'<td>'
                   2905:            .'<label>'
                   2906:            .'<input type="radio" name="pschp"'
1.497     bisitz   2907:         );
                   2908:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2909:         $r->print(
                   2910:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2911:            .&mt('All Maps or Folders')
                   2912:            .'</label>'
                   2913:            .'<hr /></td>'
                   2914:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2915:         );
1.497     bisitz   2916: 
1.532     raeburn  2917:         # Display row: "Main Content"
1.468     amueller 2918:         if (exists($$allmaps{1})) {
1.498     bisitz   2919:             $r->print(
                   2920:                 &Apache::loncommon::start_data_table_row()
                   2921:                .'<td>'
                   2922:                .'<label>'
                   2923:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2924:             );
1.497     bisitz   2925:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2926:             $r->print(
                   2927:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2928:                .$$maptitles{1}
                   2929:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2930:                .'</label>'
                   2931:                .'</td>'
                   2932:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2933:             );
                   2934:         }
1.497     bisitz   2935: 
                   2936:         # Display rows for all course maps and folders
1.468     amueller 2937:         foreach my $id (@{$tree}) {
                   2938:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2939:             # Indentation
1.468     amueller 2940:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2941:             my $indent;
                   2942:             for (my $i = 0; $i < $depth; $i++) {
                   2943:                 $indent.= $whitespace;
                   2944:             }
1.461     neumanie 2945:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2946:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2947:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2948:             }
1.468     amueller 2949:             my $symb_name = $$symbp{$id};
                   2950:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2951:             $symb_name = $tail;
1.498     bisitz   2952:             $r->print(
                   2953:                 &Apache::loncommon::start_data_table_row()
                   2954:                .'<td>'
                   2955:                .'<label>'
1.463     bisitz   2956:             );
1.498     bisitz   2957:             # Only offer radio button for folders/maps which can be parameterized
                   2958:             if ($allmaps_inverted{$symb_name}) {
                   2959:                 $r->print(
                   2960:                     '<input type ="radio" name="pschp"'
                   2961:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2962:                 );
                   2963:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2964:                 $r->print('/>');
                   2965:             } else {
                   2966:                 $r->print($whitespace);
1.461     neumanie 2967:             }
1.498     bisitz   2968:             $r->print(
                   2969:                 $indent.$icon.'&nbsp;'
                   2970:                .$treeinfo->{$id}->{name}
                   2971:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2972:                .'</label>'
                   2973:                .'</td>'
                   2974:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2975:             );
1.461     neumanie 2976:         }
1.497     bisitz   2977: 
1.523     raeburn  2978:         $r->print(&Apache::loncommon::end_data_table().
                   2979:                   '<br style="line-height:2px;" />'.
                   2980:                   &Apache::loncommon::end_scrollbox());
1.209     www      2981:     }
                   2982: }
                   2983: 
1.563     damieng  2984: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2985: # Used by table and overview modes.
                   2986: #
                   2987: # @param {Apache2::RequestRec} $r - the Apache request
                   2988: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2989: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2990: sub levelmenu {
1.446     bisitz   2991:     my ($r,$alllevs,$parmlev)=@_;
                   2992: 
1.548     raeburn  2993:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2994:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2995:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2996:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2997:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2998:         if ($parmlev eq $$alllevs{$lev}) {
                   2999:             $r->print(' selected="selected"');
                   3000:         }
                   3001:         $r->print('>'.&mt($lev).'</option>');
1.208     www      3002:     }
1.446     bisitz   3003:     $r->print("</select>");
1.208     www      3004: }
                   3005: 
1.211     www      3006: 
1.563     damieng  3007: # Returns HTML to select a section (with a select HTML element).
                   3008: # Used by overview mode.
                   3009: #
                   3010: # @param {array reference} $selectedsections - list of selected section ids
                   3011: # @returns {string}
1.211     www      3012: sub sectionmenu {
1.553     raeburn  3013:     my ($selectedsections)=@_;
1.300     albertel 3014:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  3015:     return '' if (!%sectionhash);
1.300     albertel 3016: 
1.552     raeburn  3017:     my (@possibles,$disabled);
                   3018:     if ($env{'request.course.sec'} ne '') {
                   3019:         @possibles = ($env{'request.course.sec'});
                   3020:         $selectedsections = [$env{'request.course.sec'}];
                   3021:         $disabled = ' disabled="disabled"';
                   3022:     } else {
                   3023:         @possibles = ('all',sort(keys(%sectionhash)));
                   3024:     }
1.553     raeburn  3025:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  3026:     foreach my $s (@possibles) {
1.553     raeburn  3027:         $output .= '    <option value="'.$s.'"';
                   3028:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   3029:             $output .= ' selected="selected"';
1.473     amueller 3030:         }
1.553     raeburn  3031:         $output .= '>'."$s</option>\n";
1.300     albertel 3032:     }
1.553     raeburn  3033:     $output .= "</select>\n";
                   3034:     return $output;
1.269     raeburn  3035: }
                   3036: 
1.563     damieng  3037: # Returns HTML to select a group (with a select HTML element).
                   3038: # Used by overview mode.
                   3039: #
                   3040: # @param {array reference} $selectedgroups - list of selected group names
                   3041: # @returns {string}
1.269     raeburn  3042: sub groupmenu {
1.553     raeburn  3043:     my ($selectedgroups)=@_;
                   3044:     my %grouphash;
                   3045:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3046:         %grouphash = &Apache::longroup::coursegroups();
                   3047:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  3048:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  3049:     }
                   3050:     return '' if (!%grouphash);
1.299     albertel 3051: 
1.553     raeburn  3052:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 3053:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  3054:         $output .= '    <option value="'.$group.'"';
                   3055:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   3056:             $output .=  ' selected="selected"';
1.473     amueller 3057:         }
1.553     raeburn  3058:         $output .= '>'."$group</option>\n";
1.211     www      3059:     }
1.553     raeburn  3060:     $output .= "</select>\n";
                   3061:     return $output;
1.211     www      3062: }
                   3063: 
1.563     damieng  3064: # Returns an array with the given parameter split by comma.
                   3065: # Used by assessparms (table mode).
                   3066: #
                   3067: # @param {string} $keyp - the string to split
                   3068: # @returns {Array<string>}
1.210     www      3069: sub keysplit {
                   3070:     my $keyp=shift;
                   3071:     return (split(/\,/,$keyp));
                   3072: }
                   3073: 
1.563     damieng  3074: # Returns the keys in $name, sorted using $keyorder.
                   3075: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   3076: # Used by assessparms (table mode) for resource level.
                   3077: #
                   3078: # @param {hash reference} $name - parameter key -> parameter name
                   3079: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3080: # @returns {Array<string>}
1.210     www      3081: sub keysinorder {
                   3082:     my ($name,$keyorder)=@_;
                   3083:     return sort {
1.560     damieng  3084:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  3085:     } (keys(%{$name}));
1.210     www      3086: }
                   3087: 
1.563     damieng  3088: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3089: # Used by assessparms (table mode) for map and general levels.
                   3090: #
                   3091: # @param {hash reference} $name - parameter key -> parameter name
                   3092: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3093: # @returns {Array<string>}
1.236     albertel 3094: sub keysinorder_bytype {
                   3095:     my ($name,$keyorder)=@_;
                   3096:     return sort {
1.563     damieng  3097:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3098:         my $tb=(split('_',$b))[-1];
                   3099:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3100:             return ($a cmp $b);
                   3101:         }
                   3102:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3103:     } (keys(%{$name}));
1.236     albertel 3104: }
                   3105: 
1.563     damieng  3106: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3107: # Used by defaultsetter (parameter settings default actions).
                   3108: #
                   3109: # @param {hash reference} $name - hash parameter name -> parameter title
                   3110: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3111: # @returns {Array<string>}
1.211     www      3112: sub keysindisplayorder {
                   3113:     my ($name,$keyorder)=@_;
                   3114:     return sort {
1.560     damieng  3115:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3116:     } (keys(%{$name}));
1.211     www      3117: }
                   3118: 
1.563     damieng  3119: # Prints HTML with a choice to sort results by realm or student first.
                   3120: # Used by overview mode.
                   3121: #
                   3122: # @param {Apache2::RequestRec} $r - the Apache request
                   3123: # @param {string} $sortorder - realmstudent|studentrealm
1.608     raeburn  3124: # @param {string} $context - newoverview|overview
1.214     www      3125: sub sortmenu {
1.608     raeburn  3126:     my ($r,$sortorder,$context)=@_;
                   3127:     my %text;
                   3128:     if ($context eq 'newoverview') {
                   3129:         %text = &Apache::lonlocal::texthash (
                   3130:                    realmstudent => 'Sort by location in course first, then student (group/section)',
                   3131:                    studentrealm => 'Sort by student (group/section) first, then location in course',
                   3132:         );
                   3133:     } else {
                   3134:         %text = &Apache::lonlocal::texthash (
                   3135:                    realmstudent => 'Sort by realm first, then student (group/section)',
                   3136:                    studentrealm => 'Sort by student (group/section) first, then realm',
                   3137:         );
1.214     www      3138:     }
1.608     raeburn  3139:     my %sortchecked = (
                   3140:        realmstudent => ' checked="checked"',
                   3141:        studentrealm => '',
                   3142:     );
1.214     www      3143:     if ($sortorder eq 'studentrealm') {
1.608     raeburn  3144:         $sortchecked{'studentrealm'} = $sortchecked{'realmstudent'};
                   3145:         $sortchecked{'realmstudent'} = '';
                   3146:     }
                   3147:     foreach my $sorttype ('realmstudent','studentrealm') {
                   3148:         $r->print('<br /><label><input type="radio" name="sortorder" value="'.$sorttype.'"'.$sortchecked{$sorttype}.' />'.
                   3149:                   $text{$sorttype}.'</label>');
1.214     www      3150:     }
                   3151: }
                   3152: 
1.563     damieng  3153: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3154: #
                   3155: # @returns {hash}
1.211     www      3156: sub standardkeyorder {
                   3157:     return ('parameter_0_opendate' => 1,
1.473     amueller 3158:         'parameter_0_duedate' => 2,
                   3159:         'parameter_0_answerdate' => 3,
                   3160:         'parameter_0_interval' => 4,
                   3161:         'parameter_0_weight' => 5,
                   3162:         'parameter_0_maxtries' => 6,
                   3163:         'parameter_0_hinttries' => 7,
                   3164:         'parameter_0_contentopen' => 8,
                   3165:         'parameter_0_contentclose' => 9,
                   3166:         'parameter_0_type' => 10,
                   3167:         'parameter_0_problemstatus' => 11,
                   3168:         'parameter_0_hiddenresource' => 12,
                   3169:         'parameter_0_hiddenparts' => 13,
                   3170:         'parameter_0_display' => 14,
                   3171:         'parameter_0_ordered' => 15,
                   3172:         'parameter_0_tol' => 16,
                   3173:         'parameter_0_sig' => 17,
                   3174:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3175:         'parameter_0_discussend' => 19,
                   3176:         'parameter_0_discusshide' => 20,
                   3177:         'parameter_0_discussvote' => 21,
1.560     damieng  3178:         'parameter_0_printstartdate'  =>  22,
                   3179:         'parameter_0_printenddate' =>  23);
1.211     www      3180: }
                   3181: 
1.59      matthew  3182: 
1.560     damieng  3183: # Table mode UI.
1.563     damieng  3184: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3185: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3186: #
                   3187: # Parameters used from the request:
                   3188: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3189: # cgroup - selected group
                   3190: # command - 'set': direct access to table mode for a resource
                   3191: # csec - selected section
                   3192: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3193: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3194: # id - student/employee ID
                   3195: # parmlev - selected level (full|map|general)
                   3196: # part - selected part (unused ?)
                   3197: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3198: # pres_type - &&&-separated parameter types
                   3199: # pres_value - &&&-separated parameter values
                   3200: # prevvisit - '1' if the user has submitted the form before
                   3201: # pscat (multiple values) - selected parameter names
1.566     damieng  3202: # pschp - selected map pc, or 'all'
1.563     damieng  3203: # psprt (multiple values) - list of selected parameter parts
                   3204: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3205: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3206: # symb - resource symb (when a single resource is selected)
                   3207: # udom - selected user domain
                   3208: # uname - selected user name
                   3209: # url - used only with command 'set', the resource url
                   3210: #
                   3211: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3212: # @param $parm_permission - ref to hash of permissions
                   3213: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3214: sub assessparms {
1.1       www      3215: 
1.568     raeburn  3216:     my ($r,$parm_permission) = @_;
1.201     www      3217: 
1.512     foxr     3218: 
                   3219: # -------------------------------------------------------- Variable declaration
1.566     damieng  3220:     my @ids=(); # resource and map ids
                   3221:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3222:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3223:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3224:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3225:     my %uris=(); # hash resource/map id -> resource src
                   3226:     my %maptitles=(); # hash map pc or src -> map title
                   3227:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3228:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3229:     my %alllevs=(); # hash English level title -> value
                   3230: 
                   3231:     my $uname; # selected user name
                   3232:     my $udom; # selected user domain
                   3233:     my $uhome; # server with the user's files, or 'no_host'
                   3234:     my $csec; # selected section name
                   3235:     my $cgroup; # selected group name
                   3236:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3237:     my $numreclinks = 0;
1.446     bisitz   3238: 
1.190     albertel 3239:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3240: 
1.57      albertel 3241:     $alllevs{'Resource Level'}='full';
1.215     www      3242:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3243:     $alllevs{'Course Level'}='general';
                   3244: 
1.563     damieng  3245:     my %allparms; # hash parameter name -> parameter title
                   3246:     my %allparts; # hash parameter part -> part title
1.512     foxr     3247: # ------------------------------------------------------------------------------
                   3248: 
1.210     www      3249: #
                   3250: # Order in which these parameters will be displayed
                   3251: #
1.211     www      3252:     my %keyorder=&standardkeyorder();
                   3253: 
1.512     foxr     3254: #    @ids=();
                   3255: #    %symbp=();       # These seem defined above already.
                   3256: #    %typep=();
1.43      albertel 3257: 
                   3258:     my $message='';
                   3259: 
1.190     albertel 3260:     $csec=$env{'form.csec'};
1.552     raeburn  3261:     if ($env{'request.course.sec'} ne '') {
                   3262:         $csec = $env{'request.course.sec'};    
                   3263:     }
                   3264: 
1.553     raeburn  3265: # Check group privs.
1.269     raeburn  3266:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3267:     my $noeditgrp; 
                   3268:     if ($cgroup ne '') {
                   3269:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3270:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3271:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3272:                 $noeditgrp = 1;
                   3273:             }
                   3274:         }
                   3275:     }
1.188     www      3276: 
1.190     albertel 3277:     if      ($udom=$env{'form.udom'}) {
                   3278:     } elsif ($udom=$env{'request.role.domain'}) {
                   3279:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3280:     } else {
1.473     amueller 3281:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3282:     }
1.468     amueller 3283:     
1.43      albertel 3284: 
1.134     albertel 3285:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3286:     my $pschp=$env{'form.pschp'};
1.506     www      3287: 
                   3288: 
1.134     albertel 3289:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3290:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3291:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3292: 
1.43      albertel 3293:     my $pssymb='';
1.57      albertel 3294:     my $parmlev='';
1.446     bisitz   3295: 
1.190     albertel 3296:     unless ($env{'form.parmlev'}) {
1.57      albertel 3297:         $parmlev = 'map';
                   3298:     } else {
1.190     albertel 3299:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3300:     }
1.26      www      3301: 
1.29      www      3302: # ----------------------------------------------- Was this started from grades?
                   3303: 
1.560     damieng  3304:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3305:             (!$env{'form.dis'})) {
1.473     amueller 3306:         my $url=$env{'form.url'};
                   3307:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3308:         $pssymb=&Apache::lonnet::symbread($url);
                   3309:         if (!@pscat) { @pscat=('all'); }
                   3310:         $pschp='';
1.57      albertel 3311:         $parmlev = 'full';
1.190     albertel 3312:     } elsif ($env{'form.symb'}) {
1.473     amueller 3313:         $pssymb=$env{'form.symb'};
                   3314:         if (!@pscat) { @pscat=('all'); }
                   3315:         $pschp='';
1.57      albertel 3316:         $parmlev = 'full';
1.43      albertel 3317:     } else {
1.473     amueller 3318:         $env{'form.url'}='';
1.43      albertel 3319:     }
                   3320: 
1.190     albertel 3321:     my $id=$env{'form.id'};
1.43      albertel 3322:     if (($id) && ($udom)) {
1.555     raeburn  3323:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3324:         if ($uname) {
                   3325:             $id='';
                   3326:         } else {
                   3327:             $message=
1.540     bisitz   3328:                 '<p class="LC_warning">'.
                   3329:                 &mt('Unknown ID [_1] at domain [_2]',
                   3330:                     "'".$id."'","'".$udom."'").
                   3331:                 '</p>';
1.473     amueller 3332:         }
1.43      albertel 3333:     } else {
1.473     amueller 3334:         $uname=$env{'form.uname'};
1.43      albertel 3335:     }
                   3336:     unless ($udom) { $uname=''; }
                   3337:     $uhome='';
                   3338:     if ($uname) {
1.473     amueller 3339:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3340:         if ($uhome eq 'no_host') {
1.473     amueller 3341:             $message=
1.540     bisitz   3342:                 '<p class="LC_warning">'.
                   3343:                 &mt('Unknown user [_1] at domain [_2]',
                   3344:                     "'".$uname."'","'".$udom."'").
                   3345:                 '</p>';
1.473     amueller 3346:             $uname='';
1.12      www      3347:         } else {
1.473     amueller 3348:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3349:                           $env{'request.course.id'});
                   3350:             if ($csec eq '-1') {
1.596     raeburn  3351:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3352:                 if ($env{'form.userroles'} eq 'any') {
                   3353:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3354:                         $csec = $env{'request.course.sec'};
                   3355:                         $message = '<span class="LC_info">';
                   3356:                         if ($crstype eq 'Community') {
                   3357:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3358:                                             $uname,$udom);
                   3359:                         } else {
                   3360:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3361:                                             $uname,$udom);
                   3362:                         }
                   3363:                         $message .= '</span>';
                   3364:                     } else {
                   3365:                         my @possroles = ('in','ep','ta','cr');
                   3366:                         if ($crstype eq 'Community') {
                   3367:                             unshift(@possroles,'co');
                   3368:                         } else {
                   3369:                             unshift(@possroles,'cc');
                   3370:                         }
                   3371:                         my %not_student_roles =
                   3372:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3373:                                                           \@possroles,[$udom],1,1);
                   3374:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3375:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3376:                         my %sections_by_role;
                   3377:                         foreach my $role (keys(%not_student_roles)) {
                   3378:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3379:                                 my ($rolename,$sec) = ($1,$2);
                   3380:                                 if ($rolename =~ m{^cr/}) {
                   3381:                                     $rolename = 'cr';
                   3382:                                 }
                   3383:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3384:                             }
                   3385:                         }
                   3386:                         my $numroles = scalar(keys(%sections_by_role));
                   3387:                         if ($numroles) {
                   3388:                             foreach my $role (@possroles) {
                   3389:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3390:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3391:                                     $csec = $secs[0];
                   3392:                                     last;
                   3393:                                 }
                   3394:                             }
                   3395:                         }
                   3396:                         if ($csec eq '-1') {
                   3397:                             $message = '<span class="LC_warning">';
                   3398:                             if ($crstype eq 'Community') {
                   3399:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3400:                                                 $uname,$udom);
                   3401:                             } else {
                   3402:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3403:                                                 $uname,$udom);
                   3404:                             }
                   3405:                             $message .= '</span>';
                   3406:                             $uname='';
                   3407:                             if ($env{'request.course.sec'} ne '') {
                   3408:                                 $csec=$env{'request.course.sec'};
                   3409:                             } else {
                   3410:                                 $csec=$env{'form.csec'};
                   3411:                             }
                   3412:                             $cgroup=$env{'form.cgroup'};
                   3413:                         } else {
                   3414:                             $message = '<span class="LC_info">';
                   3415:                             if ($crstype eq 'Community') {
                   3416:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3417:                                          $uname,$udom);
                   3418:                             } else {
                   3419:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3420:                                                 $uname,$udom);
                   3421:                             }
                   3422:                             $message .= '</span>';
                   3423:                         }
                   3424:                     }
1.594     raeburn  3425:                 } else {
1.596     raeburn  3426:                     $message = '<span class="LC_warning">';
                   3427:                     if ($crstype eq 'Community') {
                   3428:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3429:                                          $uname,$udom);
                   3430:                     } else {
                   3431:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3432:                                          $uname,$udom);
                   3433:                     }
                   3434:                     $message .= '</span>';
                   3435:                     $uname='';
                   3436:                     if ($env{'request.course.sec'} ne '') {
                   3437:                         $csec=$env{'request.course.sec'};
                   3438:                     } else {
                   3439:                         $csec=$env{'form.csec'};
                   3440:                     }
                   3441:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3442:                 }
                   3443:             } elsif ($env{'request.course.sec'} ne '') {
                   3444:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3445:                     $message='<span class="LC_warning">'.
1.594     raeburn  3446:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3447:                                   $uname,$udom,$env{'request.course.sec'}).
                   3448:                               '</span>';
                   3449:                     $uname='';
                   3450:                     $csec=$env{'request.course.sec'};
                   3451:                 }
1.269     raeburn  3452:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3453:             }
                   3454:             if ($uname ne '') {
1.473     amueller 3455:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3456:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3457:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3458:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3459:                             .$name{'lastname'}.' '.$name{'generation'}
                   3460:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3461:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3462:                                    $udom,$uname,$env{'request.course.id'});
                   3463:                 if (@usersgroups > 0) {
                   3464:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3465:                         $cgroup = $usersgroups[0];
                   3466:                     }
                   3467:                 } else {
                   3468:                     $cgroup = '';
1.297     raeburn  3469:                 }
1.269     raeburn  3470:             }
1.12      www      3471:         }
1.43      albertel 3472:     }
1.2       www      3473: 
1.43      albertel 3474:     unless ($csec) { $csec=''; }
1.269     raeburn  3475:     unless ($cgroup) { $cgroup=''; }
1.12      www      3476: 
1.14      www      3477: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3478:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3479:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3480:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3481: 
1.582     raeburn  3482:     %allmaps_inverted = reverse(%allmaps);
                   3483: 
1.57      albertel 3484:     $mapp{'0.0'} = '';
                   3485:     $symbp{'0.0'} = '';
1.99      albertel 3486: 
1.14      www      3487: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3488:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3489:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3490:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3491:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3492:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3493:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3494:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3495:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3496:         my $totalstored = 0;
1.605     raeburn  3497:         my $totalskippeduser = 0;
1.546     raeburn  3498:         my $now = time;
1.473     amueller 3499:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3500:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3501:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3502:                 next if ($csec ne $env{'request.course.sec'});
                   3503:             }
1.556     raeburn  3504:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3505:                 next if ($noeditgrp);
1.605     raeburn  3506:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3507:                 if ($uname eq '') {
                   3508:                     $totalskippeduser ++;
                   3509:                     next;
                   3510:                 }
1.557     raeburn  3511:             }
                   3512:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3513:                 $namematch = 'maplevelrecurse';
                   3514:             }
1.556     raeburn  3515:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3516:                 my (@ok_slots,@fail_slots,@del_slots);
                   3517:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3518:                 my ($level,@all) =
                   3519:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3520:                                      $csec,$cgroup,$courseopt);
                   3521:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3522:                     next if ($slot_name eq '');
                   3523:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3524:                         push(@ok_slots,$slot_name);
                   3525: 
                   3526:                     } else {
                   3527:                         push(@fail_slots,$slot_name);
                   3528:                     }
                   3529:                 }
                   3530:                 if (@ok_slots) {
                   3531:                     $values[$i] = join(':',@ok_slots);
                   3532:                 } else {
                   3533:                     $values[$i] = '';
                   3534:                 }
                   3535:                 if ($all[$level] ne '') {
                   3536:                     my @existing = split(/:/,$all[$level]);
                   3537:                     foreach my $slot_name (@existing) {
                   3538:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3539:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3540:                                 push(@del_slots,$slot_name);
                   3541:                             }
                   3542:                         }
                   3543:                     }
                   3544:                 }
1.554     raeburn  3545:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3546:                 $name = $1;
1.533     raeburn  3547:                 my $val = $values[$i];
1.549     raeburn  3548:                 my $valmatch = '';
1.533     raeburn  3549:                 if ($name eq 'examcode') {
1.544     raeburn  3550:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3551:                         $val = 'valid';
                   3552:                     }
1.546     raeburn  3553:                 } elsif ($name eq 'printstartdate') {
                   3554:                     if ($val =~ /^\d+$/) {
                   3555:                         if ($val > $now) {
                   3556:                             $val = 'future';
                   3557:                         }
                   3558:                     } 
                   3559:                 } elsif ($name eq 'printenddate') {
                   3560:                     if ($val =~ /^\d+$/) {
                   3561:                         if ($val < $now) {
                   3562:                             $val = 'past';
                   3563:                         }
                   3564:                     }
1.549     raeburn  3565:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3566:                     my $stringtype = &get_stringtype($name);
                   3567:                     my $stringmatch = &standard_string_matches($stringtype);
                   3568:                     if (ref($stringmatch) eq 'ARRAY') {
                   3569:                         foreach my $item (@{$stringmatch}) {
                   3570:                             if (ref($item) eq 'ARRAY') {
                   3571:                                 my ($regexpname,$pattern) = @{$item};
                   3572:                                 if ($pattern ne '') {
                   3573:                                     if ($val =~ /$pattern/) {
                   3574:                                         $valmatch = $regexpname;
                   3575:                                         $val = '';
                   3576:                                         last;
                   3577:                                     }
                   3578:                                 }
                   3579:                             }
                   3580:                         }
                   3581:                     }
1.554     raeburn  3582:                 } elsif ($name eq 'interval') {
                   3583:                     my $intervaltype = &get_intervaltype($name);
                   3584:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3585:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3586:                         foreach my $item (@{$intervalmatch}) {
                   3587:                             if (ref($item) eq 'ARRAY') {
                   3588:                                 my ($regexpname,$pattern) = @{$item};
                   3589:                                 if ($pattern ne '') {
                   3590:                                     if ($val =~ /$pattern/) {
                   3591:                                         $valmatch = $regexpname;
                   3592:                                         $val = '';
                   3593:                                         last;
                   3594:                                     }
                   3595:                                 }
                   3596:                             }
                   3597:                         }
                   3598:                     }
1.533     raeburn  3599:                 }
1.504     raeburn  3600:                 $needsrelease =
1.557     raeburn  3601:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3602:                 if ($needsrelease) {
1.505     raeburn  3603:                     unless ($got_chostname) {
1.514     raeburn  3604:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3605:                         $got_chostname = 1;
1.546     raeburn  3606:                     } 
1.557     raeburn  3607:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3608:                                                           $needsrelease,
                   3609:                                                           $cmajor,$cminor);
1.500     raeburn  3610:                 }
1.437     raeburn  3611:             }
1.504     raeburn  3612:             if ($needsnewer) {
1.557     raeburn  3613:                 undef($namematch);
                   3614:             } else {
                   3615:                 my $currneeded;
                   3616:                 if ($needsrelease) {
                   3617:                     $currneeded = $needsrelease;
                   3618:                 }
                   3619:                 if ($namematch) {
                   3620:                     $needsrelease =
                   3621:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3622:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3623:                         unless ($got_chostname) {
                   3624:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3625:                             $got_chostname = 1;
                   3626:                         }
                   3627:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3628:                                                               $needsrelease,
                   3629:                                                               $cmajor,$cminor);
                   3630:                     } else {
                   3631:                         undef($namematch);
                   3632:                     }
                   3633:                 }
                   3634:             }
                   3635:             if ($needsnewer) {
                   3636:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3637:                                                 $cminor,$needsrelease);
                   3638:             } else {
                   3639:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3640:                                      $values[$i],
                   3641:                                      $types[$i],
                   3642:                                      $uname,$udom,$csec,$cgroup);
                   3643:                 $totalstored ++;
                   3644:             }
1.473     amueller 3645:         }
1.68      www      3646: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3647:         if ($totalstored) {
                   3648:             $message.='<p class="LC_warning">'
1.605     raeburn  3649:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3650:                      .'<br />'
1.504     raeburn  3651:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3652:                      .&Apache::loncommon::help_open_topic('Caching')
                   3653:                      .'</p>';
1.605     raeburn  3654:         } else {
                   3655:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3656:         }
                   3657:         if ($totalskippeduser) {
                   3658:             $message .= '<p class="LC_warning">';
                   3659:             if ($uhome eq 'no_host') {
                   3660:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3661:                                 $totalskippeduser);
                   3662:             } elsif ($env{'form.userroles'} eq 'any') {
                   3663:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3664:                                 $totalskippeduser);
                   3665:             } else {
                   3666:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3667:                                 $totalskippeduser);
                   3668:             }
                   3669:             $message .= '</p>';
1.504     raeburn  3670:         }
1.68      www      3671:     }
1.584     raeburn  3672: 
1.57      albertel 3673: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3674:     if ($pscat[0] eq "all") {
                   3675:         @pscat = (keys(%allparms));
                   3676:     }
                   3677:     if (!@pscat) {
                   3678:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3679:     };
                   3680:     if ($psprt[0] eq "all" || !@psprt) {
                   3681:         @psprt = (keys(%allparts));
                   3682:     }
1.2       www      3683: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3684: 
1.531     raeburn  3685:     my $crstype = &Apache::loncommon::course_type();
                   3686:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3687: 
1.548     raeburn  3688:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3689:             'date_interval','int','float','string','string_lenient',
                   3690:             'string_examcode','string_deeplink','string_discussvote',
                   3691:             'string_useslots','string_problemstatus','string_ip',
                   3692:             'string_questiontype') {
1.473     amueller 3693:         $r->print('<input type="hidden" value="'.
1.563     damieng  3694:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3695:             '" name="recent_'.$item.'" />');
1.44      albertel 3696:     }
1.446     bisitz   3697: 
1.459     bisitz   3698:     # ----- Start Parameter Selection
                   3699: 
1.606     raeburn  3700:     # Hide parm selection and possibly table?
                   3701:     my ($tablejs,$tabledivsty);
                   3702:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
                   3703:         ($env{'form.dis'}) && ($pssymb eq '')) {
                   3704:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
                   3705:         $tabledivsty = ' style="display:none"';
                   3706:     }
1.459     bisitz   3707:     $r->print(<<ENDPARMSELSCRIPT);
                   3708: <script type="text/javascript">
                   3709: // <![CDATA[
                   3710: function parmsel_show() {
1.562     damieng  3711:     document.getElementById('parmsel').style.display = "";
                   3712:     document.getElementById('parmsellink').style.display = "none";
1.606     raeburn  3713:     $tablejs
1.459     bisitz   3714: }
                   3715: // ]]>
                   3716: </script>
                   3717: ENDPARMSELSCRIPT
1.474     amueller 3718:     
1.445     neumanie 3719:     if (!$pssymb) {
1.563     damieng  3720:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3721:         my $parmselhiddenstyle=' style="display:none"';
                   3722:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3723:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3724:         } else  {
                   3725:            $r->print('<div id="parmsel">');
                   3726:         }
                   3727: 
1.491     bisitz   3728:         # Step 1
1.523     raeburn  3729:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3730:         $r->print('
1.474     amueller 3731: <script type="text/javascript">
1.523     raeburn  3732: // <![CDATA['.
                   3733:                  &showhide_js().'
1.474     amueller 3734: // ]]>
                   3735: </script>
1.523     raeburn  3736: ');
                   3737:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3738:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3739:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.610     raeburn  3740:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.491     bisitz   3741:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3742:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3743:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3744:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3745:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3746: 
                   3747:         # Step 2
1.523     raeburn  3748:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3749:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3750: 
                   3751:         # Step 3
1.523     raeburn  3752:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3753:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3754:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3755:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3756:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3757: 
                   3758:         # Update Display Button
1.486     www      3759:         $r->print('<p>'
                   3760:              .'<input type="submit" name="dis"'
1.511     www      3761:              .' value="'.&mt('Update Display').'" />'
1.486     www      3762:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3763:              .'</p>');
                   3764:         $r->print('</div>');
1.491     bisitz   3765: 
1.486     www      3766:         # Offer link to display parameter selection again
                   3767:         $r->print('<p id="parmsellink"');
                   3768:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3769:            $r->print($parmselhiddenstyle);
                   3770:         }
                   3771:         $r->print('>'
                   3772:              .'<a href="javascript:parmsel_show()">'
                   3773:              .&mt('Change Parameter Selection')
                   3774:              .'</a>'
                   3775:              .'</p>');
1.44      albertel 3776:     } else {
1.478     amueller 3777:         # parameter screen for a single resource. 
1.486     www      3778:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3779:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3780:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3781:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3782:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3783:                   '<br />');
                   3784:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3785:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3786:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3787:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3788:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3789:         $r->print('<p>'
1.459     bisitz   3790:              .'<input type="submit" name="dis"'
1.511     www      3791:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3792:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3793:              .'</p>');
1.459     bisitz   3794:     }
1.478     amueller 3795:     
1.486     www      3796:     # ----- End Parameter Selection
1.57      albertel 3797: 
1.459     bisitz   3798:     # Display Messages
                   3799:     $r->print('<div>'.$message.'</div>');
1.210     www      3800: 
1.57      albertel 3801: 
                   3802:     my @temp_pscat;
                   3803:     map {
                   3804:         my $cat = $_;
                   3805:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3806:     } @pscat;
                   3807: 
                   3808:     @pscat = @temp_pscat;
                   3809: 
1.548     raeburn  3810: 
1.209     www      3811:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3812: # ----------------------------------------------------------------- Start Table
1.57      albertel 3813:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3814:         my $csuname=$env{'user.name'};
                   3815:         my $csudom=$env{'user.domain'};
1.568     raeburn  3816:         my $readonly = 1;
                   3817:         if ($parm_permission->{'edit'}) {
                   3818:             undef($readonly); 
                   3819:         }
1.606     raeburn  3820:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3821: 
1.203     www      3822:         if ($parmlev eq 'full') {
1.506     www      3823: #
                   3824: # This produces the cascading table output of parameters
                   3825: #
1.578     raeburn  3826:             my $coursespan=$csec?8:5;
                   3827:             my $userspan=3;
1.560     damieng  3828:             if ($cgroup ne '') {
1.578     raeburn  3829:                 $coursespan += 3;
1.560     damieng  3830:             }
1.473     amueller 3831: 
1.560     damieng  3832:             $r->print(&Apache::loncommon::start_data_table());
                   3833:             #
                   3834:             # This produces the headers
                   3835:             #
                   3836:             $r->print('<tr><td colspan="5"></td>');
                   3837:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3838:             if ($uname) {
1.473     amueller 3839:                 if (@usersgroups > 1) {
1.560     damieng  3840:                     $userspan ++;
                   3841:                 }
                   3842:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3843:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3844:             }
                   3845:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3846:                 'pie'    => "Parameter in Effect",
                   3847:                 'csv'    => "Current Session Value",
1.472     amueller 3848:                 'rl'     => "Resource Level",
1.473     amueller 3849:                 'ic'     => 'in Course',
                   3850:                 'aut'    => "Assessment URL and Title",
                   3851:                 'type'   => 'Type',
                   3852:                 'emof'   => "Enclosing Map or Folder",
                   3853:                 'part'   => 'Part',
1.472     amueller 3854:                 'pn'     => 'Parameter Name',
1.473     amueller 3855:                 'def'    => 'default',
                   3856:                 'femof'  => 'from Enclosing Map or Folder',
                   3857:                 'gen'    => 'general',
                   3858:                 'foremf' => 'for Enclosing Map or Folder',
                   3859:                 'fr'     => 'for Resource'
                   3860:             );
1.560     damieng  3861:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3862: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3863: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3864: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3865: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3866: 
1.10      www      3867: ENDTABLETWO
1.560     damieng  3868:             if ($csec) {
1.578     raeburn  3869:                 $r->print('<th colspan="3">'.
1.560     damieng  3870:                 &mt("in Section")." $csec</th>");
                   3871:             }
                   3872:             if ($cgroup) {
1.578     raeburn  3873:                 $r->print('<th colspan="3">'.
1.472     amueller 3874:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3875:             }
                   3876:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3877: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3878: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3879: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3880: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3881: ENDTABLEHEADFOUR
1.57      albertel 3882: 
1.560     damieng  3883:             if ($csec) {
1.578     raeburn  3884:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3885:             }
1.473     amueller 3886: 
1.560     damieng  3887:             if ($cgroup) {
1.578     raeburn  3888:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3889:             }
                   3890: 
                   3891:             if ($uname) {
                   3892:                 if (@usersgroups > 1) {
                   3893:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3894:                 }
1.578     raeburn  3895:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3896:             }
                   3897: 
                   3898:             $r->print('</tr>');
1.506     www      3899: #
                   3900: # Done with the headers
                   3901: # 
1.560     damieng  3902:             my $defbgone='';
                   3903:             my $defbgtwo='';
                   3904:             my $defbgthree = '';
1.57      albertel 3905: 
1.560     damieng  3906:             foreach my $rid (@ids) {
1.57      albertel 3907: 
                   3908:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3909:                 if ((!$pssymb &&
1.560     damieng  3910:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3911:                         ||
                   3912:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3913: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3914:                     if ($defbgone eq '#E0E099') {
                   3915:                         $defbgone='#E0E0DD';
1.57      albertel 3916:                     } else {
1.419     bisitz   3917:                         $defbgone='#E0E099';
1.57      albertel 3918:                     }
1.419     bisitz   3919:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3920:                         $defbgtwo='#FFFFDD';
1.57      albertel 3921:                     } else {
1.473     amueller 3922:                         $defbgtwo='#FFFF99';
1.57      albertel 3923:                     }
1.419     bisitz   3924:                     if ($defbgthree eq '#FFBB99') {
                   3925:                         $defbgthree='#FFBBDD';
1.269     raeburn  3926:                     } else {
1.419     bisitz   3927:                         $defbgthree='#FFBB99';
1.269     raeburn  3928:                     }
                   3929: 
1.57      albertel 3930:                     my $thistitle='';
                   3931:                     my %name=   ();
                   3932:                     undef %name;
                   3933:                     my %part=   ();
                   3934:                     my %display=();
                   3935:                     my %type=   ();
                   3936:                     my %default=();
1.196     www      3937:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3938:                     my $toolsymb;
                   3939:                     if ($uri =~ /ext\.tool$/) {
                   3940:                         $toolsymb = $symbp{$rid};
                   3941:                     }
1.57      albertel 3942: 
1.506     www      3943:                     my $filter=$env{'form.filter'};
1.548     raeburn  3944:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3945:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3946:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3947:     # We may only want certain parameters listed
                   3948:                             if ($filter) {
                   3949:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3950:                             }
                   3951:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3952:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3953: 
1.584     raeburn  3954:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3955:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3956:                                 my $identifier;
                   3957:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3958:                                     $identifier = $1;
                   3959:                                 }
                   3960:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3961:                             } else {
                   3962:                                 $display{$tempkeyp} = $parmdis;
                   3963:                             }
                   3964:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3965:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3966:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3967:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3968:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3969:                         }
                   3970:                     }
1.548     raeburn  3971:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3972:                     if ($totalparms>0) {
1.560     damieng  3973:                         my $firstrow=1;
1.473     amueller 3974:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3975:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3976:                         my @recurseup;
                   3977:                         if (ref($navmap) && $mapp{$rid}) {
                   3978:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3979:                         }
1.419     bisitz   3980:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3981:                              ' rowspan='.$totalparms.
1.419     bisitz   3982:                              '><tt><font size="-1">'.
1.57      albertel 3983:                              join(' / ',split(/\//,$uri)).
                   3984:                              '</font></tt><p><b>'.
1.154     albertel 3985:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3986:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3987:                           &escape($symbp{$rid}).
1.336     albertel 3988:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3989:                              " target=\"_self\">$title");
1.57      albertel 3990: 
                   3991:                         if ($thistitle) {
1.473     amueller 3992:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3993:                         }
                   3994:                         $r->print('</a></b></td>');
1.419     bisitz   3995:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3996:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3997:                                       '</td>');
                   3998: 
1.419     bisitz   3999:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 4000:                                       ' rowspan='.$totalparms.
1.238     www      4001:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  4002:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 4003:                             unless ($firstrow) {
                   4004:                                 $r->print('<tr>');
                   4005:                             } else {
                   4006:                                 undef $firstrow;
                   4007:                             }
1.548     raeburn  4008:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 4009:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  4010:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  4011:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   4012:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   4013:                                        \$numreclinks);
1.57      albertel 4014:                         }
                   4015:                     }
                   4016:                 }
                   4017:             } # end foreach ids
1.43      albertel 4018: # -------------------------------------------------- End entry for one resource
1.517     www      4019:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      4020:         } # end of  full
1.57      albertel 4021: #--------------------------------------------------- Entry for parm level map
                   4022:         if ($parmlev eq 'map') {
1.419     bisitz   4023:             my $defbgone = '#E0E099';
                   4024:             my $defbgtwo = '#FFFF99';
                   4025:             my $defbgthree = '#FFBB99';
1.57      albertel 4026: 
                   4027:             my %maplist;
                   4028: 
                   4029:             if ($pschp eq 'all') {
1.446     bisitz   4030:                 %maplist = %allmaps;
1.57      albertel 4031:             } else {
                   4032:                 %maplist = ($pschp => $mapp{$pschp});
                   4033:             }
                   4034: 
                   4035: #-------------------------------------------- for each map, gather information
                   4036:             my $mapid;
1.607     raeburn  4037:             foreach $mapid (sort { $a <=> $b } keys(%maplist)) {
1.60      albertel 4038:                 my $maptitle = $maplist{$mapid};
1.57      albertel 4039: 
                   4040: #-----------------------  loop through ids and get all parameter types for map
                   4041: #-----------------------------------------          and associated information
                   4042:                 my %name = ();
                   4043:                 my %part = ();
                   4044:                 my %display = ();
                   4045:                 my %type = ();
                   4046:                 my %default = ();
                   4047:                 my $map = 0;
                   4048: 
1.473     amueller 4049: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   4050: 
1.548     raeburn  4051:                 foreach my $id (@ids) {
                   4052:                     ($map)=($id =~ /([\d]*?)\./);
                   4053:                     my $rid = $id;
1.446     bisitz   4054: 
1.57      albertel 4055: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   4056: 
1.560     damieng  4057:                     if ($map eq $mapid) {
1.473     amueller 4058:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4059:                         my $toolsymb;
                   4060:                         if ($uri =~ /ext\.tool$/) {
                   4061:                             $toolsymb = $symbp{$rid};
                   4062:                         }
1.582     raeburn  4063: 
1.57      albertel 4064: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   4065: 
                   4066: #--------------------------------------------------------------------
                   4067: # @catmarker contains list of all possible parameters including part #s
                   4068: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4069: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4070: # When storing information, store as part 0
                   4071: # When requesting information, request from full part
                   4072: #-------------------------------------------------------------------
1.548     raeburn  4073:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4074:                             my $tempkeyp = $fullkeyp;
                   4075:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 4076: 
1.548     raeburn  4077:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4078:                                 $part{$tempkeyp}="0";
1.584     raeburn  4079:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4080:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4081:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   4082:                                     my $identifier;
                   4083:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4084:                                         $identifier = $1;
                   4085:                                     }
                   4086:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4087:                                 } else {
                   4088:                                     $display{$tempkeyp} = $parmdis;
                   4089:                                 }
                   4090:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4091:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4092:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4093:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4094:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 4095:                               }
                   4096:                         } # end loop through keys
1.560     damieng  4097:                     }
1.57      albertel 4098:                 } # end loop through ids
1.446     bisitz   4099: 
1.57      albertel 4100: #---------------------------------------------------- print header information
1.133     www      4101:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4102:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4103:                 my $tmp="";
1.57      albertel 4104:                 if ($uname) {
1.473     amueller 4105:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4106:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4107:                         &mt('in')." \n";
1.57      albertel 4108:                 } else {
1.401     bisitz   4109:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4110:                 }
1.269     raeburn  4111:                 if ($cgroup) {
1.401     bisitz   4112:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4113:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4114:                     $csec = '';
                   4115:                 } elsif ($csec) {
1.401     bisitz   4116:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4117:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4118:                 }
1.401     bisitz   4119:                 $r->print('<div align="center"><h4>'
                   4120:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4121:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4122:                              ,$tmp
                   4123:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4124:                              )
                   4125:                          ."<br /></h4>\n"
1.422     bisitz   4126:                 );
1.57      albertel 4127: #---------------------------------------------------------------- print table
1.419     bisitz   4128:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4129:                          .&Apache::loncommon::start_data_table_header_row()
                   4130:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4131:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4132:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4133:                          .&Apache::loncommon::end_data_table_header_row()
                   4134:                 );
1.57      albertel 4135: 
1.582     raeburn  4136:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4137:                 my @recurseup;
                   4138:                 if (ref($navmap)) {
                   4139:                      my $mapres = $navmap->getByMapPc($mapid);
                   4140:                      if (ref($mapres)) {
                   4141:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4142:                      }
                   4143:                 }
                   4144: 
                   4145: 
1.548     raeburn  4146:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4147:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4148:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4149:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4150:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4151:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4152:                            \$numreclinks);
1.57      albertel 4153:                 }
1.422     bisitz   4154:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4155:                          .'</div>'
                   4156:                 );
1.57      albertel 4157:             } # end each map
                   4158:         } # end of $parmlev eq map
                   4159: #--------------------------------- Entry for parm level general (Course level)
                   4160:         if ($parmlev eq 'general') {
1.473     amueller 4161:             my $defbgone = '#E0E099';
1.419     bisitz   4162:             my $defbgtwo = '#FFFF99';
                   4163:             my $defbgthree = '#FFBB99';
1.57      albertel 4164: 
                   4165: #-------------------------------------------- for each map, gather information
                   4166:             my $mapid="0.0";
                   4167: #-----------------------  loop through ids and get all parameter types for map
                   4168: #-----------------------------------------          and associated information
                   4169:             my %name = ();
                   4170:             my %part = ();
                   4171:             my %display = ();
                   4172:             my %type = ();
                   4173:             my %default = ();
1.446     bisitz   4174: 
1.548     raeburn  4175:             foreach $id (@ids) {
                   4176:                 my $rid = $id;
1.446     bisitz   4177: 
1.196     www      4178:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4179:                 my $toolsymb;
                   4180:                 if ($uri =~ /ext\.tool$/) {
                   4181:                     $toolsymb = $symbp{$rid};
                   4182:                 }
1.57      albertel 4183: 
                   4184: #--------------------------------------------------------------------
                   4185: # @catmarker contains list of all possible parameters including part #s
                   4186: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4187: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4188: # When storing information, store as part 0
                   4189: # When requesting information, request from full part
                   4190: #-------------------------------------------------------------------
1.548     raeburn  4191:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4192:                     my $tempkeyp = $fullkeyp;
                   4193:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4194:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4195:                         $part{$tempkeyp}="0";
1.584     raeburn  4196:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4197:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4198:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4199:                             my $identifier;
                   4200:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4201:                                 $identifier = $1;
                   4202:                             }
                   4203:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4204:                         } else {
                   4205:                             $display{$tempkeyp} = $parmdis;
                   4206:                         }
                   4207:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4208:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4209:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4210:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4211:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4212:                     }
1.57      albertel 4213:                 } # end loop through keys
                   4214:             } # end loop through ids
1.446     bisitz   4215: 
1.57      albertel 4216: #---------------------------------------------------- print header information
1.473     amueller 4217:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4218:             $r->print(<<ENDMAPONE);
1.419     bisitz   4219: <center>
                   4220: <h4>$setdef
1.135     albertel 4221: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4222: ENDMAPONE
                   4223:             if ($uname) {
1.473     amueller 4224:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4225:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4226:             } else {
1.135     albertel 4227:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4228:             }
1.446     bisitz   4229: 
1.135     albertel 4230:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4231:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4232:             $r->print("</h4>\n");
1.57      albertel 4233: #---------------------------------------------------------------- print table
1.419     bisitz   4234:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4235:                      .&Apache::loncommon::start_data_table_header_row()
                   4236:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4237:                      .'<th>'.&mt('Default Value').'</th>'
                   4238:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4239:                      .&Apache::loncommon::end_data_table_header_row()
                   4240:             );
1.57      albertel 4241: 
1.548     raeburn  4242:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4243:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4244:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4245:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4246:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4247:                            $readonly);
1.57      albertel 4248:             }
1.419     bisitz   4249:             $r->print(&Apache::loncommon::end_data_table()
                   4250:                      .'</p>'
                   4251:                      .'</center>'
                   4252:             );
1.57      albertel 4253:         } # end of $parmlev eq general
1.606     raeburn  4254:         $r->print('</div>');
1.43      albertel 4255:     }
1.507     www      4256:     $r->print('</form>');
1.582     raeburn  4257:     if ($numreclinks) {
                   4258:         $r->print(<<"END");
                   4259: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4260: <input type="hidden" name="pschp" />
                   4261: <input type="hidden" name="pscat" />
                   4262: <input type="hidden" name="psprt" />
                   4263: <input type="hidden" name="hideparmsel" value="hidden" />
                   4264: </form>
                   4265: <script type="text/javascript">
                   4266: function pjumprec(rid,name,part) {
                   4267:     document.forms.recurseform.pschp.value = rid;
                   4268:     document.forms.recurseform.pscat.value = name;
                   4269:     document.forms.recurseform.psprt.value = part;
                   4270:     document.forms.recurseform.submit();
                   4271:     return false;
                   4272: }
                   4273: </script>
                   4274: END
                   4275:     }
1.507     www      4276:     &endSettingsScreen($r);
                   4277:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4278: } # end sub assessparms
1.30      www      4279: 
1.560     damieng  4280: 
                   4281: 
1.120     www      4282: ##################################################
1.560     damieng  4283: # OVERVIEW MODE
1.207     www      4284: ##################################################
1.124     www      4285: 
1.563     damieng  4286: my $tableopen; # boolean, true if HTML table is already opened
                   4287: 
                   4288: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4289: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4290: # @returns {string}
1.124     www      4291: sub tablestart {
1.576     raeburn  4292:     my ($readonly,$is_map) = @_;
1.124     www      4293:     if ($tableopen) {
1.552     raeburn  4294:         return '';
1.124     www      4295:     } else {
1.552     raeburn  4296:         $tableopen=1;
                   4297:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4298:         if ($readonly) {
                   4299:             $output .= '<th>'.&mt('Current value').'</th>';
                   4300:         } else {
1.576     raeburn  4301:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4302:                        '<th>'.&mt('Set to ...').'</th>';
                   4303:             if ($is_map) {
                   4304:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4305:             }
1.552     raeburn  4306:         }
                   4307:         $output .= '</tr>';
                   4308:         return $output;
1.124     www      4309:     }
                   4310: }
                   4311: 
1.563     damieng  4312: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4313: # @returns {string}
1.124     www      4314: sub tableend {
                   4315:     if ($tableopen) {
1.560     damieng  4316:         $tableopen=0;
                   4317:         return &Apache::loncommon::end_data_table();
1.124     www      4318:     } else {
1.560     damieng  4319:         return'';
1.124     www      4320:     }
                   4321: }
                   4322: 
1.563     damieng  4323: # Reads course and user information.
                   4324: # 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).
                   4325: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4326: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4327: # @param {string} $crs - course number
                   4328: # @param {string} $dom - course domain
                   4329: # @returns {hash reference|Array}
1.207     www      4330: sub readdata {
                   4331:     my ($crs,$dom)=@_;
                   4332: # Read coursedata
                   4333:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4334: # Read userdata
                   4335: 
                   4336:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4337:     foreach my $user (keys(%$classlist)) {
                   4338:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4339:             my ($tuname,$tudom)=($1,$2);
                   4340:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4341:             foreach my $userkey (keys(%{$useropt})) {
                   4342:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4343:                     my $newkey=$userkey;
1.548     raeburn  4344:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4345:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4346:                 }
                   4347:             }
1.473     amueller 4348:         }
                   4349:     }
1.552     raeburn  4350:     if (wantarray) {
                   4351:         return ($resourcedata,$classlist);
                   4352:     } else {
                   4353:         return $resourcedata;
                   4354:     }
1.207     www      4355: }
                   4356: 
                   4357: 
1.563     damieng  4358: # Stores parameter data, using form parameters directly.
                   4359: #
                   4360: # 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  4361: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4362: # del_* - remove a parameter
                   4363: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4364: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4365: # key_* - date values
                   4366: # days_* - for date intervals
                   4367: # hours_* - for date intervals
                   4368: # minutes_* - for date intervals
                   4369: # seconds_* - for date intervals
                   4370: # done_* - for date intervals
                   4371: # typeof_* - parameter type
                   4372: # 
                   4373: # @param {Apache2::RequestRec} $r - the Apache request
                   4374: # @param {string} $crs - course number
                   4375: # @param {string} $dom - course domain
1.208     www      4376: sub storedata {
                   4377:     my ($r,$crs,$dom)=@_;
1.207     www      4378: # Set userlevel immediately
                   4379: # Do an intermediate store of course level
                   4380:     my $olddata=&readdata($crs,$dom);
1.124     www      4381:     my %newdata=();
                   4382:     undef %newdata;
                   4383:     my @deldata=();
1.576     raeburn  4384:     my @delrec=();
                   4385:     my @delnonrec=();
1.124     www      4386:     undef @deldata;
1.504     raeburn  4387:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4388:     my $now = time;
1.560     damieng  4389:     foreach my $key (keys(%env)) {
                   4390:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4391:             my $cmd=$1;
                   4392:             my $thiskey=$2;
1.576     raeburn  4393:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4394:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4395:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4396:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4397:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4398:                     $altkey = $thiskey;
                   4399:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4400:                     if ($env{'form.rec_'.$thiskey}) {
                   4401:                         $recursive = 1;
                   4402:                     }
                   4403:                 }
                   4404:             }
1.560     damieng  4405:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4406:             if ($tuname) {
1.576     raeburn  4407:                 $tkey=$thiskey;
1.560     damieng  4408:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4409:                 if ($altkey) {
                   4410:                     $tkeynonrec = $tkey; 
                   4411:                     $tkeyrec = $altkey;
                   4412:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4413:                 }
1.560     damieng  4414:             }
                   4415:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4416:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4417:                 if ($cmd eq 'set') {
                   4418:                     $data=$env{$key};
                   4419:                     $valmatch = '';
                   4420:                     $valchk = $data;
                   4421:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4422:                     $text = &mt('Saved modified parameter for');
                   4423:                     if ($typeof eq 'string_questiontype') {
                   4424:                         $name = 'type';
1.588     raeburn  4425:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4426:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4427:                         my $stringmatch = &standard_string_matches($typeof);
                   4428:                         if (ref($stringmatch) eq 'ARRAY') {
                   4429:                             foreach my $item (@{$stringmatch}) {
                   4430:                                 if (ref($item) eq 'ARRAY') {
                   4431:                                     my ($regexpname,$pattern) = @{$item};
                   4432:                                     if ($pattern ne '') {
                   4433:                                         if ($data =~ /$pattern/) {
                   4434:                                             $valmatch = $regexpname;
                   4435:                                             $valchk = '';
                   4436:                                             last;
                   4437:                                         }
1.560     damieng  4438:                                     }
1.549     raeburn  4439:                                 }
                   4440:                             }
                   4441:                         }
1.563     damieng  4442:                     } elsif ($typeof eq 'string_discussvote') {
                   4443:                         $name = 'discussvote';
                   4444:                     } elsif ($typeof eq 'string_examcode') {
                   4445:                         $name = 'examcode';
                   4446:                         if (&Apache::lonnet::validCODE($data)) {
                   4447:                             $valchk = 'valid';
                   4448:                         }
                   4449:                     } elsif ($typeof eq 'string_yesno') {
                   4450:                         if ($thiskey =~ /\.retrypartial$/) {
                   4451:                             $name = 'retrypartial';
                   4452:                         }
1.549     raeburn  4453:                     }
1.563     damieng  4454:                 } elsif ($cmd eq 'datepointer') {
                   4455:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4456:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4457:                     $text = &mt('Saved modified date for');
                   4458:                     if ($typeof eq 'date_start') {
                   4459:                         if ($thiskey =~ /\.printstartdate$/) {
                   4460:                             $name = 'printstartdate';
                   4461:                             if (($data) && ($data > $now)) {
                   4462:                                 $valchk = 'future';
                   4463:                             }
1.560     damieng  4464:                         }
1.563     damieng  4465:                     } elsif ($typeof eq 'date_end') {
                   4466:                         if ($thiskey =~ /\.printenddate$/) {
                   4467:                             $name = 'printenddate';
                   4468:                             if (($data) && ($data < $now)) {
                   4469:                                 $valchk = 'past';
                   4470:                             }
1.560     damieng  4471:                         }
1.504     raeburn  4472:                     }
1.563     damieng  4473:                 } elsif ($cmd eq 'dateinterval') {
                   4474:                     $data=&get_date_interval_from_form($thiskey);
                   4475:                     if ($thiskey =~ /\.interval$/) {
                   4476:                         $name = 'interval';
                   4477:                         my $intervaltype = &get_intervaltype($name);
                   4478:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4479:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4480:                             foreach my $item (@{$intervalmatch}) {
                   4481:                                 if (ref($item) eq 'ARRAY') {
                   4482:                                     my ($regexpname,$pattern) = @{$item};
                   4483:                                     if ($pattern ne '') {
                   4484:                                         if ($data =~ /$pattern/) {
                   4485:                                             $valmatch = $regexpname;
                   4486:                                             $valchk = '';
                   4487:                                             last;
                   4488:                                         }
1.560     damieng  4489:                                     }
1.554     raeburn  4490:                                 }
                   4491:                             }
                   4492:                         }
                   4493:                     }
1.563     damieng  4494:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4495:                     $text = &mt('Saved modified date for');
1.554     raeburn  4496:                 }
1.576     raeburn  4497:                 if ($recursive) {
1.563     damieng  4498:                     $namematch = 'maplevelrecurse';
1.560     damieng  4499:                 }
1.563     damieng  4500:                 if (($name ne '') || ($namematch ne '')) {
                   4501:                     my ($needsrelease,$needsnewer);
                   4502:                     if ($name ne '') {
                   4503:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4504:                         if ($needsrelease) {
                   4505:                             unless ($got_chostname) {
1.563     damieng  4506:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4507:                                 $got_chostname = 1;
                   4508:                             }
1.563     damieng  4509:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4510:                                                                 $needsrelease,
                   4511:                                                                 $cmajor,$cminor);
                   4512:                         }
                   4513:                     }
                   4514:                     if ($namematch ne '') {
                   4515:                         if ($needsnewer) {
                   4516:                             undef($namematch);
1.560     damieng  4517:                         } else {
1.563     damieng  4518:                             my $currneeded;
                   4519:                             if ($needsrelease) {
                   4520:                                 $currneeded = $needsrelease;
                   4521:                             }
                   4522:                             $needsrelease =
                   4523:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4524:                             if (($needsrelease) &&
                   4525:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4526:                                 unless ($got_chostname) {
                   4527:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4528:                                     $got_chostname = 1;
                   4529:                                 }
                   4530:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4531:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4532:                             } else {
                   4533:                                 undef($namematch);
                   4534:                             }
1.560     damieng  4535:                         }
1.557     raeburn  4536:                     }
1.563     damieng  4537:                     if ($needsnewer) {
                   4538:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4539:                                                             $chostname,$cmajor,
                   4540:                                                             $cminor,$needsrelease));
                   4541:                         next;
                   4542:                     }
1.504     raeburn  4543:                 }
1.576     raeburn  4544:                 my ($reconlychg,$haschange,$storekey);
                   4545:                 if ($tuname) {
                   4546:                     my $ustorekey;
                   4547:                     if ($altkey) {
                   4548:                         if ($recursive) {
                   4549:                             if (exists($$olddata{$thiskey})) {
                   4550:                                 if ($$olddata{$thiskey} eq $data) {
                   4551:                                     $reconlychg = 1;
                   4552:                                 }
                   4553:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4554:                             }
                   4555:                             if (exists($$olddata{$altkey})) {
                   4556:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4557:                                     $haschange = 1;
                   4558:                                 }
                   4559:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4560:                                 $haschange = 1;
                   4561:                             }
                   4562:                             $ustorekey = $tkeyrec;
                   4563:                         } else {
                   4564:                             if (exists($$olddata{$altkey})) {
                   4565:                                 if ($$olddata{$altkey} eq $data) {
                   4566:                                     $reconlychg = 1;
                   4567:                                 }
                   4568:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4569:                             }
                   4570:                             if (exists($$olddata{$thiskey})) {
                   4571:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4572:                                     $haschange = 1;
                   4573:                                 }
                   4574:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4575:                                 $haschange = 1;
                   4576:                             }
                   4577:                             $ustorekey = $tkeynonrec;
                   4578:                         }
                   4579:                     } else {
                   4580:                         if (exists($$olddata{$tkey})) {
                   4581:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4582:                                 $haschange = 1;
                   4583:                             }
                   4584:                             $ustorekey = $tkey;
                   4585:                         }
                   4586:                     }
                   4587:                     if ($haschange || $reconlychg)  {
                   4588:                         unless ($env{'form.del_'.$thiskey}) {
                   4589:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4590:                                                                      $ustorekey.'.type' => $typeof},
                   4591:                                                                      $tudom,$tuname) eq 'ok') {
                   4592:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4593:                                 $r->print('<br />'.$text.' '.
                   4594:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4595:                             } else {
                   4596:                                 $r->print('<div class="LC_error">'.
                   4597:                                           &mt('Error saving parameters').'</div>');
                   4598:                             }
                   4599:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4600:                         }
                   4601:                     }
                   4602:                 } else {
                   4603:                     if ($altkey) {
                   4604:                         if ($recursive) {
                   4605:                             if (exists($$olddata{$thiskey})) {
                   4606:                                 if ($$olddata{$thiskey} eq $data) {
                   4607:                                     $reconlychg = 1;
                   4608:                                 }
                   4609:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4610:                             }
                   4611:                             if (exists($$olddata{$altkey})) {
                   4612:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4613:                                     $haschange = 1;
                   4614:                                 }
                   4615:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4616:                                 $haschange = 1;
                   4617:                             }
                   4618:                             $storekey = $altkey;
1.563     damieng  4619:                         } else {
1.576     raeburn  4620:                             if (exists($$olddata{$altkey})) {
                   4621:                                 if ($$olddata{$altkey} eq $data) {
                   4622:                                     $reconlychg = 1;
                   4623:                                 }
                   4624:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4625:                             } 
                   4626:                             if (exists($$olddata{$thiskey})) {
                   4627:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4628:                                     $haschange = 1;
                   4629:                                 }
                   4630:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4631:                                 $haschange = 1;
                   4632:                             }
                   4633:                             $storekey = $thiskey;
1.563     damieng  4634:                         }
1.560     damieng  4635:                     } else {
1.576     raeburn  4636:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4637:                             $haschange = 1;
                   4638:                             $storekey = $thiskey;
                   4639:                         }
                   4640:                     }
                   4641:                 }
                   4642:                 if ($reconlychg || $haschange) {
                   4643:                     unless ($env{'form.del_'.$thiskey}) {
                   4644:                         $newdata{$storekey}=$data;
                   4645:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4646:                     }
                   4647:                 }
                   4648:             } elsif ($cmd eq 'del') {
                   4649:                 if ($tuname) {
1.576     raeburn  4650:                     my $error;
                   4651:                     if ($altkey) {  
                   4652:                         if (exists($$olddata{$altkey})) {
                   4653:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4654:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4655:                                 if ($recursive) {
                   4656:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4657:                                 }
                   4658:                             } elsif ($recursive) {
                   4659:                                 $error = 1;
                   4660:                             }
                   4661:                         }
                   4662:                         if (exists($$olddata{$thiskey})) {
                   4663:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4664:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4665:                                 unless ($recursive) {
                   4666:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4667:                                 }
                   4668:                             } elsif (!$recursive) {
                   4669:                                 $error = 1;
                   4670:                             }
                   4671:                         }
1.560     damieng  4672:                     } else {
1.576     raeburn  4673:                         if (exists($$olddata{$thiskey})) {
                   4674:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4675:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4676:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4677:                             } else {
                   4678:                                 $error = 1;
                   4679:                             }
                   4680:                         }
                   4681:                     }
                   4682:                     if ($error) { 
1.560     damieng  4683:                         $r->print('<div class="LC_error">'.
                   4684:                             &mt('Error deleting parameters').'</div>');
                   4685:                     }
                   4686:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4687:                 } else {
1.576     raeburn  4688:                     if ($altkey) {
                   4689:                         if (exists($$olddata{$altkey})) {
                   4690:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4691:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4692:                             }
                   4693:                         }
                   4694:                         if (exists($$olddata{$thiskey})) {
                   4695:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4696:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4697:                             }
                   4698:                         }
                   4699:                     } elsif (exists($$olddata{$thiskey})) {
                   4700:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4701:                     }
1.560     damieng  4702:                 }
1.473     amueller 4703:             }
                   4704:         }
                   4705:     }
1.207     www      4706: # Store all course level
1.144     www      4707:     my $delentries=$#deldata+1;
1.576     raeburn  4708:     my @alldels;
                   4709:     if (@delrec) {
                   4710:         push(@alldels,@delrec);
                   4711:     }
                   4712:     if (@delnonrec) {
                   4713:         push(@alldels,@delnonrec);
                   4714:     }
                   4715:     if (@deldata) {
                   4716:         push(@alldels,@deldata);
                   4717:     }
1.548     raeburn  4718:     my @newdatakeys=keys(%newdata);
1.144     www      4719:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4720:     my ($delresult,$devalidate);
                   4721:     if (@alldels) {
                   4722:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4723:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4724:             &log_parmset(\%loghash,1);
1.576     raeburn  4725:             if ($delentries) {
                   4726:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4727:             }
                   4728:         } elsif ($delentries) {
1.560     damieng  4729:             $r->print('<div class="LC_error">'.
                   4730:                 &mt('Error deleting parameters').'</div>');
                   4731:         }
1.576     raeburn  4732:         $devalidate = 1; 
1.144     www      4733:     }
                   4734:     if ($putentries) {
1.560     damieng  4735:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4736:                     &log_parmset(\%newdata,0);
                   4737:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4738:         } else {
                   4739:             $r->print('<div class="LC_error">'.
                   4740:                 &mt('Error saving parameters').'</div>');
                   4741:         }
1.576     raeburn  4742:         $devalidate = 1; 
                   4743:     }
                   4744:     if ($devalidate) {
1.560     damieng  4745:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4746:     }
1.208     www      4747: }
1.207     www      4748: 
1.563     damieng  4749: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4750: #
                   4751: # @param {string} $key - the key
                   4752: # @returns {Array}
1.208     www      4753: sub extractuser {
                   4754:     my $key=shift;
1.350     albertel 4755:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4756: }
1.206     www      4757: 
1.563     damieng  4758: # Parses a parameter key and returns the components.
                   4759: #
                   4760: # @param {string} $key - 
                   4761: # @param {hash reference} $listdata - 
                   4762: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4763: sub parse_listdata_key {
                   4764:     my ($key,$listdata) = @_;
                   4765:     # split into student/section affected, and
                   4766:     # the realm (folder/resource part and parameter
1.446     bisitz   4767:     my ($student,$realm) =
1.473     amueller 4768:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4769:     # if course wide student would be undefined
                   4770:     if (!defined($student)) {
1.560     damieng  4771:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4772:     }
                   4773:     # strip off the .type if it's not the Question type parameter
                   4774:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4775:         $realm=~s/\.type//;
1.381     albertel 4776:     }
                   4777:     # split into resource+part and parameter name
1.388     albertel 4778:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4779:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4780:     return ($student,$res,$part,$parm);
                   4781: }
                   4782: 
1.563     damieng  4783: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4784: #
                   4785: # @param {Apache2::RequestRec} $r - the Apache request
                   4786: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4787: # @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
                   4788: # @param {string} $sortorder - realmstudent|studentrealm
                   4789: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4790: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4791: # @param {boolean} $readonly - true if editing not allowed
1.608     raeburn  4792: # @param {string} $parmlev - full|map
                   4793: # @param {hash reference} $hash_for_realm - keys: realm, values: numeric order  
                   4794: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  4795: # @returns{integer} - number of $listdata parameters processed
1.208     www      4796: sub listdata {
1.608     raeburn  4797:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly,$parmlev,$hash_for_realm,$pschp)=@_;
1.552     raeburn  4798:     
1.207     www      4799: # Start list output
1.206     www      4800: 
1.122     www      4801:     my $oldsection='';
                   4802:     my $oldrealm='';
                   4803:     my $oldpart='';
1.123     www      4804:     my $pointer=0;
1.124     www      4805:     $tableopen=0;
1.145     www      4806:     my $foundkeys=0;
1.248     albertel 4807:     my %keyorder=&standardkeyorder();
1.594     raeburn  4808:     my $readonlyall = $readonly;
1.381     albertel 4809: 
1.552     raeburn  4810:     my ($secidx,%grouphash);
                   4811:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4812:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4813:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4814:             %grouphash = &Apache::longroup::coursegroups();
                   4815:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4816:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4817:         }
1.552     raeburn  4818:     }
                   4819: 
1.576     raeburn  4820:     foreach my $key (sort {
1.560     damieng  4821:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4822:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.608     raeburn  4823:         my ($aid,$bid);
                   4824:         if ($caller eq 'newoverview') {
                   4825:             if (ref($hash_for_realm) eq 'HASH') {
                   4826:                 if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4827:                     my ($aurl) = ($ares =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4828:                     my ($burl) = ($bres =~ /^(.+\.(?:sequence|page))___\(all\)$/);
                   4829:                     $aid = $hash_for_realm->{$aurl};
                   4830:                     $bid = $hash_for_realm->{$burl};
                   4831:                 } elsif ($parmlev eq 'full') {
                   4832:                     $aid = $hash_for_realm->{$ares};
                   4833:                     $bid = $hash_for_realm->{$bres};
                   4834:                 }
                   4835:             }
                   4836:         }
1.381     albertel 4837: 
1.560     damieng  4838:         # get the numerical order for the param
                   4839:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4840:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4841: 
1.560     damieng  4842:         my $result=0;
1.381     albertel 4843: 
1.560     damieng  4844:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4845:             if ($ares     ne $bres    ) {
1.608     raeburn  4846:                 if ($caller eq 'newoverview') {
                   4847:                     if (ref($hash_for_realm) eq 'HASH') {
                   4848:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4849:                             $result = ($aid <=> $bid);
                   4850:                         } elsif ($parmlev eq 'full') {
                   4851:                             $result = ($aid <=> $bid);
                   4852:                         } else {
                   4853:                             $result = ($ares cmp $bres);
                   4854:                         }
                   4855:                     } else {
                   4856:                         $result = ($ares cmp $bres);
                   4857:                     }
                   4858:                 } else {
                   4859:                     $result = ($ares cmp $bres);
                   4860:                 }
1.446     bisitz   4861:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4862:                 $result = ($astudent cmp $bstudent);
                   4863:             } elsif ($apart    ne $bpart   ) {
                   4864:                 $result = ($apart    cmp $bpart);
                   4865:             }
                   4866:         } else {
                   4867:             if      ($astudent ne $bstudent) {
                   4868:                 $result = ($astudent cmp $bstudent);
                   4869:             } elsif ($ares     ne $bres    ) {
1.608     raeburn  4870:                 if ($caller eq 'newoverview') {
                   4871:                     if (ref($hash_for_realm) eq 'HASH') {
                   4872:                         if (($parmlev eq 'map') && ($pschp eq 'all')) {
                   4873:                             $result = ($aid <=> $bid);
                   4874:                         } elsif ($parmlev eq 'full') {
                   4875:                             $result = ($aid <=> $bid);
                   4876:                         } else {
                   4877:                             $result = ($ares cmp $bres);
                   4878:                         }
                   4879:                     } else {
                   4880:                         $result = ($ares cmp $bres);
                   4881:                     }
                   4882:                 } else {
                   4883:                     $result = ($ares cmp $bres);
                   4884:                 }
1.560     damieng  4885:             } elsif ($apart    ne $bpart   ) {
                   4886:                 $result = ($apart    cmp $bpart);
                   4887:             }
1.473     amueller 4888:         }
1.446     bisitz   4889: 
1.560     damieng  4890:         if (!$result) {
1.381     albertel 4891:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4892:                 $result = ($aparm <=> $bparm);
1.381     albertel 4893:             } elsif (defined($aparm)) {
1.560     damieng  4894:                 $result = -1;
1.381     albertel 4895:             } elsif (defined($bparm)) {
1.560     damieng  4896:                 $result = 1;
                   4897:             }
1.473     amueller 4898:         }
1.381     albertel 4899: 
1.560     damieng  4900:         $result;
                   4901:         
1.576     raeburn  4902:     } keys(%{$listdata})) { # foreach my $key
                   4903:         my $thiskey = $key;
1.560     damieng  4904:         if ($$listdata{$thiskey.'.type'}) {
                   4905:             my $thistype=$$listdata{$thiskey.'.type'};
                   4906:             if ($$resourcedata{$thiskey.'.type'}) {
                   4907:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4908:             }
                   4909:             my ($middle,$part,$name)=
1.572     damieng  4910:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4911:             my $section=&mt('All Students');
1.594     raeburn  4912:             $readonly = $readonlyall;
1.599     raeburn  4913:             my $userscope;
1.576     raeburn  4914:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4915:             if ($middle=~/^\[(.*)\]/) {
                   4916:                 my $issection=$1;
                   4917:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4918:                     my ($stuname,$studom) = ($1,$2);
                   4919:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4920:                         if (ref($classlist) eq 'HASH') {
                   4921:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4922:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4923:                             }
                   4924:                         }
                   4925:                     }
                   4926:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4927:                     $userscope = 1;
1.560     damieng  4928:                 } else {
                   4929:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4930:                         if (exists($grouphash{$issection})) {
                   4931:                             $section=&mt('Group').': '.$issection;
                   4932:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4933:                             $section = &mt('Section').': '.$issection;
                   4934:                         } else {
                   4935:                             next; 
1.552     raeburn  4936:                         }
1.560     damieng  4937:                     } else {
                   4938:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4939:                     }
                   4940:                 }
1.560     damieng  4941:                 $middle=~s/^\[(.*)\]//;
                   4942:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4943:                 $readonly = 1;
                   4944:             }
                   4945:             $middle=~s/\.+$//;
                   4946:             $middle=~s/^\.+//;
                   4947:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4948:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4949:             if ($caller eq 'overview') {
                   4950:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4951:                     $mapurl = $1;
                   4952:                     $maplevel = $2;
                   4953:                     $is_map = 1;
                   4954:                 }
                   4955:             } elsif ($caller eq 'newoverview') {
                   4956:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4957:                     $mapurl = $1;
                   4958:                     $maplevel = $2;
                   4959:                     $is_map = 1;
                   4960:                 }
                   4961:             }
                   4962:             if ($is_map) {
1.560     damieng  4963:                 my $leveltitle = &mt('Folder/Map');
1.615     raeburn  4964:                 my $title = &Apache::lonnet::gettitle($mapurl);
1.608     raeburn  4965:                 if (ref($hash_for_realm) eq 'HASH') {
                   4966:                     if ($hash_for_realm->{$mapurl} eq '1') {
                   4967:                         $title = &mt('Main Content');
                   4968:                     }
                   4969:                 }
1.576     raeburn  4970:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4971:                     if ($caller eq 'newoverview') {
                   4972:                         my $altkey = $thiskey;
                   4973:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4974:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4975:                             $is_recursive = 1;
                   4976:                             if ($$resourcedata{$altkey.'.type'}) {
                   4977:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4978:                             }
                   4979:                             $showval = $$resourcedata{$altkey};
                   4980:                         }
                   4981:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4982:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4983:                         $is_recursive = 1;
                   4984:                     }
1.560     damieng  4985:                 }
1.608     raeburn  4986:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.$title.' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
1.560     damieng  4987:             } elsif ($middle) {
                   4988:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
1.609     raeburn  4989:                 next if (($url =~ /\.(page|sequence)$/) && ($parmlev eq 'full') && ($caller eq 'newoverview'));
1.560     damieng  4990:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4991:                     ': '.&Apache::lonnet::gettitle($middle).
                   4992:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4993:                     $id.')</span></span>';
                   4994:             }
                   4995:             if ($sortorder eq 'realmstudent') {
                   4996:                 if ($realm ne $oldrealm) {
                   4997:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4998:                     $oldrealm=$realm;
                   4999:                     $oldsection='';
                   5000:                 }
                   5001:                 if ($section ne $oldsection) {
                   5002:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   5003:                     $oldsection=$section;
                   5004:                     $oldpart='';
                   5005:                 }
1.552     raeburn  5006:             } else {
1.560     damieng  5007:                 if ($section ne $oldsection) {
                   5008:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   5009:                     $oldsection=$section;
                   5010:                     $oldrealm='';
                   5011:                 }
                   5012:                 if ($realm ne $oldrealm) {
                   5013:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   5014:                     $oldrealm=$realm;
                   5015:                     $oldpart='';
1.552     raeburn  5016:                 }
                   5017:             }
1.560     damieng  5018:             if ($part ne $oldpart) {
                   5019:                 $r->print(&tableend().
                   5020:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   5021:                 $oldpart=$part;
1.556     raeburn  5022:             }
1.560     damieng  5023:     #
                   5024:     # Ready to print
                   5025:     #
1.470     raeburn  5026:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  5027:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  5028:                 &Apache::loncommon::start_data_table_row().
                   5029:                 '<td><b>'.&mt($parmitem).
                   5030:                 '</b></td>');
                   5031:             unless ($readonly) {
1.599     raeburn  5032:                 my $disabled;
                   5033:                 if (($name eq 'availablestudent') &&
                   5034:                     (($showval eq '') || ($userscope))) {
                   5035:                     $disabled = ' disabled="disabled"';
                   5036:                 }
1.560     damieng  5037:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  5038:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  5039:             }
                   5040:             $r->print('<td>');
                   5041:             $foundkeys++;
                   5042:             if (&isdateparm($thistype)) {
                   5043:                 my $jskey='key_'.$pointer;
                   5044:                 my $state;
                   5045:                 $pointer++;
                   5046:                 if ($readonly) {
                   5047:                     $state = 'disabled';
                   5048:                 }
                   5049:                 $r->print(
                   5050:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   5051:                                                         $jskey,
1.576     raeburn  5052:                                                         $showval,
1.560     damieng  5053:                                                         '',1,$state));
                   5054:                 unless  ($readonly) {
                   5055:                     $r->print(
                   5056:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  5057:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  5058:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  5059:     &date_sanity_info($showval)
1.560     damieng  5060:                     );
                   5061:                 }
                   5062:             } elsif ($thistype eq 'date_interval') {
                   5063:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  5064:                           $showval,$readonly));
1.560     damieng  5065:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  5066:                 if ($name eq 'availablestudent') {
                   5067:                     $readonly = 1;
                   5068:                 }
1.560     damieng  5069:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  5070:                           $showval,$name,$readonly));
1.560     damieng  5071:             } else {
1.576     raeburn  5072:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  5073:             }
1.560     damieng  5074:             unless ($readonly) {
                   5075:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   5076:                         $thistype.'" />');
1.552     raeburn  5077:             }
1.576     raeburn  5078:             $r->print('</td>');
                   5079:             if ($is_map) {
                   5080:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   5081:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   5082:                 } else {
                   5083:                     my ($disabled,$recon,$recoff);
                   5084:                     if ($readonly) {
                   5085:                         $disabled = ' disabled="disabled"';
                   5086:                     }
                   5087:                     if ($is_recursive) {
                   5088:                         $recon = ' checked="checked"';
                   5089:                     } else {
                   5090:                         $recoff = ' checked="checked"';
                   5091:                     }
                   5092:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   5093:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   5094:                 }
                   5095:             }
                   5096:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 5097:         }
1.121     www      5098:     }
1.208     www      5099:     return $foundkeys;
                   5100: }
                   5101: 
1.563     damieng  5102: # Returns a string representing the interval, directly using form data matching the given key.
                   5103: # The returned string may also include information related to proctored exams.
                   5104: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   5105: #
                   5106: # @param {string} $key - suffix for form fields related to the interval
                   5107: # @returns {string}
1.385     albertel 5108: sub get_date_interval_from_form {
                   5109:     my ($key) = @_;
                   5110:     my $seconds = 0;
1.611     raeburn  5111:     my $numnotnull = 0;
1.385     albertel 5112:     foreach my $which (['days', 86400],
1.473     amueller 5113:                ['hours', 3600],
                   5114:                ['minutes', 60],
                   5115:                ['seconds',  1]) {
1.560     damieng  5116:         my ($name, $factor) = @{ $which };
                   5117:         if (defined($env{'form.'.$name.'_'.$key})) {
1.611     raeburn  5118:             unless ($env{'form.'.$name.'_'.$key} eq '') {
                   5119:                 $numnotnull ++;
                   5120:                 $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   5121:             }
1.560     damieng  5122:         }
1.473     amueller 5123:     }
1.560     damieng  5124:     if (($key =~ /\.interval$/) &&
                   5125:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  5126:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   5127:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   5128:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   5129:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   5130:                 $seconds .= '_proctor';
                   5131:             }
                   5132:         } else {
                   5133:             $seconds .= $env{'form.done_'.$key}; 
                   5134:         }
                   5135:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  5136:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  5137:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   5138:         }
1.554     raeburn  5139:     }
1.611     raeburn  5140:     return if (!$numnotnull);
1.385     albertel 5141:     return $seconds;
                   5142: }
                   5143: 
                   5144: 
1.563     damieng  5145: # Returns HTML to enter a text value for a parameter.
                   5146: #
                   5147: # @param {string} $thiskey - parameter key
                   5148: # @param {string} $showval - the current value
                   5149: # @param {boolean} $readonly - true if the field should not be made editable
                   5150: # @returns {string}
1.383     albertel 5151: sub default_selector {
1.552     raeburn  5152:     my ($thiskey, $showval, $readonly) = @_;
                   5153:     my $disabled;
                   5154:     if ($readonly) {
                   5155:         $disabled = ' disabled="disabled"';
                   5156:     }
                   5157:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 5158: }
                   5159: 
1.563     damieng  5160: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5161: #
                   5162: # @param {string} $thiskey - parameter key
                   5163: # @param {string} $showval - the current value
                   5164: # @param {boolean} $readonly - true if the fields should not be made editable
                   5165: # @returns {string}
1.549     raeburn  5166: sub string_ip_selector {
1.552     raeburn  5167:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5168:     my %access = (
                   5169:                    allow => [],
                   5170:                    deny  => [],
                   5171:                  );
                   5172:     if ($showval ne '') {
                   5173:         my @current;
                   5174:         if ($showval =~ /,/) {
                   5175:             @current = split(/,/,$showval);
                   5176:         } else {
                   5177:             @current = ($showval);
                   5178:         }
                   5179:         foreach my $item (@current) {
                   5180:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5181:                 push(@{$access{'deny'}},$1);
                   5182:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5183:                 push(@{$access{'allow'}},$item);
                   5184:             }
                   5185:         }
                   5186:     }
                   5187:     if (!@{$access{'allow'}}) {
                   5188:         @{$access{'allow'}} = ('');
                   5189:     }
                   5190:     if (!@{$access{'deny'}}) {
                   5191:         @{$access{'deny'}} = ('');
                   5192:     }
1.552     raeburn  5193:     my ($disabled,$addmore);
1.567     raeburn  5194:     if ($readonly) {
1.552     raeburn  5195:         $disabled=' disabled="disabled"';
                   5196:     } else {
                   5197:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5198:     }
1.549     raeburn  5199:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5200: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5201:     foreach my $acctype ('allow','deny') {
                   5202:         $output .= '
                   5203: <td valign="top">
                   5204: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5205:   <div class="LC_string_ipacc_inner">'."\n";
                   5206:         my $num = 0;
                   5207:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5208:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5209:             if ($num > 0) {
                   5210:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5211:             }
                   5212:             $output .= '</div>'."\n";
                   5213:             $num ++;
                   5214:         }
                   5215:         $output .= '
1.552     raeburn  5216:   </div>'.$addmore.'
1.549     raeburn  5217: </div>
                   5218: </td>';
                   5219:    }
                   5220:    $output .= '
                   5221: </tr>
                   5222: </table>'."\n";
                   5223:     return $output;
                   5224: }
                   5225: 
1.588     raeburn  5226: sub string_deeplink_selector {
                   5227:     my ($thiskey, $showval, $readonly) = @_;
1.616   ! raeburn  5228:     my (@tables,%values,@current,%titles,%options,%optiontext,%defaults,
        !          5229:         %selectnull,%domlti,%crslti,@possmenus,%components);
        !          5230:     @tables = ('upper','lower');
        !          5231:     %components = (
        !          5232:                     upper => ['state','others','listing','scope'],
        !          5233:                     lower => ['protect','menus','target','exit'],
        !          5234:                   );   
1.588     raeburn  5235:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5236:                   state   => 'Access status',
                   5237:                   others  => 'Hide other resources',
1.588     raeburn  5238:                   listing => 'In Contents and/or Gradebook',
                   5239:                   scope   => 'Access scope for link',
1.601     raeburn  5240:                   protect => 'Link protection',
1.597     raeburn  5241:                   menus   => 'Menu Items Displayed',
1.613     raeburn  5242:                   target  => 'Embedded?',
1.616   ! raeburn  5243:                   exit    => 'Exit Tool Button?',
1.588     raeburn  5244:               );
                   5245:     %options = (
1.601     raeburn  5246:                    state   => ['only','off','both'],
                   5247:                    others  => ['hide','unhide'],
1.588     raeburn  5248:                    listing => ['full','absent','grades','details','datestatus'],
                   5249:                    scope   => ['res','map','rec'],
1.601     raeburn  5250:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5251:                    menus   => ['std','colls'],
1.613     raeburn  5252:                    target  => ['_self','_top'],
1.616   ! raeburn  5253:                    exit    => ['no','yes','url'],
1.588     raeburn  5254:                );
                   5255:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5256:                     only       => 'deep only',
                   5257:                     off        => 'deeplink off',
                   5258:                     both       => 'regular + deep',
                   5259:                     hide       => 'Hidden',
                   5260:                     unhide     => 'Unhidden',
1.588     raeburn  5261:                     full       => 'Listed (linked) in both',
                   5262:                     absent     => 'Not listed',
                   5263:                     grades     => 'Listed in grades only',
                   5264:                     details    => 'Listed (unlinked) in both',
                   5265:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5266:                     res        => 'resource only',
                   5267:                     map        => 'enclosing map/folder',
                   5268:                     rec        => 'recursive map/folder',
1.601     raeburn  5269:                     none       => 'not in use',
                   5270:                     key        => 'key access',
                   5271:                     ltic       => 'LTI access (course)',
                   5272:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5273:                     std        => 'Standard (all menus)',
                   5274:                     colls      => 'Numbered collection',
1.614     raeburn  5275:                     _self      => 'Embedded',
1.613     raeburn  5276:                     _top       => 'Not embedded',
1.616   ! raeburn  5277:                     no         => 'Not in use',
        !          5278:                     yes        => 'In use, no URL redirect',
        !          5279:                     url        => 'In use, redirect to URL',  
1.597     raeburn  5280:                   );
                   5281:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5282:                     ltic => 'Select Launcher',
                   5283:                     ltid => 'Select Launcher', 
1.597     raeburn  5284:                     colls => 'Select',
1.588     raeburn  5285:                   );
                   5286:     if ($showval =~ /,/) {
1.597     raeburn  5287:         %values=();
1.588     raeburn  5288:         @current = split(/,/,$showval);
1.601     raeburn  5289:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5290:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5291:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5292:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5293:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5294:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.613     raeburn  5295:         ($values{'target'}) = ($current[6] =~ /^(_self|_top)$/);
1.616   ! raeburn  5296:         ($values{'exit'}) = ($current[7] =~ /^((?:(?:yes|url)(?:|\:[^:;"',]+))|no)$/);
1.588     raeburn  5297:     } else {
1.601     raeburn  5298:         $defaults{'state'} = 'off',
                   5299:         $defaults{'others'} = 'unhide',
1.588     raeburn  5300:         $defaults{'listing'} = 'full';
                   5301:         $defaults{'scope'} = 'res';
1.601     raeburn  5302:         $defaults{'protect'} = 'none';
1.597     raeburn  5303:         $defaults{'menus'} = '0';
1.613     raeburn  5304:         $defaults{'target'} = '_top';
1.616   ! raeburn  5305:         $defaults{'exit'} = 'yes';
1.588     raeburn  5306:     }
                   5307:     my $disabled;
                   5308:     if ($readonly) {
                   5309:         $disabled=' disabled="disabled"';
                   5310:     }
1.601     raeburn  5311:     my %courselti =
                   5312:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5313:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5314:     foreach my $item (keys(%courselti)) {
                   5315:         if (ref($courselti{$item}) eq 'HASH') {
                   5316:             $crslti{$item} = $courselti{$item}{'name'};
                   5317:         }
                   5318:     }
                   5319:     my %lti =
1.588     raeburn  5320:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5321:                                         'linkprot');
1.588     raeburn  5322:     foreach my $item (keys(%lti)) {
1.604     raeburn  5323:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5324:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5325:         }
                   5326:     }
1.597     raeburn  5327:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5328:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5329:             my ($num,$value) = split(/\%/,$item);
                   5330:             if ($num =~ /^\d+$/) {
                   5331:                 push(@possmenus,$num);
                   5332:             }
                   5333:         }
                   5334:     }
                   5335: 
1.616   ! raeburn  5336:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />';
        !          5337:     foreach my $table ('upper','lower') {
        !          5338:         next unless (ref($components{$table}) eq 'ARRAY');
        !          5339:         $output .= '<table width="100%"><tr>';
        !          5340:         foreach my $item (@{$components{$table}}) {
        !          5341:             $output .= '<th>'.$titles{$item}.'</th>';
        !          5342:         }
        !          5343:         $output .= '</tr><tr>';
        !          5344:         foreach my $item (@{$components{$table}}) {
        !          5345:             $output .= '<td>';
        !          5346:             if (($item eq 'protect') || ($item eq 'menus') || ($item eq 'exit')) {
        !          5347:                 my $selected = $values{$item};
        !          5348:                 foreach my $option (@{$options{$item}}) {
        !          5349:                     if ($item eq 'protect') { 
        !          5350:                         if ($option eq 'ltid') {
        !          5351:                             next unless (keys(%domlti));
        !          5352:                         } elsif ($option eq 'ltic') {
        !          5353:                             next unless (keys(%crslti));
        !          5354:                         }
        !          5355:                     } elsif (($item eq 'menus') && ($option eq 'colls')) {
        !          5356:                         next unless (@possmenus);
        !          5357:                     }
        !          5358:                     my $checked;
        !          5359:                     if ($item eq 'menus') {
        !          5360:                         if (($selected =~ /^\d+$/) && (@possmenus) &&
        !          5361:                             (grep(/^\Q$selected\E$/,@possmenus))) {
        !          5362:                             if ($option eq 'colls') {
        !          5363:                                 $checked = ' checked="checked"';
        !          5364:                             }
        !          5365:                         } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
1.597     raeburn  5366:                             $checked = ' checked="checked"';
                   5367:                         }
1.616   ! raeburn  5368:                     } elsif ($selected =~ /^\Q$option\E/) {
1.597     raeburn  5369:                         $checked = ' checked="checked"';
                   5370:                     }
1.616   ! raeburn  5371:                     my $onclick;
        !          5372:                     unless ($readonly) {
        !          5373:                         my $esc_key = &js_escape($thiskey);
        !          5374:                         $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
        !          5375:                     }
        !          5376:                     $output .= '<span class="LC_nobreak"><label>'.
        !          5377:                                '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
        !          5378:                                $optiontext{$option}.'</label>';
        !          5379:                     if (($item eq 'protect') && ($option eq 'key')) {
        !          5380:                         my $visibility="hidden";
        !          5381:                         my $currkey;
        !          5382:                         if ($checked) {
        !          5383:                             $visibility = "text";
        !          5384:                             $currkey = (split(/\:/,$values{$item}))[1];
        !          5385:                         }
        !          5386:                         $output .= '&nbsp;'.
        !          5387:                                    '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
        !          5388:                     } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
        !          5389:                         my $display="none";
        !          5390:                         my ($current,$blankcheck,@possibles);
        !          5391:                         if ($checked) {
        !          5392:                             $display = 'inline-block';
        !          5393:                             if (($option eq 'ltic') || ($option eq 'ltid'))  {
        !          5394:                                 $current = (split(/\:/,$selected))[1];
        !          5395:                             } else {
        !          5396:                                 $current = $selected;
        !          5397:                             }
1.597     raeburn  5398:                         } else {
1.616   ! raeburn  5399:                             $blankcheck = ' selected="selected"';
1.597     raeburn  5400:                         }
1.601     raeburn  5401:                         if ($option eq 'ltid') {
1.616   ! raeburn  5402:                             @possibles = keys(%domlti);
1.601     raeburn  5403:                         } elsif ($option eq 'ltic') {
1.616   ! raeburn  5404:                             @possibles = keys(%crslti); 
        !          5405:                         } else {
        !          5406:                             @possibles = @possmenus;
        !          5407:                         }
        !          5408:                         $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
        !          5409:                                    ' style="display: '.$display.'">&nbsp;<select name="'.
        !          5410:                                    'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
        !          5411:                         if (@possibles > 1) {
        !          5412:                             $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
        !          5413:                                        '</option>'."\n";
        !          5414:                         }
        !          5415:                         foreach my $poss (sort { $a <=> $b } @possibles) {
        !          5416:                             my $selected;
        !          5417:                             if (($poss == $current) || (scalar(@possibles) ==1)) {
        !          5418:                                 $selected = ' selected="selected"';
        !          5419:                             }
        !          5420:                             my $shown = $poss;
        !          5421:                             if ($option eq 'ltid') {
        !          5422:                                 $shown = $domlti{$poss};
        !          5423:                             } elsif ($option eq 'ltic') {
        !          5424:                                 $shown = $crslti{$poss};
        !          5425:                             }
        !          5426:                             $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
        !          5427:                         }
        !          5428:                         $output .= '</select></div>';
        !          5429:                     }
        !          5430:                     $output .= '</span> ';
        !          5431:                 }
        !          5432:                 if ($item eq 'exit') {
        !          5433:                     my $exitsty = 'none';
        !          5434:                     my $displayval;
        !          5435:                     if ($values{$item} =~ /^(yes|url)/) { 
        !          5436:                         $exitsty = 'inline-block';
        !          5437:                         my $currval = (split(/\:/,$values{$item}))[1];
        !          5438:                         if ($currval eq '') {
        !          5439:                             $displayval = 'Exit Tool';
        !          5440:                         } else {
        !          5441:                             $displayval = $currval;
1.597     raeburn  5442:                         }
1.588     raeburn  5443:                     }
1.616   ! raeburn  5444:                     $output .= '<div id="deeplinkdiv_'.$item.'_'.$thiskey.'"'.
        !          5445:                                ' style="display: '.$exitsty.'"><br />'.&mt('Button text').': '.
        !          5446:                                '<input type="text" name="deeplink_exittext_'.$thiskey.'"'.
        !          5447:                                ' id="deeplink_exittext_'.$thiskey.'" value="'.$displayval.'"'.
        !          5448:                                ' size="10"'.$disabled.' /></div>';
1.588     raeburn  5449:                 }
1.616   ! raeburn  5450:             } else {
        !          5451:                 my $selected = $values{$item};
        !          5452:                 my $defsel;
        !          5453:                 if ($selected eq '') {
        !          5454:                     $defsel = ' selected="selected"';
        !          5455:                 }
        !          5456:                 $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
        !          5457:                            '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
        !          5458:                 foreach my $option (@{$options{$item}}) {
        !          5459:                     $output .= '<option value="'.$option.'"';
        !          5460:                     if ($option eq $selected) {
        !          5461:                         $output .= ' selected="selected"';
        !          5462:                     }
        !          5463:                     $output .= '>'.$optiontext{$option}.'</option>';
1.588     raeburn  5464:                 }
1.616   ! raeburn  5465:                 $output .= '</select>';
1.588     raeburn  5466:             }
1.616   ! raeburn  5467:             $output .= '</td>';
        !          5468:         }
        !          5469:         $output .= '</tr></table>'."\n";
        !          5470:         if ($table eq 'upper') {
        !          5471:             $output .= '<br />';
1.588     raeburn  5472:         }
                   5473:     }
                   5474:     return $output;
                   5475: }
                   5476: 
1.560     damieng  5477: 
                   5478: { # block using some constants related to parameter types (overview mode)
                   5479: 
1.446     bisitz   5480: my %strings =
1.383     albertel 5481:     (
                   5482:      'string_yesno'
                   5483:              => [[ 'yes', 'Yes' ],
1.560     damieng  5484:                  [ 'no', 'No' ]],
1.383     albertel 5485:      'string_problemstatus'
                   5486:              => [[ 'yes', 'Yes' ],
1.473     amueller 5487:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5488:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5489:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5490:      'string_questiontype'
                   5491:              => [[ 'problem', 'Standard Problem'],
                   5492:                  [ 'survey', 'Survey'],
                   5493:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5494:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5495:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5496:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5497:                  [ 'practice', 'Practice'],
                   5498:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5499:      'string_lenient'
                   5500:              => [['yes', 'Yes' ],
                   5501:                  [ 'no', 'No' ],
1.549     raeburn  5502:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5503:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5504:      'string_discussvote'
                   5505:              => [['yes','Yes'],
                   5506:                  ['notended','Yes, unless discussion ended'],
                   5507:                  ['no','No']],
1.549     raeburn  5508:      'string_ip'
                   5509:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5510:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5511:      'string_deeplink'
1.616   ! raeburn  5512:              => [['on','Set choices for link protection, resource listing, access scope, shown menu items, embedding, and exit link']],
1.587     raeburn  5513:     );
                   5514:    
1.383     albertel 5515: 
1.549     raeburn  5516: my %stringmatches = (
                   5517:          'string_lenient'
                   5518:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5519:          'string_ip'
                   5520:               => [['_allowfrom_','[^\!]+'],
                   5521:                   ['_denyfrom_','\!']],
1.588     raeburn  5522:          'string_deeplink'
1.616   ! raeburn  5523:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)\,_(self|top),(yes|url|no)(|:[^:;\'",]+)$']],
1.549     raeburn  5524:     );
                   5525: 
                   5526: my %stringtypes = (
                   5527:                     type         => 'string_questiontype',
                   5528:                     lenient      => 'string_lenient',
                   5529:                     retrypartial => 'string_yesno',
                   5530:                     discussvote  => 'string_discussvote',
                   5531:                     examcode     => 'string_examcode',
                   5532:                     acc          => 'string_ip',
1.587     raeburn  5533:                     deeplink     => 'string_deeplink',
1.549     raeburn  5534:                   );
                   5535: 
1.563     damieng  5536: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5537: # Used by courseprefs.
                   5538: #
                   5539: # @param {string} $string_type - a parameter type for strings
                   5540: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5541: sub standard_string_options {
                   5542:     my ($string_type) = @_;
                   5543:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5544:         return $strings{$string_type};
                   5545:     }
                   5546:     return;
                   5547: }
1.383     albertel 5548: 
1.563     damieng  5549: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5550: #
                   5551: # @param {string} $string_type - a parameter type for strings
                   5552: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5553: sub standard_string_matches {
                   5554:     my ($string_type) = @_;
                   5555:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5556:         return $stringmatches{$string_type};
                   5557:     }
                   5558:     return;
                   5559: }
                   5560: 
1.563     damieng  5561: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5562: #
                   5563: # @param {string} $name - parameter name
                   5564: # @returns {string}
1.549     raeburn  5565: sub get_stringtype {
                   5566:     my ($name) = @_;
                   5567:     if (exists($stringtypes{$name})) {
                   5568:         return $stringtypes{$name};
                   5569:     }
                   5570:     return;
                   5571: }
                   5572: 
1.563     damieng  5573: # Returns HTML to edit a string parameter.
                   5574: #
                   5575: # @param {string} $thistype - parameter type
                   5576: # @param {string} $thiskey - parameter key
                   5577: # @param {string} $showval - parameter current value
                   5578: # @param {string} $name - parameter name
                   5579: # @param {boolean} $readonly - true if the values should not be made editable
                   5580: # @returns {string}
1.383     albertel 5581: sub string_selector {
1.552     raeburn  5582:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5583: 
1.383     albertel 5584:     if (!exists($strings{$thistype})) {
1.552     raeburn  5585:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5586:     }
                   5587: 
1.504     raeburn  5588:     my %skiptype;
1.514     raeburn  5589:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5590:             ($thistype eq 'string_lenient') ||
                   5591:             ($thistype eq 'string_discussvote') ||
                   5592:             ($thistype eq 'string_ip') ||
1.588     raeburn  5593:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5594:             ($name eq 'retrypartial')) {
1.504     raeburn  5595:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5596:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5597:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5598:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5599:             my $parmmatch;
                   5600:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5601:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5602:                     if (ref($item) eq 'ARRAY') {
                   5603:                         if ($parmval eq $item->[0]) {
                   5604:                             $parmmatch = $parmval;
                   5605:                             $parmval = '';
                   5606:                             last;
                   5607:                         }
                   5608:                     }
                   5609:                 }
                   5610:             }
                   5611:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5612:             if ($needsrelease) {
                   5613:                 unless ($got_chostname) {
1.514     raeburn  5614:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5615:                     $got_chostname = 1;
                   5616:                 }
1.557     raeburn  5617:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5618:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5619:                 if ($needsnewer) {
1.549     raeburn  5620:                     if ($parmmatch ne '') {
                   5621:                         $skiptype{$parmmatch} = 1;
                   5622:                     } elsif ($parmval ne '') {
                   5623:                         $skiptype{$parmval} = 1;
                   5624:                     }
1.504     raeburn  5625:                 }
                   5626:             }
                   5627:         }
                   5628:     }
1.549     raeburn  5629: 
                   5630:     if ($thistype eq 'string_ip') {
1.552     raeburn  5631:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5632:     } elsif ($thistype eq 'string_deeplink') {
                   5633:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5634:     }
1.504     raeburn  5635: 
1.552     raeburn  5636:     my ($result,$disabled);
                   5637: 
                   5638:     if ($readonly) {
                   5639:         $disabled = ' disabled="disabled"';
                   5640:     }
1.504     raeburn  5641:     my $numinrow = 3;
                   5642:     if ($thistype eq 'string_problemstatus') {
                   5643:         $numinrow = 2;
                   5644:     } elsif ($thistype eq 'string_questiontype') {
                   5645:         if (keys(%skiptype) > 0) {
                   5646:              $numinrow = 4;
                   5647:         }
                   5648:     }
                   5649:     my $rem;
                   5650:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5651:         my $i=0;
                   5652:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5653:             next unless (ref($possibilities) eq 'ARRAY');
                   5654:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5655:             next if ($skiptype{$name});
1.504     raeburn  5656:             $rem = $i%($numinrow);
                   5657:             if ($rem == 0) {
                   5658:                 if ($i > 0) {
                   5659:                     $result .= '</tr>';
                   5660:                 }
                   5661:                 $result .= '<tr>';
                   5662:             }
1.549     raeburn  5663:             my $colspan;
                   5664:             if ($i == @{ $strings{$thistype} }-1) {
                   5665:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5666:                 if ($rem) {
                   5667:                     my $colsleft = $numinrow - $rem;
                   5668:                     if ($colsleft) {
                   5669:                         $colspan = $colsleft+1;
                   5670:                         $colspan = ' colspan="'.$colspan.'"';
                   5671:                     }
                   5672:                 }
                   5673:             }
                   5674:             my ($add,$onchange,$css_class);
                   5675:             if ($thistype eq 'string_lenient') {
                   5676:                 if ($name eq 'weighted') {
                   5677:                     my $display;
                   5678:                     my %relatives = &Apache::lonlocal::texthash(
                   5679:                                         corrchkd     => 'Correct (checked)',
                   5680:                                         corrunchkd   => 'Correct (unchecked)',
                   5681:                                         incorrchkd   => 'Incorrect (checked)',
                   5682:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5683:                     );
                   5684:                     my %textval = (
                   5685:                                     corrchkd     => '1.0',
                   5686:                                     corrunchkd   => '1.0',
                   5687:                                     incorrchkd   => '0.0',
                   5688:                                     incorrunchkd => '0.0',
                   5689:                     );
                   5690:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5691:                         $textval{'corrchkd'} = $1;
                   5692:                         $textval{'corrunchkd'} = $2;
                   5693:                         $textval{'incorrchkd'} = $3;
                   5694:                         $textval{'incorrunchkd'} = $4;
                   5695:                         $display = 'inline';
                   5696:                         $showval = $name;
                   5697:                     } else {
                   5698:                         $display = 'none';
                   5699:                     }
                   5700:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5701:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5702:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5703:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5704:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5705:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5706:                                 '</td></tr>';
                   5707:                     }
                   5708:                     $add .= '</table></div>'."\n";
                   5709:                 }
                   5710:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5711:                 $css_class = ' class="LC_lenient_radio"';
                   5712:             }
                   5713:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5714:                        '<span class="LC_nobreak"><label>'.
                   5715:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5716:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5717:             if ($showval eq $name) {
                   5718:                 $result .= ' checked="checked"';
                   5719:             }
1.549     raeburn  5720:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5721:             $i++;
                   5722:         }
                   5723:         $result .= '</tr>';
1.473     amueller 5724:     }
1.504     raeburn  5725:     if ($result) {
                   5726:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5727:     }
                   5728:     return $result;
                   5729: }
                   5730: 
1.554     raeburn  5731: my %intervals =
                   5732:     (
                   5733:      'date_interval'
                   5734:              => [[ 'done', 'Yes' ],
1.558     raeburn  5735:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5736:                  [ '', 'No' ]],
                   5737:     );
                   5738: 
                   5739: my %intervalmatches = (
                   5740:          'date_interval'
1.559     raeburn  5741:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5742:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5743:     );
                   5744: 
                   5745: my %intervaltypes = (
                   5746:                       interval => 'date_interval',
                   5747:     );
                   5748: 
1.563     damieng  5749: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5750: #
                   5751: # @param {string} $interval_type - a parameter type for intervals
                   5752: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5753: sub standard_interval_matches {
                   5754:     my ($interval_type) = @_;
                   5755:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5756:         return $intervalmatches{$interval_type};
                   5757:     }
                   5758:     return;
                   5759: }
                   5760: 
1.563     damieng  5761: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5762: #
                   5763: # @param {string} $name - parameter name
                   5764: # @returns {string}
1.554     raeburn  5765: sub get_intervaltype {
                   5766:     my ($name) = @_;
                   5767:     if (exists($intervaltypes{$name})) {
                   5768:         return $intervaltypes{$name};
                   5769:     }
                   5770:     return;
                   5771: }
                   5772: 
1.563     damieng  5773: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5774: # Used by courseprefs.
                   5775: #
                   5776: # @param {string} $interval_type - a parameter type for intervals
                   5777: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5778: sub standard_interval_options {
                   5779:     my ($interval_type) = @_;
                   5780:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5781:         return $intervals{$interval_type};
                   5782:     }
                   5783:     return;
                   5784: }
                   5785: 
1.563     damieng  5786: # Returns HTML to edit a date interval parameter.
                   5787: #
                   5788: # @param {string} $thiskey - parameter key
                   5789: # @param {string} $name - parameter name
                   5790: # @param {string} $showval - parameter current value
                   5791: # @param {boolean} $readonly - true if the values should not be made editable
                   5792: # @returns {string}
1.554     raeburn  5793: sub date_interval_selector {
                   5794:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5795:     my ($result,%skipval);
                   5796:     if ($name eq 'interval') {
                   5797:         my $intervaltype = &get_intervaltype($name);
                   5798:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5799:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5800:             next unless (ref($possibilities) eq 'ARRAY');
                   5801:             my ($parmval, $description) = @{ $possibilities };
                   5802:             my $parmmatch;
                   5803:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5804:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5805:                     if (ref($item) eq 'ARRAY') {
                   5806:                         if ($parmval eq $item->[0]) {
                   5807:                             $parmmatch = $parmval;
                   5808:                             $parmval = '';
                   5809:                             last;
                   5810:                         }
                   5811:                     }
                   5812:                 }
                   5813:             }
                   5814:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5815:             if ($needsrelease) {
                   5816:                 unless ($got_chostname) {
                   5817:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5818:                     $got_chostname = 1;
                   5819:                 }
1.557     raeburn  5820:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5821:                                                        $needsrelease,$cmajor,$cminor);
                   5822:                 if ($needsnewer) {
                   5823:                     if ($parmmatch ne '') {
                   5824:                         $skipval{$parmmatch} = 1;
                   5825:                     } elsif ($parmval ne '') {
                   5826:                         $skipval{$parmval} = 1;
                   5827:                     }
                   5828:                 }
                   5829:             }
                   5830:         }
                   5831:     }
                   5832: 
                   5833:     my $currval = $showval;
                   5834:     foreach my $which (['days', 86400, 31],
                   5835:                ['hours', 3600, 23],
                   5836:                ['minutes', 60, 59],
                   5837:                ['seconds',  1, 59]) {
1.560     damieng  5838:         my ($name, $factor, $max) = @{ $which };
                   5839:         my $amount = int($showval/$factor);
                   5840:         $showval  %= $factor;
                   5841:         my %select = ((map {$_ => $_} (0..$max)),
                   5842:                 'select_form_order' => [0..$max]);
1.611     raeburn  5843:         if ($currval eq '') {
                   5844:             unshift(@{$select{'select_form_order'}},'');
                   5845:             $select{''} = '';
                   5846:             $amount = '';
                   5847:         }
1.560     damieng  5848:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5849:                             \%select,'',$readonly);
                   5850:         $result .= ' '.&mt($name);
1.554     raeburn  5851:     }
                   5852:     if ($name eq 'interval') {
                   5853:         unless ($skipval{'done'}) {
                   5854:             my $checkedon = '';
1.611     raeburn  5855:             my $checkedoff = '';
1.558     raeburn  5856:             my $checkedproc = '';
                   5857:             my $currproctorkey = '';
                   5858:             my $currprocdisplay = 'hidden';
1.559     raeburn  5859:             my $currdonetext = &mt('Done');
                   5860:             if ($currval =~ /^(?:\d+)_done$/) {
                   5861:                 $checkedon = ' checked="checked"';
                   5862:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5863:                 $currdonetext = $1;
1.554     raeburn  5864:                 $checkedon = ' checked="checked"';
1.558     raeburn  5865:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5866:                 $currproctorkey = $1;
                   5867:                 $checkedproc = ' checked="checked"';
                   5868:                 $currprocdisplay = 'text';
1.559     raeburn  5869:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5870:                 $currdonetext = $1;
                   5871:                 $currproctorkey = $2;
                   5872:                 $checkedproc = ' checked="checked"';
                   5873:                 $currprocdisplay = 'text';
1.611     raeburn  5874:             } elsif ($currval ne '') {
                   5875:                 $checkedoff = ' checked="checked"';
                   5876:             } else {
                   5877:                 $currdonetext = '';
1.554     raeburn  5878:             }
1.558     raeburn  5879:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5880:             my $disabled;
                   5881:             if ($readonly) {
                   5882:                 $disabled = ' disabled="disabled"';
                   5883:             }
1.558     raeburn  5884:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5885:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5886:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5887:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5888:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5889:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5890:                        &mt('Yes, with proctor key').'</label>'.
                   5891:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5892:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5893:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.611     raeburn  5894:                        '<input type="text" name="done_'.$thiskey.'_buttontext" id="done_'.$thiskey.'_buttontext" value="'.
                   5895:                        &HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5896:         }
                   5897:     }
                   5898:     unless ($readonly) {
                   5899:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5900:     }
                   5901:     return $result;
                   5902: }
                   5903: 
1.563     damieng  5904: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5905: #
                   5906: # @param {string} $name - parameter name
                   5907: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5908: # @param {string} $value - parameter value
                   5909: # @param {string} $chostname - course server name
                   5910: # @param {integer} $cmajor - major version number
                   5911: # @param {integer} $cminor - minor version number
                   5912: # @param {string} $needsrelease - release version needed (major.minor)
                   5913: # @returns {string}
1.549     raeburn  5914: sub oldversion_warning {
1.557     raeburn  5915:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5916:     my $standard_name = &standard_parameter_names($name);
                   5917:     if ($namematch) {
                   5918:         my $level = &standard_parameter_levels($namematch);
                   5919:         my $msg = '';
                   5920:         if ($level) {
                   5921:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5922:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5923:         } else {
                   5924:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5925:                       $standard_name,'<b>','</b>');
                   5926:         }
                   5927:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5928:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5929:                    $cmajor.'.'.$cminor,$chostname,
                   5930:                    $needsrelease).
                   5931:                    '</p>';
                   5932:     }
1.549     raeburn  5933:     my $desc;
                   5934:     my $stringtype = &get_stringtype($name);
                   5935:     if ($stringtype ne '') {
                   5936:         if ($name eq 'examcode') {
                   5937:             $desc = $value;
                   5938:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5939:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5940:                 next unless (ref($possibilities) eq 'ARRAY');
                   5941:                 my ($parmval, $description) = @{ $possibilities };
                   5942:                 my $parmmatch;
                   5943:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5944:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5945:                         if (ref($item) eq 'ARRAY') {
                   5946:                             my ($regexpname,$pattern) = @{$item};
                   5947:                             if ($parmval eq $regexpname) {
                   5948:                                 if ($value =~ /$pattern/) {
                   5949:                                     $desc = $description; 
                   5950:                                     $parmmatch = 1;
                   5951:                                     last;
                   5952:                                 }
                   5953:                             }
                   5954:                         }
                   5955:                     }
                   5956:                     last if ($parmmatch);
                   5957:                 } elsif ($parmval eq $value) {
                   5958:                     $desc = $description;
                   5959:                     last;
                   5960:                 }
                   5961:             }
                   5962:         }
                   5963:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5964:         my $now = time;
                   5965:         if ($value =~ /^\d+$/) {
                   5966:             if ($name eq 'printstartdate') {
                   5967:                 if ($value > $now) {
                   5968:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5969:                 }
                   5970:             } elsif ($name eq 'printenddate') {
                   5971:                 if ($value < $now) {
                   5972:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5973:                 }
                   5974:             }
                   5975:         }
                   5976:     }
                   5977:     return '<p class="LC_warning">'.
1.557     raeburn  5978:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5979:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5980:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5981:        $cmajor.'.'.$cminor,$chostname,
                   5982:        $needsrelease).
                   5983:        '</p>';
1.549     raeburn  5984: }
                   5985: 
1.560     damieng  5986: } # end of block using some constants related to parameter types
                   5987: 
1.549     raeburn  5988: 
1.563     damieng  5989: 
                   5990: # Shifts all start and end dates in the current course by $shift.
1.389     www      5991: #
1.563     damieng  5992: # @param {integer} $shift - time to shift, in seconds
                   5993: # @returns {string} - error name or 'ok'
1.389     www      5994: sub dateshift {
1.594     raeburn  5995:     my ($shift,$numchanges)=@_;
1.389     www      5996:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5997:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5998:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5999:     my $secgrpregex;
                   6000:     if ($sec ne '') {
                   6001:         my @groups;
                   6002:         if ($env{'request.course.groups'} ne '') {
                   6003:             @groups = split(/:/,$env{'request.course.groups'});
                   6004:         }
                   6005:         if (@groups) {
                   6006:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   6007:         } else {
                   6008:             $secgrpregex = $sec;
                   6009:         }
                   6010:     }
1.389     www      6011:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   6012: # ugly retro fix for broken version of types
1.548     raeburn  6013:     foreach my $key (keys(%data)) {
1.389     www      6014:         if ($key=~/\wtype$/) {
                   6015:             my $newkey=$key;
                   6016:             $newkey=~s/type$/\.type/;
                   6017:             $data{$newkey}=$data{$key};
                   6018:             delete $data{$key};
                   6019:         }
                   6020:     }
1.391     www      6021:     my %storecontent=();
1.389     www      6022: # go through all parameters and look for dates
1.548     raeburn  6023:     foreach my $key (keys(%data)) {
1.389     www      6024:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  6025:           if ($sec ne '') {
1.595     raeburn  6026:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  6027:           }
1.389     www      6028:           my $newdate=$data{$key}+$shift;
1.594     raeburn  6029:           $$numchanges ++;
1.391     www      6030:           $storecontent{$key}=$newdate;
1.389     www      6031:        }
                   6032:     }
1.391     www      6033:     my $reply=&Apache::lonnet::cput
                   6034:                 ('resourcedata',\%storecontent,$dom,$crs);
                   6035:     if ($reply eq 'ok') {
                   6036:        &log_parmset(\%storecontent);
                   6037:     }
                   6038:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   6039:     return $reply;
1.389     www      6040: }
                   6041: 
1.563     damieng  6042: # Overview mode UI to edit course parameters.
                   6043: #
                   6044: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6045: sub newoverview {
1.568     raeburn  6046:     my ($r,$parm_permission) = @_;
1.280     albertel 6047: 
1.208     www      6048:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6049:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6050:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6051:     my $readonly = 1;
                   6052:     if ($parm_permission->{'edit'}) {
                   6053:         undef($readonly);
                   6054:     }
1.414     droeschl 6055:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6056:         text=>"Overview Mode"});
1.523     raeburn  6057: 
                   6058:     my %loaditems = (
1.549     raeburn  6059:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  6060:                     );
                   6061:     my $js = '
                   6062: <script type="text/javascript">
                   6063: // <![CDATA[
                   6064: '.
                   6065:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   6066:             &showhide_js()."\n".
1.549     raeburn  6067:             &toggleparmtextbox_js()."\n".
                   6068:             &validateparms_js()."\n".
                   6069:             &ipacc_boxes_js()."\n".
1.558     raeburn  6070:             &done_proctor_js()."\n".
1.588     raeburn  6071:             &deeplink_js()."\n".
1.523     raeburn  6072: '// ]]>
                   6073: </script>
                   6074: ';
1.549     raeburn  6075: 
1.523     raeburn  6076:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   6077:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 6078:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6079:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6080:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      6081:     $r->print(<<ENDOVER);
1.549     raeburn  6082: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      6083: ENDOVER
1.211     www      6084:     my @ids=();
                   6085:     my %typep=();
                   6086:     my %keyp=();
                   6087:     my %allparms=();
                   6088:     my %allparts=();
                   6089:     my %allmaps=();
                   6090:     my %mapp=();
                   6091:     my %symbp=();
                   6092:     my %maptitles=();
                   6093:     my %uris=();
                   6094:     my %keyorder=&standardkeyorder();
                   6095:     my %defkeytype=();
                   6096: 
                   6097:     my %alllevs=();
                   6098:     $alllevs{'Resource Level'}='full';
1.215     www      6099:     $alllevs{'Map/Folder Level'}='map';
1.211     www      6100:     $alllevs{'Course Level'}='general';
                   6101: 
                   6102:     my $csec=$env{'form.csec'};
1.269     raeburn  6103:     my $cgroup=$env{'form.cgroup'};
1.211     www      6104: 
                   6105:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   6106:     my $pschp=$env{'form.pschp'};
1.506     www      6107: 
1.211     www      6108:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      6109:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      6110: 
1.446     bisitz   6111:     my @selected_sections =
1.473     amueller 6112:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      6113:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 6114:     foreach my $sec (@selected_sections) {
                   6115:         if ($sec eq 'all') {
1.211     www      6116:             @selected_sections = ('all');
                   6117:         }
                   6118:     }
1.552     raeburn  6119:     if ($env{'request.course.sec'} ne '') {
                   6120:         @selected_sections = ($env{'request.course.sec'});
                   6121:     }
1.269     raeburn  6122:     my @selected_groups =
                   6123:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      6124: 
                   6125:     my $pssymb='';
                   6126:     my $parmlev='';
1.446     bisitz   6127: 
1.211     www      6128:     unless ($env{'form.parmlev'}) {
                   6129:         $parmlev = 'map';
                   6130:     } else {
                   6131:         $parmlev = $env{'form.parmlev'};
                   6132:     }
                   6133: 
1.446     bisitz   6134:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6135:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  6136:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      6137: 
1.374     albertel 6138:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 6139:         @psprt = keys(%allparts);
1.374     albertel 6140:     }
1.211     www      6141: # Menu to select levels, etc
                   6142: 
1.456     bisitz   6143:     $r->print('<div class="LC_Box">');
1.445     neumanie 6144:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   6145:     $r->print('<div>');
1.523     raeburn  6146:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      6147:     &levelmenu($r,\%alllevs,$parmlev);
1.610     raeburn  6148:     $r->print(&Apache::lonhtmlcommon::row_closure());
                   6149:     &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp,$parmlev);
1.447     bisitz   6150:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6151:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6152:     $r->print('</div></div>');
1.446     bisitz   6153: 
1.456     bisitz   6154:     $r->print('<div class="LC_Box">');
1.452     bisitz   6155:     $r->print('<div>');
1.581     raeburn  6156:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 6157:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   6158:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  6159:     my $sectionselector = &sectionmenu(\@selected_sections);
                   6160:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 6161:     $r->print('<table>'.
1.553     raeburn  6162:               '<tr><th>'.&mt('Parts').'</th>');
                   6163:     if ($sectionselector) {
                   6164:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   6165:     }
                   6166:     if ($groupselector) {
                   6167:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   6168:     }
                   6169:     $r->print('</tr><tr><td>');
1.211     www      6170:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  6171:     $r->print('</td>');
                   6172:     if ($sectionselector) { 
                   6173:         $r->print('<td>'.$sectionselector.'</td>');
                   6174:     }
                   6175:     if ($groupselector) {
                   6176:         $r->print('<td>'.$groupselector.'</td>');
                   6177:     }
                   6178:     $r->print('</tr></table>');
1.447     bisitz   6179:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 6180:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   6181:     $r->print('</div></div>');
                   6182: 
1.456     bisitz   6183:     $r->print('<div class="LC_Box">');
1.452     bisitz   6184:     $r->print('<div>');
1.214     www      6185:     my $sortorder=$env{'form.sortorder'};
                   6186:     unless ($sortorder) { $sortorder='realmstudent'; }
1.612     raeburn  6187:     &sortmenu($r,$sortorder,'newoverview');
1.445     neumanie 6188:     $r->print('</div></div>');
1.446     bisitz   6189: 
1.214     www      6190:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   6191: 
1.211     www      6192: # Build the list data hash from the specified parms
                   6193: 
                   6194:     my $listdata;
                   6195:     %{$listdata}=();
                   6196: 
                   6197:     foreach my $cat (@pscat) {
1.269     raeburn  6198:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   6199:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      6200:     }
                   6201: 
1.212     www      6202:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      6203: 
1.481     amueller 6204:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6205: 
                   6206: # Read modified data
                   6207: 
1.481     amueller 6208:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6209: 
                   6210: # List data
                   6211: 
1.608     raeburn  6212:         my $hash_for_realm;
                   6213:         if (($parmlev eq 'map') && (keys(%allmaps))) {
                   6214:             %{$hash_for_realm} = reverse(%allmaps);
                   6215:         } elsif (($parmlev eq 'full') && (keys(%symbp))) {
                   6216:             for (my $i=0; $i<@ids; $i++) {
                   6217:                 $hash_for_realm->{$symbp{$ids[$i]}} = $i;
                   6218:             }
                   6219:         }
                   6220:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly,$parmlev,$hash_for_realm,$pschp);
1.568     raeburn  6221:     }
                   6222:     $r->print(&tableend());
                   6223:     unless ($readonly) {
                   6224:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6225:     }
1.568     raeburn  6226:     $r->print('</form>');
1.507     www      6227:     &endSettingsScreen($r);
                   6228:     $r->print(&Apache::loncommon::end_page());
1.208     www      6229: }
                   6230: 
1.563     damieng  6231: # Fills $listdata with parameter information.
                   6232: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6233: # The non-type value is always 1.
                   6234: #
                   6235: # @param {string} $cat - parameter name
1.566     damieng  6236: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6237: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6238: # @param {hash reference} $listdata - the parameter data that will be modified
                   6239: # @param {array reference} $psprt - selected parts
                   6240: # @param {array reference} $selections - selected sections
                   6241: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6242: # @param {hash reference} $allmaps - hash map pc -> map src
                   6243: # @param {array reference} $ids - resource and map ids
                   6244: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6245: sub secgroup_lister {
                   6246:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6247:     foreach my $item (@{$selections}) {
                   6248:         foreach my $part (@{$psprt}) {
                   6249:             my $rootparmkey=$env{'request.course.id'};
                   6250:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6251:                 $rootparmkey.='.['.$item.']';
                   6252:             }
                   6253:             if ($parmlev eq 'general') {
                   6254: # course-level parameter
                   6255:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6256:                 $$listdata{$newparmkey}=1;
                   6257:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6258:             } elsif ($parmlev eq 'map') {
                   6259: # map-level parameter
1.548     raeburn  6260:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6261:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6262:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6263:                     $$listdata{$newparmkey}=1;
                   6264:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6265:                 }
                   6266:             } else {
                   6267: # resource-level parameter
                   6268:                 foreach my $rid (@{$ids}) {
                   6269:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6270:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6271:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6272:                     $$listdata{$newparmkey}=1;
                   6273:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6274:                 }
                   6275:             }
                   6276:         }
                   6277:     }
                   6278: }
                   6279: 
1.563     damieng  6280: # UI to edit parameter settings starting with a list of all existing parameters.
                   6281: # (called by setoverview action)
                   6282: #
                   6283: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6284: sub overview {
1.568     raeburn  6285:     my ($r,$parm_permission) = @_;
1.208     www      6286:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6287:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6288:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6289:     my $readonly = 1;
                   6290:     if ($parm_permission->{'edit'}) {
                   6291:         undef($readonly);
                   6292:     }
1.549     raeburn  6293:     my $js = '<script type="text/javascript">'."\n".
                   6294:              '// <![CDATA['."\n".
                   6295:              &toggleparmtextbox_js()."\n".
                   6296:              &validateparms_js()."\n".
                   6297:              &ipacc_boxes_js()."\n".
1.558     raeburn  6298:              &done_proctor_js()."\n".
1.588     raeburn  6299:              &deeplink_js()."\n".
1.549     raeburn  6300:              '// ]]>'."\n".
                   6301:              '</script>'."\n";
1.414     droeschl 6302:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6303:     text=>"Overview Mode"});
1.549     raeburn  6304:     my %loaditems = (
                   6305:                       'onload'   => "showHideLenient();",
                   6306:                     );
                   6307: 
                   6308:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6309:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6310:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6311:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6312:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6313: 
1.208     www      6314: # Store modified
                   6315: 
1.568     raeburn  6316:     unless ($readonly) {
                   6317:         &storedata($r,$crs,$dom);
                   6318:     }
1.208     www      6319: 
                   6320: # Read modified data
                   6321: 
1.552     raeburn  6322:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6323: 
1.214     www      6324: 
                   6325:     my $sortorder=$env{'form.sortorder'};
                   6326:     unless ($sortorder) { $sortorder='realmstudent'; }
1.608     raeburn  6327:     &sortmenu($r,$sortorder,'overview');
1.214     www      6328: 
1.568     raeburn  6329:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6330: 
                   6331:     if ($readonly) {
                   6332:         $r->print('<p>'.$submitbutton.'</p>');
                   6333:     }
                   6334: 
1.208     www      6335: # List data
                   6336: 
1.568     raeburn  6337:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6338:     $r->print(&tableend().'<p>');
                   6339:     if ($foundkeys) {
                   6340:         unless ($readonly) {
                   6341:             $r->print('<p>'.$submitbutton.'</p>');
                   6342:         }
                   6343:     } else {
                   6344:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6345:     }
                   6346:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6347: }
1.121     www      6348: 
1.560     damieng  6349: # Unused sub.
1.563     damieng  6350: #
                   6351: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6352: sub clean_parameters {
                   6353:     my ($r) = @_;
                   6354:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6355:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6356: 
1.414     droeschl 6357:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6358:         text=>"Clean Parameters"});
1.333     albertel 6359:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6360:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6361:     $r->print(<<ENDOVER);
                   6362: $start_page
                   6363: $breadcrumbs
                   6364: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6365: ENDOVER
                   6366: # Store modified
                   6367: 
                   6368:     &storedata($r,$crs,$dom);
                   6369: 
                   6370: # Read modified data
                   6371: 
                   6372:     my $resourcedata=&readdata($crs,$dom);
                   6373: 
                   6374: # List data
                   6375: 
                   6376:     $r->print('<h3>'.
1.473     amueller 6377:           &mt('These parameters refer to resources that do not exist.').
                   6378:           '</h3>'.
                   6379:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6380:           '<br />');
1.333     albertel 6381:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6382:           '<tr>'.
                   6383:           '<th>'.&mt('Delete').'</th>'.
                   6384:           '<th>'.&mt('Parameter').'</th>'.
                   6385:           '</tr>');
1.333     albertel 6386:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6387:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6388:             && $thiskey=~/\.type$/);
                   6389:         my %data = &parse_key($thiskey);
                   6390:         if (1) { #exists($data{'realm_exists'})
                   6391:             #&& !$data{'realm_exists'}) {
                   6392:             $r->print(&Apache::loncommon::start_data_table_row().
                   6393:                 '<tr>'.
                   6394:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6395: 
                   6396:             $r->print('<td>');
                   6397:             my $display_value = $resourcedata->{$thiskey};
                   6398:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6399:             $display_value =
                   6400:                 &Apache::lonlocal::locallocaltime($display_value);
                   6401:             }
1.470     raeburn  6402:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6403:             $parmitem = &mt($parmitem);
1.560     damieng  6404:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6405:                 $parmitem,$resourcedata->{$thiskey}));
                   6406:             $r->print('<br />');
                   6407:             if ($data{'scope_type'} eq 'all') {
                   6408:                 $r->print(&mt('All users'));
                   6409:             } elsif ($data{'scope_type'} eq 'user') {
                   6410:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6411:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6412:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6413:             }
                   6414:             $r->print('<br />');
                   6415:             if ($data{'realm_type'} eq 'all') {
                   6416:                 $r->print(&mt('All Resources'));
                   6417:             } elsif ($data{'realm_type'} eq 'folder') {
                   6418:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6419:             } elsif ($data{'realm_type'} eq 'symb') {
                   6420:             my ($map,$resid,$url) =
                   6421:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6422:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6423:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6424:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6425:             }
                   6426:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6427:             $r->print('</td></tr>');
                   6428: 
1.473     amueller 6429:         }
1.333     albertel 6430:     }
                   6431:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6432:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6433:           '</p></form>');
                   6434:     &endSettingsScreen($r);
                   6435:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6436: }
                   6437: 
1.563     damieng  6438: # UI to shift all dates (called by dateshift1 action).
                   6439: # Used by overview mode.
                   6440: #
                   6441: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6442: sub date_shift_one {
                   6443:     my ($r) = @_;
                   6444:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6445:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6446:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6447:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6448:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6449:         text=>"Shifting Dates"});
1.594     raeburn  6450:     my $submit_text = &mt('Shift all dates accordingly');
                   6451:     if ($sec ne '') {
1.595     raeburn  6452:         my @groups;
                   6453:         if ($env{'request.course.groups'} ne '') {
                   6454:             @groups = split(/:/,$env{'request.course.groups'});
                   6455:         }
                   6456:         if (@groups) {
                   6457:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6458:         } else {
                   6459:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6460:         }
1.594     raeburn  6461:     }
1.390     www      6462:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6463:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6464:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6465:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6466:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6467:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6468:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6469:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6470:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6471:                                                         'timeshifted',
                   6472:                                                         $env{'form.timebase'},,
                   6473:                                                         '').
                   6474:               '</td></tr></table>'.
                   6475:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6476:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6477:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6478:     &endSettingsScreen($r);
1.390     www      6479:     $r->print(&Apache::loncommon::end_page());
                   6480: }
                   6481: 
1.563     damieng  6482: # UI to shift all dates (second form).
                   6483: #
                   6484: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6485: sub date_shift_two {
                   6486:     my ($r) = @_;
                   6487:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6488:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6489:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6490:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6491:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6492:         text=>"Shifting Dates"});
1.390     www      6493:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6494:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6495:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6496:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6497:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6498:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6499:     if ($sec ne '') {
1.595     raeburn  6500:         my @groups;
                   6501:         if ($env{'request.course.groups'} ne '') {
                   6502:             @groups = split(/:/,$env{'request.course.groups'});
                   6503:         }
                   6504:         if (@groups) {
                   6505:             $r->print('<p>'.
                   6506:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6507:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6508:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6509:                       '</p>');
                   6510:         } else {
                   6511:             $r->print('<p>'.
                   6512:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6513:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6514:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6515:                       '</p>');
                   6516:         }
1.594     raeburn  6517:     } else {
                   6518:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6519:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6520:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6521:                   '</p>');
                   6522:     }
1.390     www      6523:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6524:     my $numchanges = 0;
                   6525:     my $result = &dateshift($delta,\$numchanges);
                   6526:     if ($result eq 'ok') {
                   6527:         $r->print(
                   6528:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6529:                                                     $numchanges)));
                   6530:     } elsif ($result eq 'con_delayed') {
                   6531:         $r->print(
                   6532:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6533:                                                         $numchanges)));
                   6534:     } else {
                   6535:         $r->print(
                   6536:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6537:     }
1.543     bisitz   6538:     $r->print(
                   6539:         '<br /><br />'.
                   6540:         &Apache::lonhtmlcommon::actionbox(
                   6541:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6542:     &endSettingsScreen($r);
1.390     www      6543:     $r->print(&Apache::loncommon::end_page());
                   6544: }
                   6545: 
1.563     damieng  6546: # Returns the different components of a resourcedata key.
                   6547: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6548: #       realm_exists, parameter_part, parameter_name.
                   6549: # Was used by clean_parameters (which is unused).
                   6550: #
                   6551: # @param {string} $key - the parameter key
                   6552: # @returns {hash}
1.333     albertel 6553: sub parse_key {
                   6554:     my ($key) = @_;
                   6555:     my %data;
                   6556:     my ($middle,$part,$name)=
1.572     damieng  6557:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6558:     $data{'scope_type'} = 'all';
                   6559:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6560:         $data{'scope'} = $1;
                   6561:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6562:             $data{'scope_type'} = 'user';
                   6563:             $data{'scope'} = [$1,$2];
                   6564:         } else {
1.581     raeburn  6565:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6566:         }
                   6567:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6568:     }
                   6569:     $middle=~s/\.+$//;
                   6570:     $middle=~s/^\.+//;
                   6571:     $data{'realm_type'}='all';
                   6572:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6573:         $data{'realm'} = $1;
                   6574:         $data{'realm_type'} = 'folder';
                   6575:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6576:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6577:     } elsif ($middle) {
1.560     damieng  6578:         $data{'realm'} = $middle;
                   6579:         $data{'realm_type'} = 'symb';
                   6580:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6581:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6582:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6583:     }
1.446     bisitz   6584: 
1.333     albertel 6585:     $data{'parameter_part'} = $part;
                   6586:     $data{'parameter_name'} = $name;
                   6587: 
                   6588:     return %data;
                   6589: }
                   6590: 
1.239     raeburn  6591: 
1.563     damieng  6592: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6593: sub header {
1.507     www      6594:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6595: }
1.193     albertel 6596: 
                   6597: 
                   6598: 
1.560     damieng  6599: ##################################################
                   6600: # MAIN MENU
                   6601: ##################################################
                   6602: 
1.563     damieng  6603: # Content and problem settings main menu.
                   6604: #
                   6605: # @param {Apache2::RequestRec} $r - the Apache request
                   6606: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6607: sub print_main_menu {
                   6608:     my ($r,$parm_permission)=@_;
                   6609:     #
1.414     droeschl 6610:     $r->print(&header());
1.507     www      6611:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6612:     my $crstype = &Apache::loncommon::course_type();
                   6613:     my $lc_crstype = lc($crstype);
                   6614: 
                   6615:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6616:     $r->print(<<ENDMAINFORMHEAD);
                   6617: <form method="post" enctype="multipart/form-data"
                   6618:       action="/adm/parmset" name="studentform">
                   6619: ENDMAINFORMHEAD
                   6620: #
1.195     albertel 6621:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6622:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6623:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6624:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6625:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6626:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6627:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6628:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6629:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6630:                                         '/'.$env{'request.course.sec'});
                   6631:     }
1.568     raeburn  6632:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6633:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6634:                                         '/'.$env{'request.course.sec'});
                   6635:     }
                   6636:     my (%linktext,%linktitle,%url);
                   6637:     if ($parm_permission->{'edit'}) {
                   6638:         %linktext = (
                   6639:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6640:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6641:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6642:                     );
                   6643:         %linktitle = (
                   6644:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6645:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6646:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6647:                      );
                   6648:     } else {
                   6649:         %linktext = (
                   6650:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6651:                      settable        => 'View Resource Parameters - Table Mode',
                   6652:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6653:                    );
                   6654:         %linktitle = (
                   6655:                      newoverview     => 'Display resource parameters in overview mode.',
                   6656:                      settable        => 'Display resource parameters in table mode.',
                   6657:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6658:                      );
                   6659:     }
                   6660:     if ($mgr) {
                   6661:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6662:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6663:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6664:     } elsif ($vgr) {
                   6665:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6666:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6667:         $url{'resettimes'} = '/adm/accesstimes';
                   6668:     }
1.193     albertel 6669:     my @menu =
1.507     www      6670:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6671:         items => [
                   6672:           { linktext => 'Portfolio Metadata',
                   6673:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6674:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6675:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6676:             icon =>'contact-new.png'   ,
                   6677:             },
1.568     raeburn  6678:           { linktext => $linktext{'resettimes'},
                   6679:             url => $url{'resettimes'},
                   6680:             permission => ($vgr || $mgr),
                   6681:             linktitle => $linktitle{'resettimes'},
                   6682:             icon => 'start-here.png',
1.473     amueller 6683:             },
1.520     raeburn  6684:           { linktext => 'Blocking Communication/Resource Access',
                   6685:             url => '/adm/setblock',
1.568     raeburn  6686:             permission => ($vcb || $dcm),
1.520     raeburn  6687:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6688:             icon => 'comblock.png',
                   6689:             },
1.473     amueller 6690:           { linktext => 'Set Parameter Setting Default Actions',
                   6691:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6692:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6693:             linktitle =>'Set default actions for parameters.'  ,
                   6694:             icon => 'folder-new.png'  ,
                   6695:             }]},
                   6696:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6697:         items => [
                   6698:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6699:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6700:             permission => $parm_permission->{'helper'},
1.473     amueller 6701:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6702:             icon => 'dialog-information.png'  ,
                   6703:             #help => 'Parameter_Helper',
                   6704:             },
1.568     raeburn  6705:           { linktext => $linktext{'newoverview'},
1.473     amueller 6706:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6707:             permission => $parm_permission->{'newoverview'},
                   6708:             linktitle => $linktitle{'newoverview'},
                   6709:             icon => 'edit-find.png',
1.473     amueller 6710:             #help => 'Parameter_Overview',
                   6711:             },
1.568     raeburn  6712:           { linktext => $linktext{'settable'},
1.473     amueller 6713:             url => '/adm/parmset?action=settable',
1.568     raeburn  6714:             permission => $parm_permission->{'settable'},
                   6715:             linktitle => $linktitle{'settable'},
                   6716:             icon => 'edit-copy.png',
1.473     amueller 6717:             #help => 'Table_Mode',
                   6718:             }]},
1.417     droeschl 6719:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6720:          items => [
1.570     raeburn  6721:           { linktext => $linktext{'setoverview'},
1.473     amueller 6722:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6723:             permission => $parm_permission->{'setoverview'},
                   6724:             linktitle => $linktitle{'setoverview'},
                   6725:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6726:             #help => 'Parameter_Overview',
                   6727:             },
                   6728:           { linktext => 'Change Log',
                   6729:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6730:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6731:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6732:             icon => 'document-properties.png',
1.473     amueller 6733:             }]}
1.193     albertel 6734:           );
1.414     droeschl 6735:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6736:     $r->print('</form>');
1.507     www      6737:     &endSettingsScreen($r);
1.539     raeburn  6738:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6739:     return;
                   6740: }
1.414     droeschl 6741: 
1.416     jms      6742: 
                   6743: 
1.560     damieng  6744: ##################################################
                   6745: # PORTFOLIO METADATA
                   6746: ##################################################
                   6747: 
1.563     damieng  6748: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6749: # It looks like field titles are not localized.
                   6750: #
                   6751: # @param {Apache2::RequestRec} $r - the Apache request
                   6752: # @param {string} $field_name - metadata field name
                   6753: # @param {string} $field_text - metadata field title, in English unless manually added
                   6754: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6755: sub output_row {
1.347     banghart 6756:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6757:     my $output;
1.263     banghart 6758:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6759:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6760:     if (!defined($options)) {
1.254     banghart 6761:         $options = 'active,stuadd';
1.261     banghart 6762:         $values = '';
1.252     banghart 6763:     }
1.337     banghart 6764:     if (!($options =~ /deleted/)) {
                   6765:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6766:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6767:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6768: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6769:         if ($added_flag) {
                   6770:             push @options,['deleted', 'Delete Metadata Field'];
                   6771:         }
1.351     banghart 6772:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6773:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6774:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6775:         foreach my $opt (@options) {
1.560     damieng  6776:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6777:             $output .= &Apache::loncommon::continue_data_table_row();
                   6778:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6779:                     <input type="checkbox" name="'.
                   6780:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6781:                     &mt($opt->[1]).'</label></td>';
                   6782:             $output .= &Apache::loncommon::end_data_table_row();
                   6783:         }
1.351     banghart 6784:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6785:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6786:         $output .= &Apache::loncommon::end_data_table_row();
                   6787:         my $multiple_checked;
                   6788:         my $single_checked;
                   6789:         if ($options =~ m/onlyone/) {
1.422     bisitz   6790:             $multiple_checked = '';
1.423     bisitz   6791:             $single_checked = ' checked="checked"';
1.351     banghart 6792:         } else {
1.423     bisitz   6793:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6794:             $single_checked = '';
1.351     banghart 6795:         }
1.560     damieng  6796:         $output .= &Apache::loncommon::continue_data_table_row();
                   6797:         $output .= '<td>'.('&nbsp;' x 10).'
                   6798:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6799:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6800:         $output .= &Apache::loncommon::end_data_table_row();
                   6801:         $output .= &Apache::loncommon::continue_data_table_row();
                   6802:         $output .= '<td>'.('&nbsp;' x 10).'
                   6803:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6804:                     '.&mt('Student may select only one choice from list').'</td>';
                   6805:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6806:     }
                   6807:     return ($output);
                   6808: }
1.416     jms      6809: 
                   6810: 
1.560     damieng  6811: # UI to order portfolio metadata fields.
1.563     damieng  6812: # Currently useless because addmetafield does not work.
                   6813: #
                   6814: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6815: sub order_meta_fields {
                   6816:     my ($r)=@_;
                   6817:     my $idx = 1;
                   6818:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6819:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6820:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6821:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6822:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6823:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6824:         text=>"Add Metadata Field"});
1.560     damieng  6825:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6826:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6827:         text=>"Restrict Metadata"},
                   6828:         {text=>"Order Metadata"});
1.345     banghart 6829:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6830:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6831:     if ($env{'form.storeorder'}) {
                   6832:         my $newpos = $env{'form.newpos'} - 1;
                   6833:         my $currentpos = $env{'form.currentpos'} - 1;
                   6834:         my @neworder = ();
1.548     raeburn  6835:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6836:         my $i;
1.341     banghart 6837:         if ($newpos > $currentpos) {
1.340     banghart 6838:         # moving stuff up
                   6839:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6840:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6841:             }
                   6842:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6843:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6844:             }
                   6845:             $neworder[$newpos]=$oldorder[$currentpos];
                   6846:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6847:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6848:             }
                   6849:         } else {
                   6850:         # moving stuff down
1.473     amueller 6851:             for ($i=0;$i<$newpos;$i++) {
                   6852:                 $neworder[$i]=$oldorder[$i];
                   6853:             }
                   6854:             $neworder[$newpos]=$oldorder[$currentpos];
                   6855:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6856:                 $neworder[$i]=$oldorder[$i-1];
                   6857:             }
                   6858:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6859:                 $neworder[$i]=$oldorder[$i];
                   6860:             }
1.340     banghart 6861:         }
1.560     damieng  6862:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6863:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6864:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6865:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6866:     }
1.357     raeburn  6867:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6868:     my $ordered_fields;
1.548     raeburn  6869:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6870:     if (!@fields_in_order) {
                   6871:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6872:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6873:             push @fields_in_order, $key;
1.341     banghart 6874:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6875:         }
1.341     banghart 6876:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6877:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6878:     }
1.340     banghart 6879:     $r->print('<table>');
                   6880:     my $num_fields = scalar(@fields_in_order);
                   6881:     foreach my $key (@fields_in_order) {
                   6882:         $r->print('<tr><td>');
                   6883:         $r->print('<form method="post" action="">');
1.537     bisitz   6884:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6885:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6886:             if ($i eq $idx) {
                   6887:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6888:             } else {
                   6889:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6890:             }
                   6891:         }
                   6892:         $r->print('</select></td><td>');
                   6893:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6894:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6895:         $r->print('</form>');
                   6896:         $r->print($$fields{$key}.'</td></tr>');
                   6897:         $idx ++;
                   6898:     }
                   6899:     $r->print('</table>');
1.507     www      6900:     &endSettingsScreen($r);
1.340     banghart 6901:     return 'ok';
                   6902: }
1.416     jms      6903: 
                   6904: 
1.563     damieng  6905: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6906: # @returns {string}
1.359     banghart 6907: sub continue {
                   6908:     my $output;
                   6909:     $output .= '<form action="" method="post">';
                   6910:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6911:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6912:     return ($output);
                   6913: }
1.416     jms      6914: 
                   6915: 
1.563     damieng  6916: # UI to add a metadata field.
                   6917: # Currenly does not work because of an HTML error (the field is not visible).
                   6918: #
                   6919: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6920: sub addmetafield {
                   6921:     my ($r)=@_;
1.414     droeschl 6922:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6923:         text=>"Add Metadata Field"});
1.334     banghart 6924:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6925:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6926:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6927:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6928:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6929:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6930:     if (exists($env{'form.undelete'})) {
1.358     banghart 6931:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6932:         foreach my $meta_field(@meta_fields) {
                   6933:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6934:             $options =~ s/deleted//;
                   6935:             $options =~ s/,,/,/;
                   6936:             my $put_result = &Apache::lonnet::put('environment',
                   6937:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6938: 
1.586     raeburn  6939:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6940:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6941:                           '</strong>',$put_result).
                   6942:                       '<br />');
1.339     banghart 6943:         }
1.359     banghart 6944:         $r->print(&continue());
1.339     banghart 6945:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6946:         my $meta_field = $env{'form.fieldname'};
                   6947:         my $display_field = $env{'form.fieldname'};
                   6948:         $meta_field =~ s/\W/_/g;
1.338     banghart 6949:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6950:         my $put_result = &Apache::lonnet::put('environment',
                   6951:                             {'metadata.'.$meta_field.'.values'=>"",
                   6952:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6953:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6954:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6955:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6956:                   '<br />');
1.359     banghart 6957:         $r->print(&continue());
1.335     banghart 6958:     } else {
1.357     raeburn  6959:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6960:         if ($fields) {
1.586     raeburn  6961:             $r->print(&mt('You may undelete previously deleted fields.').
                   6962:                       '<br />'.
                   6963:                       &mt('Check those you wish to undelete and click Undelete.').
                   6964:                       '<br />');
1.339     banghart 6965:             $r->print('<form method="post" action="">');
                   6966:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6967:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6968:             }
1.586     raeburn  6969:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6970:             $r->print('</form>');
                   6971:         }
1.586     raeburn  6972:         $r->print('<hr />'.
                   6973:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6974:                       '<strong>','</strong>').
1.581     raeburn  6975:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6976:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6977:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6978:         $r->print('</form>');
1.334     banghart 6979:     }
1.507     www      6980:     &endSettingsScreen($r);
1.334     banghart 6981: }
1.416     jms      6982: 
                   6983: 
                   6984: 
1.560     damieng  6985: # Display or save portfolio metadata.
1.563     damieng  6986: #
                   6987: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6988: sub setrestrictmeta {
1.240     banghart 6989:     my ($r)=@_;
1.242     banghart 6990:     my $next_meta;
1.244     banghart 6991:     my $output;
1.245     banghart 6992:     my $item_num;
1.246     banghart 6993:     my $put_result;
1.414     droeschl 6994:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6995:         text=>"Restrict Metadata"});
1.280     albertel 6996:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6997:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6998:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6999:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  7000:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   7001:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 7002:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 7003:     my $save_field = '';
1.586     raeburn  7004:     my %lt = &Apache::lonlocal::texthash(
                   7005:                                            addm => 'Add Metadata Field',
                   7006:                                            ordm => 'Order Metadata Fields',
                   7007:                                            save => 'Save',
                   7008:                                         );
1.259     banghart 7009:     if ($env{'form.restrictmeta'}) {
1.254     banghart 7010:         foreach my $field (sort(keys(%env))) {
1.252     banghart 7011:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 7012:                 my $options;
1.252     banghart 7013:                 my $meta_field = $1;
                   7014:                 my $meta_key = $2;
1.253     banghart 7015:                 if ($save_field ne $meta_field) {
1.252     banghart 7016:                     $save_field = $meta_field;
1.473     amueller 7017:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   7018:                         $options.='stuadd,';
                   7019:                     }
                   7020:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   7021:                         $options.='choices,';
                   7022:                     }
                   7023:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   7024:                         $options.='onlyone,';
                   7025:                     }
                   7026:                     if ($env{'form.'.$meta_field.'_active'}) {
                   7027:                         $options.='active,';
                   7028:                     }
                   7029:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   7030:                         $options.='deleted,';
                   7031:                     }
1.259     banghart 7032:                     my $name = $save_field;
1.560     damieng  7033:                     $put_result = &Apache::lonnet::put('environment',
                   7034:                         {'metadata.'.$meta_field.'.options'=>$options,
                   7035:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   7036:                         },$dom,$crs);
1.252     banghart 7037:                 }
                   7038:             }
                   7039:         }
                   7040:     }
1.296     albertel 7041:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 7042:                        {'freshen_cache' => 1});
1.335     banghart 7043:     # Get the default metadata fields
1.258     albertel 7044:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 7045:     # Now get possible added metadata fields
1.357     raeburn  7046:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 7047:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 7048:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 7049:         if ($field ne 'courserestricted') {
1.586     raeburn  7050:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  7051:         }
1.255     banghart 7052:     }
1.351     banghart 7053:     my $buttons = (<<ENDButtons);
1.586     raeburn  7054:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 7055:         </form><br />
                   7056:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  7057:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 7058:         </form>
                   7059:         <br />
                   7060:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  7061:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 7062: ENDButtons
1.337     banghart 7063:     my $added_flag = 1;
1.335     banghart 7064:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  7065:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 7066:     }
1.347     banghart 7067:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   7068:     $r->print(<<ENDenv);
1.259     banghart 7069:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 7070:         $output
1.351     banghart 7071:         $buttons
1.340     banghart 7072:         </form>
1.244     banghart 7073: ENDenv
1.507     www      7074:     &endSettingsScreen($r);
1.280     albertel 7075:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 7076:     return 'ok';
                   7077: }
1.416     jms      7078: 
                   7079: 
1.563     damieng  7080: # Returns metadata fields that have been manually added.
                   7081: #
                   7082: # @param {string} $cid - course id
                   7083: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 7084: sub get_added_meta_fieldnames {
1.357     raeburn  7085:     my ($cid) = @_;
1.335     banghart 7086:     my %fields;
                   7087:     foreach my $key(%env) {
1.357     raeburn  7088:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 7089:             my $field_name = $1;
                   7090:             my ($display_field_name) = $env{$key};
                   7091:             $fields{$field_name} = $display_field_name;
                   7092:         }
                   7093:     }
                   7094:     return \%fields;
                   7095: }
1.416     jms      7096: 
                   7097: 
1.563     damieng  7098: # Returns metadata fields that have been manually added and deleted.
                   7099: #
                   7100: # @param {string} $cid - course id
                   7101: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 7102: sub get_deleted_meta_fieldnames {
1.357     raeburn  7103:     my ($cid) = @_;
1.339     banghart 7104:     my %fields;
                   7105:     foreach my $key(%env) {
1.357     raeburn  7106:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 7107:             my $field_name = $1;
                   7108:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   7109:                 my ($display_field_name) = $env{$key};
                   7110:                 $fields{$field_name} = $display_field_name;
                   7111:             }
                   7112:         }
                   7113:     }
                   7114:     return \%fields;
                   7115: }
1.560     damieng  7116: 
                   7117: 
                   7118: ##################################################
                   7119: # PARAMETER SETTINGS DEFAULT ACTIONS
                   7120: ##################################################
                   7121: 
                   7122: # UI to change parameter setting default actions
1.563     damieng  7123: #
                   7124: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      7125: sub defaultsetter {
1.280     albertel 7126:     my ($r) = @_;
                   7127: 
1.414     droeschl 7128:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 7129:         text=>"Set Defaults"});
1.531     raeburn  7130:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7131:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   7132:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   7133:     my $start_page =
1.531     raeburn  7134:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 7135:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      7136:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  7137:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      7138:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 7139: 
1.221     www      7140:     my @ids=();
                   7141:     my %typep=();
                   7142:     my %keyp=();
                   7143:     my %allparms=();
                   7144:     my %allparts=();
                   7145:     my %allmaps=();
                   7146:     my %mapp=();
                   7147:     my %symbp=();
                   7148:     my %maptitles=();
                   7149:     my %uris=();
                   7150:     my %keyorder=&standardkeyorder();
                   7151:     my %defkeytype=();
                   7152: 
1.446     bisitz   7153:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 7154:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   7155:                 \%keyorder,\%defkeytype);
1.224     www      7156:     if ($env{'form.storerules'}) {
1.560     damieng  7157:         my %newrules=();
                   7158:         my @delrules=();
                   7159:         my %triggers=();
                   7160:         foreach my $key (keys(%env)) {
1.225     albertel 7161:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  7162:                 my $tempkey=$1;
                   7163:                 my $action=$env{$key};
1.226     www      7164:                 if ($action) {
1.560     damieng  7165:                     $newrules{$tempkey.'_action'}=$action;
                   7166:                     if ($action ne 'default') {
                   7167:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   7168:                         $triggers{$whichparm}.=$tempkey.':';
                   7169:                     }
                   7170:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   7171:                     if (&isdateparm($defkeytype{$tempkey})) {
                   7172:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   7173:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   7174:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   7175:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   7176:                     } else {
                   7177:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   7178:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   7179:                     }
                   7180:                 } else {
                   7181:                     push(@delrules,$tempkey.'_action');
                   7182:                     push(@delrules,$tempkey.'_type');
                   7183:                     push(@delrules,$tempkey.'_hours');
                   7184:                     push(@delrules,$tempkey.'_min');
                   7185:                     push(@delrules,$tempkey.'_sec');
                   7186:                     push(@delrules,$tempkey.'_value');
                   7187:                 }
1.473     amueller 7188:             }
                   7189:         }
1.560     damieng  7190:         foreach my $key (keys(%allparms)) {
                   7191:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 7192:         }
1.560     damieng  7193:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   7194:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   7195:         &resetrulescache();
1.224     www      7196:     }
1.227     www      7197:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 7198:                        'hours' => 'Hours',
                   7199:                        'min' => 'Minutes',
                   7200:                        'sec' => 'Seconds',
                   7201:                        'yes' => 'Yes',
                   7202:                        'no' => 'No');
1.222     www      7203:     my @standardoptions=('','default');
                   7204:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   7205:     my @dateoptions=('','default');
                   7206:     my @datedisplay=('',&mt('Default value when manually setting'));
                   7207:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7208:         unless ($tempkey) { next; }
                   7209:         push @standardoptions,'when_setting_'.$tempkey;
                   7210:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   7211:         if (&isdateparm($defkeytype{$tempkey})) {
                   7212:             push @dateoptions,'later_than_'.$tempkey;
                   7213:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7214:             push @dateoptions,'earlier_than_'.$tempkey;
                   7215:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7216:         }
1.222     www      7217:     }
1.563     damieng  7218:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7219:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7220:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7221:           &Apache::loncommon::start_data_table_header_row().
                   7222:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7223:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7224:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7225:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7226:         unless ($tempkey) { next; }
                   7227:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7228:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7229:         my $action=&rulescache($tempkey.'_action');
                   7230:         $r->print('<select name="'.$tempkey.'_action">');
                   7231:         if (&isdateparm($defkeytype{$tempkey})) {
                   7232:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7233:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7234:             $r->print("\n<option value='$dateoptions[$i]'".
                   7235:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7236:                 ">$datedisplay[$i]</option>");
                   7237:             }
                   7238:         } else {
                   7239:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7240:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7241:             $r->print("\n<option value='$standardoptions[$i]'".
                   7242:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7243:                 ">$standarddisplay[$i]</option>");
                   7244:             }
1.473     amueller 7245:         }
1.560     damieng  7246:         $r->print('</select>');
                   7247:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7248:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7249:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7250:         }
1.560     damieng  7251:         $r->print("\n</td><td>\n");
1.222     www      7252: 
1.221     www      7253:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7254:             my $days=&rulescache($tempkey.'_days');
                   7255:             my $hours=&rulescache($tempkey.'_hours');
                   7256:             my $min=&rulescache($tempkey.'_min');
                   7257:             my $sec=&rulescache($tempkey.'_sec');
                   7258:             $r->print(<<ENDINPUTDATE);
                   7259:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7260:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7261:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7262:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7263: ENDINPUTDATE
1.560     damieng  7264:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7265:                 my $yeschecked='';
                   7266:                 my $nochecked='';
                   7267:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7268:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7269: 
                   7270:             $r->print(<<ENDYESNO);
                   7271:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7272:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7273: ENDYESNO
1.221     www      7274:         } else {
1.560     damieng  7275:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7276:         }
1.318     albertel 7277:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7278:     }
1.318     albertel 7279:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7280:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7281:           &mt('Save').'" /></form>'."\n");
                   7282:     &endSettingsScreen($r);
                   7283:     $r->print(&Apache::loncommon::end_page());
1.220     www      7284:     return;
                   7285: }
1.193     albertel 7286: 
1.560     damieng  7287: ##################################################
                   7288: # PARAMETER CHANGES LOG
                   7289: ##################################################
                   7290: 
1.563     damieng  7291: # Returns some info for a parameter log entry.
                   7292: # Returned entries:
                   7293: # $realm - HTML title for the parameter level and resource
                   7294: # $section - parameter section
                   7295: # $name - parameter name
                   7296: # $part - parameter part
                   7297: # $what - $part.'.'.$name
                   7298: # $middle - resource symb ?
                   7299: # $uname - user name (same as given)
                   7300: # $udom - user domain (same as given)
                   7301: # $issection - section or group name
                   7302: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7303: #
                   7304: # @param {string} $key - parameter log key
                   7305: # @param {string} $uname - user name
                   7306: # @param {string} $udom - user domain
                   7307: # @param {boolean} $typeflag - .type log entry
                   7308: # @returns {Array}
1.290     www      7309: sub components {
1.581     raeburn  7310:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7311: 
                   7312:     if ($typeflag) {
1.560     damieng  7313:         $key=~s/\.type$//;
1.290     www      7314:     }
1.330     albertel 7315: 
                   7316:     my ($middle,$part,$name)=
1.572     damieng  7317:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7318:     my $issection;
1.330     albertel 7319: 
1.290     www      7320:     my $section=&mt('All Students');
                   7321:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7322:         $issection=$1;
                   7323:         $section=&mt('Group/Section').': '.$issection;
                   7324:         $middle=~s/^\[(.*)\]//;
1.290     www      7325:     }
                   7326:     $middle=~s/\.+$//;
                   7327:     $middle=~s/^\.+//;
1.291     www      7328:     if ($uname) {
1.560     damieng  7329:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7330:         $issection='';
1.291     www      7331:     }
1.316     albertel 7332:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7333:     my $realmdescription=&mt('all resources');
1.556     raeburn  7334:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7335:         my $mapurl = $1;
                   7336:         my $maplevel = $2;
                   7337:         my $leveltitle = &mt('Folder/Map');
                   7338:         if ($maplevel eq 'rec') {
                   7339:             $leveltitle = &mt('Recursive');
                   7340:         }
1.560     damieng  7341:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7342:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7343:             $mapurl.')</span></span>';
                   7344:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7345:     } elsif ($middle) {
                   7346:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7347:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7348:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7349:             ' in '.$map.' id: '.$id.')</span></span>';
                   7350:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7351:     }
1.291     www      7352:     my $what=$part.'.'.$name;
1.330     albertel 7353:     return ($realm,$section,$name,$part,
1.473     amueller 7354:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7355: }
1.293     www      7356: 
1.563     damieng  7357: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7358: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7359: 
1.563     damieng  7360: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7361: sub load_parameter_names {
1.583     raeburn  7362:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7363:     while (my $configline=<$config>) {
1.560     damieng  7364:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7365:         chomp($configline);
                   7366:         my ($short,$plain)=split(/:/,$configline);
                   7367:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7368:         if ($type eq 'display') {
                   7369:             $standard_parms{$name} = $plain;
1.469     raeburn  7370:         } elsif ($type eq 'type') {
1.560     damieng  7371:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7372:         }
1.328     albertel 7373:     }
                   7374:     close($config);
                   7375:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7376:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7377:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7378: }
                   7379: 
1.563     damieng  7380: # Returns a parameter title for standard parameters, the name for others.
                   7381: #
                   7382: # @param {string} $name - parameter name
                   7383: # @returns {string}
1.292     www      7384: sub standard_parameter_names {
                   7385:     my ($name)=@_;
1.328     albertel 7386:     if (!%standard_parms) {
1.560     damieng  7387:         &load_parameter_names();
1.328     albertel 7388:     }
1.292     www      7389:     if ($standard_parms{$name}) {
1.560     damieng  7390:         return $standard_parms{$name};
1.446     bisitz   7391:     } else {
1.560     damieng  7392:         return $name;
1.292     www      7393:     }
                   7394: }
1.290     www      7395: 
1.563     damieng  7396: # Returns a parameter type for standard parameters, undef for others.
                   7397: #
                   7398: # @param {string} $name - parameter name
                   7399: # @returns {string}
1.469     raeburn  7400: sub standard_parameter_types {
                   7401:     my ($name)=@_;
                   7402:     if (!%standard_parms_types) {
                   7403:         &load_parameter_names();
                   7404:     }
                   7405:     if ($standard_parms_types{$name}) {
                   7406:         return $standard_parms_types{$name};
                   7407:     }
                   7408:     return;
                   7409: }
1.309     www      7410: 
1.563     damieng  7411: # Returns a parameter level title (not localized) from the parameter level name.
                   7412: #
                   7413: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7414: # @returns {string}
1.557     raeburn  7415: sub standard_parameter_levels {
                   7416:     my ($name)=@_;
                   7417:     my %levels = (
                   7418:                     'resourcelevel'   => 'a single resource',
                   7419:                     'maplevel'        => 'the enclosing map/folder', 
                   7420:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7421:                     'courselevel'     => 'the general (course) level',
                   7422:                  );
                   7423:     if ($levels{$name}) {
                   7424:         return $levels{$name};
                   7425:     }
                   7426:     return;
                   7427: }
                   7428: 
1.560     damieng  7429: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7430: #
                   7431: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7432: sub parm_change_log {
1.568     raeburn  7433:     my ($r,$parm_permission)=@_;
1.531     raeburn  7434:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7435:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7436:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7437:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7438:     text=>"Parameter Change Log"});
1.522     raeburn  7439:     my $js = '<script type="text/javascript">'."\n".
                   7440:              '// <![CDATA['."\n".
                   7441:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7442:              '// ]]>'."\n".
                   7443:              '</script>'."\n";
                   7444:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7445:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7446:     &startSettingsScreen($r,'parmset',$crstype);
                   7447:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7448: 
1.301     www      7449:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7450: 
1.522     raeburn  7451:     $r->print('<div class="LC_left_float">'.
                   7452:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7453:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7454:                      method="post" name="parameterlog">');
1.446     bisitz   7455: 
1.311     albertel 7456:     my %saveable_parameters = ('show' => 'scalar',);
                   7457:     &Apache::loncommon::store_course_settings('parameter_log',
                   7458:                                               \%saveable_parameters);
                   7459:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7460:                                                 \%saveable_parameters);
1.522     raeburn  7461:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7462:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7463:               '</form></fieldset></div><br clear="all" />');
1.301     www      7464: 
1.568     raeburn  7465:     my $readonly = 1;
                   7466:     if ($parm_permission->{'edit'}) {
                   7467:         undef($readonly);
                   7468:     }
1.531     raeburn  7469:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7470:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7471:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7472:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7473:     unless ($readonly) {
                   7474:         $r->print('<th>'.&mt('Announce').'</th>');
                   7475:     }
                   7476:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7477:     my $shown=0;
1.349     www      7478:     my $folder='';
                   7479:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7480:         my $last='';
                   7481:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7482:                 &GDBM_READER(),0640)) {
                   7483:             $last=$hash{'last_known'};
                   7484:             untie(%hash);
                   7485:         }
                   7486:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7487:     }
1.595     raeburn  7488:     my $numgroups = 0;
                   7489:     my @groups;
                   7490:     if ($env{'request.course.groups'} ne '') {
                   7491:         @groups = split(/:/,$env{'request.course.groups'});
                   7492:         $numgroups = scalar(@groups);
                   7493:     }
1.560     damieng  7494:     foreach my $id (sort {
                   7495:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7496:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7497:                 }
                   7498:                 my $aid = (split('00000',$a))[-1];
                   7499:                 my $bid = (split('00000',$b))[-1];
                   7500:                 return $bid<=>$aid;
1.473     amueller 7501:             } (keys(%parmlog))) {
1.294     www      7502:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7503:         my $count = 0;
                   7504:         my $time =
                   7505:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7506:         my $plainname =
                   7507:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7508:                         $parmlog{$id}{'exe_udom'});
                   7509:         my $about_me_link =
                   7510:             &Apache::loncommon::aboutmewrapper($plainname,
                   7511:                             $parmlog{$id}{'exe_uname'},
                   7512:                             $parmlog{$id}{'exe_udom'});
                   7513:         my $send_msg_link='';
1.568     raeburn  7514:         if ((!$readonly) && 
                   7515:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7516:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7517:             $send_msg_link ='<br />'.
                   7518:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7519:                             $parmlog{$id}{'exe_uname'},
                   7520:                             $parmlog{$id}{'exe_udom'});
                   7521:         }
                   7522:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7523:         my $makenewrow=0;
                   7524:         my %istype=();
                   7525:         my $output;
                   7526:         foreach my $changed (reverse(sort(@changes))) {
                   7527:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7528:             my $typeflag = ($changed =~/\.type$/ &&
                   7529:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7530:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7531:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7532:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7533:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7534:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7535:                 if ($uname ne '') {
                   7536:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7537:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7538:                 }
                   7539:             }
                   7540:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7541:                 if ($folder) {
                   7542:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7543:                 }
                   7544:             }
                   7545:             if ($typeflag) {
                   7546:                 $istype{$parmname}=$value;
                   7547:                 if (!$env{'form.includetypes'}) { next; }
                   7548:             }
                   7549:             $count++;
                   7550:             if ($makenewrow) {
                   7551:                 $output .= $row_start;
                   7552:             } else {
                   7553:                 $makenewrow=1;
                   7554:             }
1.470     raeburn  7555:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7556:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7557:                 &mt($parmitem).'</td><td>'.
                   7558:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7559:             my $stillactive=0;
                   7560:             if ($parmlog{$id}{'delflag'}) {
                   7561:                 $output .= &mt('Deleted');
                   7562:             } else {
                   7563:                 if ($typeflag) {
1.470     raeburn  7564:                     my $parmitem = &standard_parameter_names($value); 
                   7565:                     $parmitem = &mt($parmitem);
1.560     damieng  7566:                     $output .= &mt('Type: [_1]',$parmitem);
                   7567:                 } else {
1.584     raeburn  7568:                     my $toolsymb;
                   7569:                     if ($middle =~ /ext\.tool$/) {
                   7570:                         $toolsymb = $middle;
                   7571:                     }
1.560     damieng  7572:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7573:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7574:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7575:                     my $showvalue = $value;
                   7576:                     if ($istype{$parmname} eq '') {
                   7577:                         my $type = &standard_parameter_types($parmname);
                   7578:                         if ($type ne '') {
                   7579:                             if (&isdateparm($type)) {
                   7580:                                 $showvalue =
                   7581:                                     &Apache::lonlocal::locallocaltime($value);
                   7582:                             }
                   7583:                         }
                   7584:                     } else {
1.560     damieng  7585:                         if (&isdateparm($istype{$parmname})) {
                   7586:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7587:                         }
1.469     raeburn  7588:                     }
                   7589:                     $output .= $showvalue;
1.560     damieng  7590:                     if ($value ne $all[$level]) {
                   7591:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7592:                     } else {
                   7593:                         $stillactive=1;
                   7594:                     }
                   7595:                 }
1.473     amueller 7596:             }
1.568     raeburn  7597:             $output .= '</td>';
                   7598: 
                   7599:             unless ($readonly) { 
                   7600:                 $output .= '<td>';
                   7601:                 if ($stillactive) {
                   7602:                     my $parmitem = &standard_parameter_names($parmname);
                   7603:                     $parmitem = &mt($parmitem);
                   7604:                     my $title=&mt('Changed [_1]',$parmitem);
                   7605:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7606:                         $parmitem,$realmdescription,
                   7607:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7608:                     if (($uname) && ($udom)) {
                   7609:                         $output .=
                   7610:                         &Apache::loncommon::messagewrapper('Notify User',
                   7611:                                                            $uname,$udom,$title,
                   7612:                                                            $description);
                   7613:                     } else {
                   7614:                         $output .=
                   7615:                             &Apache::lonrss::course_blog_link($id,$title,
                   7616:                                                               $description);
                   7617:                     }
1.560     damieng  7618:                 }
1.568     raeburn  7619:                 $output .= '</td>';
1.560     damieng  7620:             }
1.568     raeburn  7621:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7622:         }
1.560     damieng  7623:         if ($env{'form.displayfilter'} eq 'containing') {
                   7624:             my $wholeentry=$about_me_link.':'.
                   7625:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7626:             $output;
                   7627:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7628:         }
1.349     www      7629:         if ($count) {
1.560     damieng  7630:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7631:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7632:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7633:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7634:             $send_msg_link.'</td>'.$output);
                   7635:             $shown++;
                   7636:         }
                   7637:         if (!($env{'form.show'} eq &mt('all')
                   7638:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7639:     }
1.301     www      7640:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7641:     &endSettingsScreen($r);
1.284     www      7642:     $r->print(&Apache::loncommon::end_page());
                   7643: }
                   7644: 
1.560     damieng  7645: ##################################################
                   7646: # MISC !
                   7647: ##################################################
                   7648: 
1.563     damieng  7649: # Stores slot information.
1.560     damieng  7650: # Used by table UI
1.563     damieng  7651: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7652: #
                   7653: # @param {string} $slot_name - slot name
                   7654: # @param {string} $cdom - course domain
                   7655: # @param {string} $cnum - course number
                   7656: # @param {string} $symb - resource symb
                   7657: # @param {string} $uname - user name
                   7658: # @param {string} $udom - user domain
                   7659: # @returns {string} - 'ok' or error name
1.437     raeburn  7660: sub update_slots {
                   7661:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7662:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7663:     if (!keys(%slot)) {
                   7664:         return 'error: slot does not exist';
                   7665:     }
                   7666:     my $max=$slot{'maxspace'};
                   7667:     if (!defined($max)) { $max=99999; }
                   7668: 
                   7669:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7670:                                        "^$slot_name\0");
                   7671:     my ($tmp)=%consumed;
                   7672:     if ($tmp=~/^error: 2 / ) {
                   7673:         return 'error: unable to determine current slot status';
                   7674:     }
                   7675:     my $last=0;
                   7676:     foreach my $key (keys(%consumed)) {
                   7677:         my $num=(split('\0',$key))[1];
                   7678:         if ($num > $last) { $last=$num; }
                   7679:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7680:             return 'ok';
                   7681:         }
                   7682:     }
                   7683: 
                   7684:     if (scalar(keys(%consumed)) >= $max) {
                   7685:         return 'error: no space left in slot';
                   7686:     }
                   7687:     my $wanted=$last+1;
                   7688: 
                   7689:     my %reservation=('name'      => $uname.':'.$udom,
                   7690:                      'timestamp' => time,
                   7691:                      'symb'      => $symb);
                   7692: 
                   7693:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7694:                                         {"$slot_name\0$wanted" =>
                   7695:                                              \%reservation},
                   7696:                                         $cdom, $cnum);
1.438     raeburn  7697:     if ($success eq 'ok') {
                   7698:         my %storehash = (
                   7699:                           symb    => $symb,
                   7700:                           slot    => $slot_name,
                   7701:                           action  => 'reserve',
                   7702:                           context => 'parameter',
                   7703:                         );
1.526     raeburn  7704:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7705:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7706: 
1.526     raeburn  7707:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7708:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7709:     }
1.437     raeburn  7710:     return $success;
                   7711: }
                   7712: 
1.563     damieng  7713: # Deletes a slot reservation.
1.560     damieng  7714: # Used by table UI
1.563     damieng  7715: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7716: #
                   7717: # @param {string} $slot_name - slot name
                   7718: # @param {string} $cdom - course domain
                   7719: # @param {string} $cnum - course number
                   7720: # @param {string} $uname - user name
                   7721: # @param {string} $udom - user domain
                   7722: # @param {string} $symb - resource symb
                   7723: # @returns {string} - 'ok' or error name
1.437     raeburn  7724: sub delete_slots {
                   7725:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7726:     my $delresult;
                   7727:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7728:                                          $cnum, "^$slot_name\0");
                   7729:     if (&Apache::lonnet::error(%consumed)) {
                   7730:         return 'error: unable to determine current slot status';
                   7731:     }
                   7732:     my ($tmp)=%consumed;
                   7733:     if ($tmp=~/^error: 2 /) {
                   7734:         return 'error: unable to determine current slot status';
                   7735:     }
                   7736:     foreach my $key (keys(%consumed)) {
                   7737:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7738:             my $num=(split('\0',$key))[1];
                   7739:             my $entry = $slot_name.'\0'.$num;
                   7740:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7741:                                               $cdom,$cnum);
                   7742:             if ($delresult eq 'ok') {
                   7743:                 my %storehash = (
                   7744:                                   symb    => $symb,
                   7745:                                   slot    => $slot_name,
                   7746:                                   action  => 'release',
                   7747:                                   context => 'parameter',
                   7748:                                 );
1.526     raeburn  7749:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7750:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7751:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7752:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7753:             }
                   7754:         }
                   7755:     }
                   7756:     return $delresult;
                   7757: }
                   7758: 
1.563     damieng  7759: # Returns true if there is a current course.
1.560     damieng  7760: # Used by handler
1.563     damieng  7761: #
                   7762: # @returns {boolean}
1.355     albertel 7763: sub check_for_course_info {
                   7764:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7765:     return 1 if ($navmap);
                   7766:     return 0;
                   7767: }
                   7768: 
1.563     damieng  7769: # Returns the current course host and host LON-CAPA version.
                   7770: #
                   7771: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7772: sub parameter_release_vars { 
1.504     raeburn  7773:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7774:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7775:    my $chostname = &Apache::lonnet::hostname($chome);
                   7776:    my ($cmajor,$cminor) = 
                   7777:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7778:    return ($chostname,$cmajor,$cminor);
                   7779: }
                   7780: 
1.563     damieng  7781: # Checks if the course host version can handle a parameter required version,
                   7782: # and if it does, stores the release needed for the course.
                   7783: #
                   7784: # @param {string} $name - parameter name
                   7785: # @param {string} $value - parameter value
                   7786: # @param {string} $valmatch - name of the test used for checking the value
                   7787: # @param {string} $namematch - name of the test used for checking the name
                   7788: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7789: # @param {integer} $cmajor - course major version number
                   7790: # @param {integer} $cminor - course minor version number
                   7791: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7792: sub parameter_releasecheck {
1.557     raeburn  7793:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7794:     my $needsnewer;
                   7795:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7796:     if (($cmajor < $needsmajor) || 
                   7797:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7798:         $needsnewer = 1;
1.557     raeburn  7799:     } elsif ($name) {
                   7800:         if ($valmatch) {
                   7801:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7802:         } elsif ($value) { 
                   7803:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7804:         }
                   7805:     } elsif ($namematch) {
                   7806:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7807:     }
                   7808:     return $needsnewer;
                   7809: }
                   7810: 
1.568     raeburn  7811: sub get_permission {
                   7812:     my %permission;
                   7813:     my $allowed = 0;
                   7814:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7815:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7816:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7817:                   $env{'request.course.sec'}))) {
                   7818:         %permission= (
                   7819:                        'edit'               => 1,
                   7820:                        'set'                => 1,
                   7821:                        'setoverview'        => 1,
                   7822:                        'addmetadata'        => 1,
                   7823:                        'ordermetadata'      => 1,
                   7824:                        'setrestrictmeta'    => 1,
                   7825:                        'newoverview'        => 1,
                   7826:                        'setdefaults'        => 1,
                   7827:                        'settable'           => 1,
                   7828:                        'parameterchangelog' => 1,
                   7829:                        'cleanparameters'    => 1,
                   7830:                        'dateshift1'         => 1,
                   7831:                        'dateshift2'         => 1,
                   7832:                        'helper'             => 1,
                   7833:          );
                   7834:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7835:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7836:                   $env{'request.course.sec'}))) {
                   7837:         %permission = (
                   7838:                        'set'                => 1,
                   7839:                        'settable'           => 1,
                   7840:                        'newoverview'        => 1,
                   7841:                        'setoverview'        => 1,
                   7842:                        'parameterchangelog' => 1,
                   7843:                       );
                   7844:     }
                   7845:     foreach my $perm (values(%permission)) {
                   7846:         if ($perm) { $allowed=1; last; }
                   7847:     }
                   7848:     return (\%permission,$allowed);
                   7849: }
                   7850: 
1.560     damieng  7851: ##################################################
                   7852: # HANDLER
                   7853: ##################################################
                   7854: 
                   7855: # Main handler for lonparmset.
                   7856: # Sub called based on request parameters action and command:
                   7857: # no command or action: print_main_menu
                   7858: # command 'set': assessparms (direct access to table mode for a resource)
                   7859: #                (this can also be accessed simply with the symb parameter)
                   7860: # action 'setoverview': overview (display all existing parameter settings)
                   7861: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7862: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7863: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7864: # action 'newoverview': newoverview (overview mode)
                   7865: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7866: # action 'settable': assessparms (table mode)
                   7867: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7868: #                              blog postings, user notification changes)
                   7869: # action 'cleanparameters': clean_parameters (unused)
                   7870: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7871: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7872: sub handler {
1.43      albertel 7873:     my $r=shift;
1.30      www      7874: 
1.376     albertel 7875:     &reset_caches();
                   7876: 
1.414     droeschl 7877:     &Apache::loncommon::content_type($r,'text/html');
                   7878:     $r->send_http_header;
                   7879:     return OK if $r->header_only;
                   7880: 
1.193     albertel 7881:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7882:                         ['action','state',
1.205     www      7883:                                              'pres_marker',
                   7884:                                              'pres_value',
1.206     www      7885:                                              'pres_type',
1.506     www      7886:                                              'filter','part',
1.390     www      7887:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7888: 
1.83      bowersj2 7889: 
1.193     albertel 7890:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7891:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7892:                         text=>"Content and Problem Settings",
1.473     amueller 7893:                         faq=>10,
                   7894:                         bug=>'Instructor Interface',
1.442     droeschl 7895:                                             help =>
                   7896:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7897: 
1.30      www      7898: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7899:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7900:     my $exists = &check_for_course_info();
                   7901: 
1.568     raeburn  7902:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7903:         #
                   7904:         # Main switch on form.action and form.state, as appropriate
                   7905:         #
                   7906:         # Check first if coming from someone else headed directly for
                   7907:         #  the table mode
1.568     raeburn  7908:         if (($parm_permission->{'set'}) && 
                   7909:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7910:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7911:             &assessparms($r,$parm_permission);
1.193     albertel 7912:         } elsif (! exists($env{'form.action'})) {
                   7913:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7914:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7915:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7916:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7917:             &overview($r,$parm_permission);
1.560     damieng  7918:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7919:             &addmetafield($r);
                   7920:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7921:             &order_meta_fields($r);
1.414     droeschl 7922:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7923:             &setrestrictmeta($r);
1.414     droeschl 7924:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7925:             &newoverview($r,$parm_permission);
1.414     droeschl 7926:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7927:             &defaultsetter($r);
                   7928:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7929:             &assessparms($r,$parm_permission);
1.414     droeschl 7930:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7931:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7932:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7933:             &clean_parameters($r);
1.414     droeschl 7934:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7935:             &date_shift_one($r);
1.414     droeschl 7936:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7937:             &date_shift_two($r);
1.446     bisitz   7938:         }
1.43      albertel 7939:     } else {
1.1       www      7940: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7941:         if ($exists) {
                   7942:             $env{'user.error.msg'}=
                   7943:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7944:         } else {
                   7945:             $env{'user.error.msg'}=
                   7946:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7947:         }
                   7948:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7949:     }
1.376     albertel 7950:     &reset_caches();
                   7951: 
1.43      albertel 7952:     return OK;
1.1       www      7953: }
                   7954: 
                   7955: 1;
                   7956: __END__
                   7957: 
                   7958: 

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