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

1.1       www         1: # The LearningOnline Network with CAPA
                      2: # Handler to set parameters for assessments
                      3: #
1.606   ! raeburn     4: # $Id: lonparmset.pm,v 1.605 2022/03/23 16:39:47 raeburn Exp $
1.40      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.59      matthew    28: ###################################################################
                     29: ###################################################################
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
                     35: lonparmset - Handler to set parameters for assessments and course
                     36: 
                     37: =head1 SYNOPSIS
                     38: 
1.579     raeburn    39: lonparmset provides an interface to setting content parameters in a 
                     40: course.
1.560     damieng    41: 
                     42: It contains all the code for the "Content and Problem Settings" UI, except
                     43: for the helpers parameter.helper and resettimes.helper, and lonhelper.pm,
                     44: and lonblockingmenu.pm.
1.59      matthew    45: 
                     46: =head1 DESCRIPTION
                     47: 
                     48: This module sets coursewide and assessment parameters.
                     49: 
                     50: =head1 INTERNAL SUBROUTINES
                     51: 
1.416     jms        52: =over
1.59      matthew    53: 
1.416     jms        54: =item parmval()
1.59      matthew    55: 
                     56: Figure out a cascading parameter.
                     57: 
1.71      albertel   58: Inputs:  $what - a parameter spec (incluse part info and name I.E. 0.weight)
1.162     albertel   59:          $id   - a bighash Id number
1.71      albertel   60:          $def  - the resource's default value   'stupid emacs
                     61: 
1.556     raeburn    62: Returns:  A list, the first item is the index into the remaining list of items of parm values that is the active one, the list consists of parm values at the 18 possible levels
1.71      albertel   63: 
1.556     raeburn    64: 18 - General Course
                     65: 17 - Map or Folder level in course (recursive) 
                     66: 16 - Map or Folder level in course (non-recursive)
                     67: 15 - resource default
                     68: 14 - map default
                     69: 13 - resource level in course
                     70: 12 - General for section
                     71: 11 - Map or Folder level for section (recursive)
                     72: 10 - Map or Folder level for section (non-recursive)
                     73: 9 - resource level in section
                     74: 8 - General for group
                     75: 7 - Map or Folder level for group (recursive)
                     76: 6 - Map or Folder level for group (non-recursive)
                     77: 5 - resource level in group
                     78: 4 - General for specific student
                     79: 3 - Map or Folder level for specific student (recursive)
                     80: 2 - Map or Folder level for specific student (non-recursive)
1.71      albertel   81: 1 - resource level for specific student
1.2       www        82: 
1.416     jms        83: =item parmval_by_symb()
                     84: 
                     85: =item reset_caches()
                     86: 
                     87: =item cacheparmhash() 
                     88: 
                     89: =item parmhash()
                     90: 
                     91: =item symbcache()
                     92: 
                     93: =item preset_defaults()
                     94: 
                     95: =item date_sanity_info()
                     96: 
                     97: =item storeparm()
                     98: 
                     99: Store a parameter by symb
                    100: 
                    101:     Takes
                    102:     - symb
                    103:     - name of parameter
                    104:     - level
                    105:     - new value
                    106:     - new type
                    107:     - username
                    108:     - userdomain
                    109: 
                    110: =item log_parmset()
                    111: 
                    112: =item storeparm_by_symb_inner()
                    113: 
                    114: =item valout()
                    115: 
                    116: Format a value for output.
                    117: 
                    118: Inputs:  $value, $type, $editable
                    119: 
                    120: Returns: $value, formatted for output.  If $type indicates it is a date,
                    121: localtime($value) is returned.
                    122: $editable will return an icon to click on
                    123: 
                    124: =item plink()
                    125: 
                    126: Produces a link anchor.
                    127: 
                    128: Inputs: $type,$dis,$value,$marker,$return,$call
                    129: 
                    130: Returns: scalar with html code for a link which will envoke the 
                    131: javascript function 'pjump'.
                    132: 
                    133: =item page_js()
                    134: 
                    135: =item startpage()
                    136: 
                    137: =item print_row()
                    138: 
                    139: =item print_td()
                    140: 
1.580     raeburn   141: =item check_other_groups()
1.416     jms       142: 
                    143: =item parm_control_group()
                    144: 
                    145: =item extractResourceInformation() : 
                    146: 
1.512     foxr      147:  extractResourceInformation extracts lots of information about all of the the course's resources into a variety of hashes.
1.416     jms       148: 
1.542     raeburn   149: Input: See list below
                    150: 
                    151: =over 4
1.416     jms       152: 
1.512     foxr      153: =item * B<env{'user.name'}> : Current username
1.416     jms       154: 
1.512     foxr      155: =item * B<env{'user.domain'}> : Domain of current user.
1.416     jms       156: 
1.542     raeburn   157: =item * B<env{"request.course.fn"}> : Course
                    158: 
                    159: =back
1.416     jms       160: 
1.512     foxr      161: Outputs: See list below:
1.416     jms       162: 
1.542     raeburn   163: =over 4
                    164: 
1.512     foxr      165: =item * B<ids> (out) : An array that will contain all of the ids in the course.
1.416     jms       166: 
1.512     foxr      167: =item * B<typep>(out) : hash, id->type, where "type" contains the extension of the file, thus, I<problem exam quiz assess survey form>.
1.416     jms       168: 
1.512     foxr      169: =item * B<keyp> (out) : hash, id->key list, will contain a comma separated list of the meta-data keys available for the given id
1.416     jms       170: 
1.512     foxr      171: =item * B<allparms> (out) : hash, name of parameter->display value (what is the display value?)
1.416     jms       172: 
1.512     foxr      173: =item * B<allparts> (out) : hash, part identification->text representation of part, where the text representation is "[Part $part]"
                    174: 
                    175: =item * B<allmaps> (out) : hash, ???
1.416     jms       176: 
                    177: =item * B<mapp> : ??
                    178: 
                    179: =item * B<symbp> : hash, id->full sym?
                    180: 
1.512     foxr      181: =item * B<maptitles>
                    182: 
                    183: =item * B<uris>
1.416     jms       184: 
1.512     foxr      185: =item * B<keyorder>
                    186: 
                    187: =item * B<defkeytype>
1.416     jms       188: 
1.542     raeburn   189: =back
                    190: 
1.416     jms       191: =item isdateparm()
                    192: 
                    193: =item parmmenu()
                    194: 
                    195: =item partmenu()
                    196: 
                    197: =item usermenu()
                    198: 
                    199: =item displaymenu()
                    200: 
                    201: =item mapmenu()
                    202: 
                    203: =item levelmenu()
                    204: 
                    205: =item sectionmenu()
                    206: 
                    207: =item keysplit()
                    208: 
                    209: =item keysinorder()
                    210: 
                    211: =item keysinorder_bytype()
                    212: 
                    213: =item keysindisplayorder()
                    214: 
                    215: =item standardkeyorder()
                    216: 
                    217: =item assessparms() : 
                    218: 
                    219: Show assessment data and parameters.  This is a large routine that should
                    220: be simplified and shortened... someday.
                    221: 
1.513     foxr      222: Inputs: $r - the Apache request object.
                    223:   
1.416     jms       224: Returns: nothing
                    225: 
                    226: Variables used (guessed by Jeremy):
                    227: 
1.542     raeburn   228: =over
                    229: 
1.416     jms       230: =item * B<pscat>: ParameterS CATegories? ends up a list of the types of parameters that exist, e.g., tol, weight, acc, opendate, duedate, answerdate, sig, maxtries, type.
                    231: 
                    232: =item * B<psprt>: ParameterS PaRTs? a list of the parts of a problem that we are displaying? Used to display only selected parts?
                    233: 
                    234: =item * B<@catmarker> contains list of all possible parameters including part #s
                    235: 
                    236: =item * B<$fullkeyp> contains the full part/id # for the extraction of proper parameters
                    237: 
                    238: =item * B<$tempkeyp> contains part 0 only (no ids - ie, subparts)
                    239:         When storing information, store as part 0
                    240:         When requesting information, request from full part
                    241: 
1.542     raeburn   242: =back
                    243: 
1.416     jms       244: =item tablestart()
                    245: 
                    246: =item tableend()
                    247: 
                    248: =item extractuser()
                    249: 
                    250: =item parse_listdata_key()
                    251: 
                    252: =item listdata()
                    253: 
                    254: =item date_interval_selector()
                    255: 
                    256: =item get_date_interval_from_form()
                    257: 
                    258: =item default_selector()
                    259: 
                    260: =item string_selector()
                    261: 
                    262: =item dateshift()
                    263: 
                    264: =item newoverview()
                    265: 
                    266: =item secgroup_lister()
                    267: 
                    268: =item overview()
                    269: 
                    270: =item clean_parameters()
                    271: 
                    272: =item date_shift_one()
                    273: 
                    274: =item date_shift_two()
                    275: 
                    276: =item parse_key()
                    277: 
                    278: =item header()
                    279: 
                    280: Output html header for page
                    281: 
                    282: =item print_main_menu()
                    283: 
                    284: =item output_row()
                    285: 
                    286: Set portfolio metadata
                    287: 
                    288: =item order_meta_fields()
                    289: 
                    290: =item addmetafield()
                    291: 
                    292: =item setrestrictmeta()
                    293: 
                    294: =item get_added_meta_fieldnames()
                    295: 
                    296: =item get_deleted_meta_fieldnames()
                    297: 
                    298: =item defaultsetter()
                    299: 
                    300: =item components()
                    301: 
                    302: =item load_parameter_names()
                    303: 
                    304: =item parm_change_log()
                    305: 
                    306: =item handler() : 
                    307: 
1.450     raeburn   308: Main handler.  Calls &assessparms subroutine.
1.416     jms       309: 
                    310: =back
                    311: 
1.59      matthew   312: =cut
                    313: 
1.416     jms       314: ###################################################################
                    315: ###################################################################
                    316: 
                    317: package Apache::lonparmset;
                    318: 
                    319: use strict;
                    320: use Apache::lonnet;
                    321: use Apache::Constants qw(:common :http REDIRECT);
                    322: use Apache::lonhtmlcommon();
                    323: use Apache::loncommon;
                    324: use GDBM_File;
                    325: use Apache::lonhomework;
                    326: use Apache::lonxml;
                    327: use Apache::lonlocal;
                    328: use Apache::lonnavmaps;
                    329: use Apache::longroup;
                    330: use Apache::lonrss;
1.506     www       331: use HTML::Entities;
1.416     jms       332: use LONCAPA qw(:DEFAULT :match);
                    333: 
                    334: 
1.560     damieng   335: ##################################################
                    336: # CONTENT AND PROBLEM SETTINGS HTML PAGE HEADER/FOOTER
                    337: ##################################################
                    338: 
                    339: # Page header
1.561     damieng   340: #
                    341: # @param {Apache2::RequestRec} $r - Apache request object
                    342: # @param {string} $mode - selected tab, 'parmset' for course and problem settings, or 'coursepref' for course settings
                    343: # @param {string} $crstype - course type ('Community' for community settings)
1.507     www       344: sub startSettingsScreen {
1.531     raeburn   345:     my ($r,$mode,$crstype)=@_;
1.507     www       346: 
1.531     raeburn   347:     my $tabtext = &mt('Course Settings');
                    348:     if ($crstype eq 'Community') {
                    349:         $tabtext = &mt('Community Settings');
                    350:     } 
1.507     www       351:     $r->print("\n".'<ul class="LC_TabContentBigger" id="main">');
                    352:     $r->print("\n".'<li'.($mode eq 'coursepref'?' class="active"':'').'><a href="/adm/courseprefs"><b>&nbsp;&nbsp;&nbsp;&nbsp;'.
1.531     raeburn   353:                                           $tabtext.
1.507     www       354:                                           '&nbsp;&nbsp;&nbsp;&nbsp;</b></a></li>');
                    355: 
1.523     raeburn   356:     $r->print("\n".'<li'.($mode eq 'parmset'?' class="active"':'').' id="tabbededitor"><a href="/adm/parmset"><b>'.
1.507     www       357:                                                                  &mt('Content and Problem Settings').'</b></a></li>');
                    358:     $r->print("\n".'</ul>'."\n");
1.523     raeburn   359:     $r->print('<div class="LC_Box" style="clear:both;margin:0;" id="parameditor"><div id="maincoursedoc" style="margin:0 0;padding:0 0;"><div class="LC_ContentBox" id="mainCourseDocuments" style="display: block;">');
1.507     www       360: }
                    361: 
1.560     damieng   362: # Page footer
1.507     www       363: sub endSettingsScreen {
                    364:    my ($r)=@_;
                    365:    $r->print('</div></div></div>');
                    366: }
                    367: 
                    368: 
                    369: 
1.560     damieng   370: ##################################################
1.563     damieng   371: # (mostly) TABLE MODE
1.560     damieng   372: # (parmval is also used for the log of parameter changes)
                    373: ##################################################
                    374: 
1.566     damieng   375: # Calls parmval_by_symb, getting the symb from $id with &symbcache.
1.561     damieng   376: #
                    377: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   378: # @param {string} $id - resource id or map pc
1.561     damieng   379: # @param {string} $def - the resource's default value for this parameter
                    380: # @param {string} $uname - user name
                    381: # @param {string} $udom - user domain
                    382: # @param {string} $csec - section name
                    383: # @param {string} $cgroup - group name
                    384: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    385: # @returns {Array}
1.2       www       386: sub parmval {
1.275     raeburn   387:     my ($what,$id,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
                    388:     return &parmval_by_symb($what,&symbcache($id),$def,$uname,$udom,$csec,
                    389:                                                            $cgroup,$courseopt);
1.201     www       390: }
                    391: 
1.561     damieng   392: # Returns an array containing
                    393: # - the most specific level that is defined for that parameter (integer)
                    394: # - an array with the level as index and the parameter value as value (when defined)
                    395: #   (level 1 is the most specific and will have precedence)
                    396: #
                    397: # @param {string} $what - part info and parameter name separated by a dot, e.g. '0.weight'
1.566     damieng   398: # @param {string} $symb - resource symb or map src
1.561     damieng   399: # @param {string} $def - the resource's default value for this parameter
                    400: # @param {string} $uname - user name
                    401: # @param {string} $udom - user domain
                    402: # @param {string} $csec - section name
                    403: # @param {string} $cgroup - group name
                    404: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
                    405: # @returns {Array}
1.201     www       406: sub parmval_by_symb {
1.275     raeburn   407:     my ($what,$symb,$def,$uname,$udom,$csec,$cgroup,$courseopt)=@_;
1.200     www       408: 
1.352     albertel  409:     my $useropt;
                    410:     if ($uname ne '' && $udom ne '') {
1.561     damieng   411:         $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
1.352     albertel  412:     }
1.200     www       413: 
1.8       www       414:     my $result='';
1.44      albertel  415:     my @outpar=();
1.2       www       416: # ----------------------------------------------------- Cascading lookup scheme
1.446     bisitz    417:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  418:     $map = &Apache::lonnet::deversion($map);
1.561     damieng   419:     
                    420:     # NOTE: some of that code looks redondant with code in lonnavmaps::parmval_real,
                    421:     # any change should be reflected there.
                    422:     
1.201     www       423:     my $symbparm=$symb.'.'.$what;
1.556     raeburn   424:     my $recurseparm=$map.'___(rec).'.$what; 
1.201     www       425:     my $mapparm=$map.'___(all).'.$what;
1.10      www       426: 
1.269     raeburn   427:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$what;
                    428:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   429:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   430:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    431: 
1.190     albertel  432:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$what;
                    433:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   434:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  435:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
                    436: 
                    437:     my $courselevel=$env{'request.course.id'}.'.'.$what;
                    438:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   439:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  440:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.2       www       441: 
1.11      www       442: 
1.182     albertel  443: # --------------------------------------------------------- first, check course
1.11      www       444: 
1.561     damieng   445: # 18 - General Course
1.200     www       446:     if (defined($$courseopt{$courselevel})) {
1.556     raeburn   447:         $outpar[18]=$$courseopt{$courselevel};
                    448:         $result=18;
                    449:     }
                    450: 
1.561     damieng   451: # 17 - Map or Folder level in course (recursive) 
1.556     raeburn   452:     if (defined($$courseopt{$courseleveli})) {
                    453:         $outpar[17]=$$courseopt{$courseleveli};
                    454:         $result=17;
1.43      albertel  455:     }
1.11      www       456: 
1.561     damieng   457: # 16 - Map or Folder level in course (non-recursive)
1.200     www       458:     if (defined($$courseopt{$courselevelm})) {
1.556     raeburn   459:         $outpar[16]=$$courseopt{$courselevelm};
                    460:         $result=16;
1.43      albertel  461:     }
1.11      www       462: 
1.182     albertel  463: # ------------------------------------------------------- second, check default
                    464: 
1.561     damieng   465: # 15 - resource default
1.556     raeburn   466:     if (defined($def)) { $outpar[15]=$def; $result=15; }
1.182     albertel  467: 
                    468: # ------------------------------------------------------ third, check map parms
                    469: 
1.556     raeburn   470:     
1.561     damieng   471: # 14 - map default
1.376     albertel  472:     my $thisparm=&parmhash($symbparm);
1.556     raeburn   473:     if (defined($thisparm)) { $outpar[14]=$thisparm; $result=14; }
1.182     albertel  474: 
1.561     damieng   475: # 13 - resource level in course
1.200     www       476:     if (defined($$courseopt{$courselevelr})) {
1.556     raeburn   477:         $outpar[13]=$$courseopt{$courselevelr};
                    478:         $result=13;
1.43      albertel  479:     }
1.11      www       480: 
1.182     albertel  481: # ------------------------------------------------------ fourth, back to course
1.352     albertel  482:     if ($csec ne '') {
1.561     damieng   483: # 12 - General for section
1.200     www       484:         if (defined($$courseopt{$seclevel})) {
1.556     raeburn   485:             $outpar[12]=$$courseopt{$seclevel};
                    486:             $result=12;
                    487:         }
1.561     damieng   488: # 11 - Map or Folder level for section (recursive)
1.556     raeburn   489:         if (defined($$courseopt{$secleveli})) {
                    490:             $outpar[11]=$$courseopt{$secleveli};
                    491:             $result=11;
                    492:         }
1.561     damieng   493: # 10 - Map or Folder level for section (non-recursive)
1.200     www       494:         if (defined($$courseopt{$seclevelm})) {
1.556     raeburn   495:             $outpar[10]=$$courseopt{$seclevelm};
                    496:             $result=10;
                    497:         }
1.561     damieng   498: # 9 - resource level in section
1.200     www       499:         if (defined($$courseopt{$seclevelr})) {
1.556     raeburn   500:             $outpar[9]=$$courseopt{$seclevelr};
                    501:             $result=9;
                    502:         }
1.43      albertel  503:     }
1.275     raeburn   504: # ------------------------------------------------------ fifth, check course group
1.352     albertel  505:     if ($cgroup ne '') {
1.561     damieng   506: # 8 - General for group
1.269     raeburn   507:         if (defined($$courseopt{$grplevel})) {
1.556     raeburn   508:             $outpar[8]=$$courseopt{$grplevel};
                    509:             $result=8;
                    510:         }
1.561     damieng   511: # 7 - Map or Folder level for group (recursive)
1.556     raeburn   512:         if (defined($$courseopt{$grpleveli})) {
                    513:             $outpar[7]=$$courseopt{$grpleveli};
                    514:             $result=7;
1.269     raeburn   515:         }
1.561     damieng   516: # 6 - Map or Folder level for group (non-recursive)
1.269     raeburn   517:         if (defined($$courseopt{$grplevelm})) {
1.556     raeburn   518:             $outpar[6]=$$courseopt{$grplevelm};
                    519:             $result=6;
1.269     raeburn   520:         }
1.561     damieng   521: # 5 - resource level in group
1.269     raeburn   522:         if (defined($$courseopt{$grplevelr})) {
1.556     raeburn   523:             $outpar[5]=$$courseopt{$grplevelr};
                    524:             $result=5;
1.269     raeburn   525:         }
                    526:     }
1.11      www       527: 
1.556     raeburn   528: # ---------------------------------------------------------- sixth, check user
1.11      www       529: 
1.352     albertel  530:     if ($uname ne '') {
1.561     damieng   531: # 4 - General for specific student
                    532:         if (defined($$useropt{$courselevel})) {
                    533:             $outpar[4]=$$useropt{$courselevel};
                    534:             $result=4;
                    535:         }
1.556     raeburn   536: 
1.561     damieng   537: # 3 - Map or Folder level for specific student (recursive)
                    538:         if (defined($$useropt{$courseleveli})) {
                    539:             $outpar[3]=$$useropt{$courseleveli};
                    540:             $result=3;
                    541:         }
1.473     amueller  542: 
1.561     damieng   543: # 2 - Map or Folder level for specific student (non-recursive)
                    544:         if (defined($$useropt{$courselevelm})) {
                    545:             $outpar[2]=$$useropt{$courselevelm};
                    546:             $result=2;
                    547:         }
1.473     amueller  548: 
1.561     damieng   549: # 1 - resource level for specific student
                    550:         if (defined($$useropt{$courselevelr})) {
                    551:             $outpar[1]=$$useropt{$courselevelr};
                    552:             $result=1;
                    553:         }
1.43      albertel  554:     }
1.44      albertel  555:     return ($result,@outpar);
1.2       www       556: }
                    557: 
1.198     www       558: 
                    559: 
1.376     albertel  560: # --- Caches local to lonparmset
                    561: 
1.446     bisitz    562: 
1.561     damieng   563: # Reset lonparmset caches (called at the beginning and end of the handler).
1.376     albertel  564: sub reset_caches {
                    565:     &resetparmhash();
                    566:     &resetsymbcache();
                    567:     &resetrulescache();
1.203     www       568: }
                    569: 
1.561     damieng   570: # cache for map parameters, stored temporarily in $env{'request.course.fn'}_parms.db
                    571: # (these parameters come from param elements in .sequence files created with the advanced RAT)
1.376     albertel  572: {
1.561     damieng   573:     my $parmhashid; # course identifier, to initialize the cache only once for a course
                    574:     my %parmhash; # the parameter cache
                    575:     # reset map parameter hash
1.376     albertel  576:     sub resetparmhash {
1.560     damieng   577:         undef($parmhashid);
                    578:         undef(%parmhash);
1.376     albertel  579:     }
1.446     bisitz    580: 
1.561     damieng   581:     # dump the _parms.db database into %parmhash
1.376     albertel  582:     sub cacheparmhash {
1.560     damieng   583:         if ($parmhashid eq  $env{'request.course.fn'}) { return; }
                    584:         my %parmhashfile;
                    585:         if (tie(%parmhashfile,'GDBM_File',
                    586:             $env{'request.course.fn'}.'_parms.db',&GDBM_READER(),0640)) {
                    587:             %parmhash=%parmhashfile;
                    588:             untie(%parmhashfile);
                    589:             $parmhashid=$env{'request.course.fn'};
                    590:         }
1.201     www       591:     }
1.446     bisitz    592: 
1.561     damieng   593:     # returns a parameter value for an identifier symb.parts.parameter, using the map parameter cache
1.376     albertel  594:     sub parmhash {
1.560     damieng   595:         my ($id) = @_;
                    596:         &cacheparmhash();
                    597:         return $parmhash{$id};
1.376     albertel  598:     }
1.560     damieng   599: }
1.376     albertel  600: 
1.566     damieng   601: # cache resource id or map pc -> resource symb or map src, using lonnavmaps to find association
1.446     bisitz    602: {
1.561     damieng   603:     my $symbsid; # course identifier, to initialize the cache only once for a course
                    604:     my %symbs; # hash id->symb
                    605:     # reset the id->symb cache
1.376     albertel  606:     sub resetsymbcache {
1.560     damieng   607:         undef($symbsid);
                    608:         undef(%symbs);
1.376     albertel  609:     }
1.446     bisitz    610: 
1.566     damieng   611:     # returns the resource symb or map src corresponding to a resource id or map pc
                    612:     # (using lonnavmaps and a cache)
1.376     albertel  613:     sub symbcache {
1.560     damieng   614:         my $id=shift;
                    615:         if ($symbsid ne $env{'request.course.id'}) {
                    616:             undef(%symbs);
                    617:         }
                    618:         if (!$symbs{$id}) {
                    619:             my $navmap = Apache::lonnavmaps::navmap->new();
                    620:             if ($id=~/\./) {
                    621:                 my $resource=$navmap->getById($id);
                    622:                 $symbs{$id}=$resource->symb();
                    623:             } else {
                    624:                 my $resource=$navmap->getByMapPc($id);
                    625:                 $symbs{$id}=&Apache::lonnet::declutter($resource->src());
                    626:             }
                    627:             $symbsid=$env{'request.course.id'};
1.473     amueller  628:         }
1.560     damieng   629:         return $symbs{$id};
1.473     amueller  630:     }
1.560     damieng   631: }
1.201     www       632: 
1.561     damieng   633: # cache for parameter default actions (stored in parmdefactions.db)
1.446     bisitz    634: {
1.561     damieng   635:     my $rulesid; # course identifier, to initialize the cache only once for a course
                    636:     my %rules; # parameter default actions hash
1.376     albertel  637:     sub resetrulescache {
1.560     damieng   638:         undef($rulesid);
                    639:         undef(%rules);
1.376     albertel  640:     }
1.446     bisitz    641: 
1.561     damieng   642:     # returns the value for a given key in the parameter default action hash
1.376     albertel  643:     sub rulescache {
1.560     damieng   644:         my $id=shift;
                    645:         if ($rulesid ne $env{'request.course.id'}
                    646:             && !defined($rules{$id})) {
                    647:             my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    648:             my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                    649:             %rules=&Apache::lonnet::dump('parmdefactions',$dom,$crs);
                    650:             $rulesid=$env{'request.course.id'};
                    651:         }
                    652:         return $rules{$id};
1.221     www       653:     }
                    654: }
                    655: 
1.416     jms       656: 
1.561     damieng   657: # Returns the values of the parameter type default action
                    658: # "default value when manually setting".
                    659: # If none is defined, ('','','','','') is returned.
                    660: #
                    661: # @param {string} $type - parameter type
                    662: # @returns {Array<string>} - (hours, min, sec, value)
1.229     www       663: sub preset_defaults {
                    664:     my $type=shift;
                    665:     if (&rulescache($type.'_action') eq 'default') {
1.560     damieng   666:         # yes, there is something
                    667:         return (&rulescache($type.'_hours'),
                    668:             &rulescache($type.'_min'),
                    669:             &rulescache($type.'_sec'),
                    670:             &rulescache($type.'_value'));
1.229     www       671:     } else {
1.560     damieng   672:         # nothing there or something else
                    673:         return ('','','','','');
1.229     www       674:     }
                    675: }
                    676: 
1.416     jms       677: 
1.561     damieng   678: # Checks that a date is after enrollment start date and before
                    679: # enrollment end date.
                    680: # Returns HTML with a warning if it is not, or the empty string otherwise.
                    681: # This is used by both overview and table modes.
                    682: #
                    683: # @param {integer} $checkdate - the date to check.
                    684: # @returns {string} - HTML possibly containing a localized warning message.
1.277     www       685: sub date_sanity_info {
                    686:    my $checkdate=shift;
                    687:    unless ($checkdate) { return ''; }
                    688:    my $result='';
                    689:    my $crsprefix='course.'.$env{'request.course.id'}.'.';
                    690:    if ($env{$crsprefix.'default_enrollment_end_date'}) {
                    691:       if ($checkdate>$env{$crsprefix.'default_enrollment_end_date'}) {
1.413     bisitz    692:          $result.='<div class="LC_warning">'
                    693:                  .&mt('After course enrollment end!')
                    694:                  .'</div>';
1.277     www       695:       }
                    696:    }
                    697:    if ($env{$crsprefix.'default_enrollment_start_date'}) {
                    698:       if ($checkdate<$env{$crsprefix.'default_enrollment_start_date'}) {
1.413     bisitz    699:          $result.='<div class="LC_warning">'
                    700:                  .&mt('Before course enrollment start!')
                    701:                  .'</div>';
1.277     www       702:       }
                    703:    }
1.413     bisitz    704: # Preparation for additional warnings about dates in the past/future.
                    705: # An improved, more context sensitive version is recommended,
                    706: # e.g. warn for due and answer dates which are defined before the corresponding open date, etc.
                    707: #   if ($checkdate<time) {
                    708: #      $result.='<div class="LC_info">'
                    709: #              .'('.&mt('in the past').')'
                    710: #              .'</div>';
                    711: #      }
                    712: #   if ($checkdate>time) {
                    713: #      $result.='<div class="LC_info">'
                    714: #              .'('.&mt('in the future').')'
                    715: #              .'</div>';
                    716: #      }
1.277     www       717:    return $result;
                    718: }
1.561     damieng   719: 
                    720: 
                    721: # Store a parameter value and type by ID, also triggering more parameter changes based on parameter default actions.
1.186     www       722: #
1.566     damieng   723: # @param {string} $sresid - resource id or map pc
1.565     damieng   724: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   725: # @param {integer} $snum - level
                    726: # @param {string} $nval - new value
                    727: # @param {string} $ntype - new type
                    728: # @param {string} $uname - username
                    729: # @param {string} $udom - userdomain
                    730: # @param {string} $csec - section name
                    731: # @param {string} $cgroup - group name
1.186     www       732: sub storeparm {
1.269     raeburn   733:     my ($sresid,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.275     raeburn   734:     &storeparm_by_symb(&symbcache($sresid),$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,'',$cgroup);
1.197     www       735: }
                    736: 
1.561     damieng   737: my %recstack; # hash parameter name -> 1 when a parameter was used before in a recursive call to storeparm_by_symb
                    738: 
                    739: # Store a parameter value and type by symb, also triggering more parameter changes based on parameter default actions.
                    740: # Uses storeparm_by_symb_inner to actually store the parameter, ignoring any returned error.
                    741: #
1.566     damieng   742: # @param {string} $symb - resource symb or map src
1.565     damieng   743: # @param {string} $spnam - part info and parameter name separated by a dot or underscore, e.g. '0.weight'
1.561     damieng   744: # @param {integer} $snum - level
                    745: # @param {string} $nval - new value
                    746: # @param {string} $ntype - new type
                    747: # @param {string} $uname - username
                    748: # @param {string} $udom - userdomain
                    749: # @param {string} $csec - section name
                    750: # @param {boolean} $recflag - should be true for recursive calls to storeparm_by_symb, false otherwise
                    751: # @param {string} $cgroup - group name
1.197     www       752: sub storeparm_by_symb {
1.275     raeburn   753:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$recflag,$cgroup)=@_;
1.226     www       754:     unless ($recflag) {
1.560     damieng   755:         # first time call
                    756:         %recstack=();
                    757:         $recflag=1;
1.226     www       758:     }
1.560     damieng   759:     # store parameter
1.226     www       760:     &storeparm_by_symb_inner
1.473     amueller  761:     ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup);
1.560     damieng   762:     # don't do anything if parameter was reset
1.266     www       763:     unless ($nval) { return; }
1.226     www       764:     my ($prefix,$parm)=($spnam=~/^(.*[\_\.])([^\_\.]+)$/);
1.560     damieng   765:     # remember that this was set
1.226     www       766:     $recstack{$parm}=1;
1.560     damieng   767:     # what does this trigger?
1.226     www       768:     foreach my $triggered (split(/\:/,&rulescache($parm.'_triggers'))) {
1.560     damieng   769:         # don't backfire
                    770:         unless ((!$triggered) || ($recstack{$triggered})) {
                    771:             my $action=&rulescache($triggered.'_action');
                    772:             my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                    773:             # set triggered parameter on same level
                    774:             my $newspnam=$prefix.$triggered;
                    775:             my $newvalue='';
                    776:             my $active=1;
                    777:             if ($action=~/^when\_setting/) {
                    778:             # are there restrictions?
                    779:                 if (&rulescache($triggered.'_triggervalue')=~/\w/) {
                    780:                     $active=0;
1.565     damieng   781:                     foreach my $possiblevalue (split(/\s*\,\s*/,&rulescache($triggered.'_triggervalue'))) {
1.560     damieng   782:                         if (lc($possiblevalue) eq lc($nval)) { $active=1; }
                    783:                     }
                    784:                 }
                    785:                 $newvalue=&rulescache($triggered.'_value');
                    786:             } else {
                    787:                 my $totalsecs=((&rulescache($triggered.'_days')*24+&rulescache($triggered.'_hours'))*60+&rulescache($triggered.'_min'))*60+&rulescache($triggered.'_sec');
                    788:                 if ($action=~/^later\_than/) {
                    789:                     $newvalue=$nval+$totalsecs;
                    790:                 } else {
                    791:                     $newvalue=$nval-$totalsecs;
                    792:                 }
                    793:             }
                    794:             if ($active) {
                    795:                 &storeparm_by_symb($symb,$newspnam,$snum,$newvalue,&rulescache($triggered.'_type'),
                    796:                         $uname,$udom,$csec,$recflag,$cgroup);
                    797:             }
                    798:         }
1.226     www       799:     }
                    800:     return '';
                    801: }
                    802: 
1.561     damieng   803: # Adds all given arguments to the course parameter log.
                    804: # @returns {string} - the answer to the lonnet query.
1.293     www       805: sub log_parmset {
1.525     raeburn   806:     return &Apache::lonnet::write_log('course','parameterlog',@_);
1.284     www       807: }
                    808: 
1.561     damieng   809: # Store a parameter value and type by symb, without using the parameter default actions.
                    810: # Expire related sheets.
                    811: #
1.566     damieng   812: # @param {string} $symb - resource symb or map src
1.561     damieng   813: # @param {string} $spnam - part info and parameter name separated by a dot, e.g. '0.weight'
                    814: # @param {integer} $snum - level
                    815: # @param {string} $nval - new value
                    816: # @param {string} $ntype - new type
                    817: # @param {string} $uname - username
                    818: # @param {string} $udom - userdomain
                    819: # @param {string} $csec - section name
                    820: # @param {string} $cgroup - group name
                    821: # @returns {string} - HTML code with an error message if the parameter could not be stored.
1.226     www       822: sub storeparm_by_symb_inner {
1.197     www       823: # ---------------------------------------------------------- Get symb, map, etc
1.269     raeburn   824:     my ($symb,$spnam,$snum,$nval,$ntype,$uname,$udom,$csec,$cgroup)=@_;
1.197     www       825: # ---------------------------------------------------------- Construct prefixes
1.186     www       826:     $spnam=~s/\_([^\_]+)$/\.$1/;
1.446     bisitz    827:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.305     albertel  828:     $map = &Apache::lonnet::deversion($map);
                    829: 
1.197     www       830:     my $symbparm=$symb.'.'.$spnam;
1.556     raeburn   831:     my $recurseparm=$map.'___(rec).'.$spnam;
1.197     www       832:     my $mapparm=$map.'___(all).'.$spnam;
                    833: 
1.269     raeburn   834:     my $grplevel=$env{'request.course.id'}.'.['.$cgroup.'].'.$spnam;
                    835:     my $grplevelr=$env{'request.course.id'}.'.['.$cgroup.'].'.$symbparm;
1.556     raeburn   836:     my $grpleveli=$env{'request.course.id'}.'.['.$cgroup.'].'.$recurseparm;
1.269     raeburn   837:     my $grplevelm=$env{'request.course.id'}.'.['.$cgroup.'].'.$mapparm;
                    838: 
1.190     albertel  839:     my $seclevel=$env{'request.course.id'}.'.['.$csec.'].'.$spnam;
                    840:     my $seclevelr=$env{'request.course.id'}.'.['.$csec.'].'.$symbparm;
1.556     raeburn   841:     my $secleveli=$env{'request.course.id'}.'.['.$csec.'].'.$recurseparm;
1.190     albertel  842:     my $seclevelm=$env{'request.course.id'}.'.['.$csec.'].'.$mapparm;
1.446     bisitz    843: 
1.190     albertel  844:     my $courselevel=$env{'request.course.id'}.'.'.$spnam;
                    845:     my $courselevelr=$env{'request.course.id'}.'.'.$symbparm;
1.556     raeburn   846:     my $courseleveli=$env{'request.course.id'}.'.'.$recurseparm;
1.190     albertel  847:     my $courselevelm=$env{'request.course.id'}.'.'.$mapparm;
1.446     bisitz    848: 
1.186     www       849:     my $storeunder='';
1.578     raeburn   850:     my $possreplace='';
1.556     raeburn   851:     if (($snum==18) || ($snum==4)) { $storeunder=$courselevel; }
1.578     raeburn   852:     if (($snum==17) || ($snum==3)) { 
                    853:         $storeunder=$courseleveli;
                    854:         $possreplace=$courselevelm; 
                    855:     } 
                    856:     if (($snum==16) || ($snum==2)) { 
                    857:         $storeunder=$courselevelm;
                    858:         $possreplace=$courseleveli;
                    859:     }
1.556     raeburn   860:     if (($snum==13) || ($snum==1)) { $storeunder=$courselevelr; }
                    861:     if ($snum==12) { $storeunder=$seclevel; }
1.578     raeburn   862:     if ($snum==11) { 
                    863:         $storeunder=$secleveli;
                    864:         $possreplace=$seclevelm; 
                    865:     }
                    866:     if ($snum==10) { 
                    867:         $storeunder=$seclevelm;
                    868:         $possreplace=$secleveli;
                    869:     }
1.556     raeburn   870:     if ($snum==9) { $storeunder=$seclevelr; }
                    871:     if ($snum==8) { $storeunder=$grplevel; }
1.578     raeburn   872:     if ($snum==7) { 
                    873:         $storeunder=$grpleveli;
                    874:         $possreplace=$grplevelm;
                    875:     }
                    876:     if ($snum==6) {
                    877:         $storeunder=$grplevelm;
                    878:         $possreplace=$grpleveli;
                    879:     }
1.556     raeburn   880:     if ($snum==5) { $storeunder=$grplevelr; }
1.269     raeburn   881: 
1.446     bisitz    882: 
1.186     www       883:     my $delete;
                    884:     if ($nval eq '') { $delete=1;}
                    885:     my %storecontent = ($storeunder         => $nval,
1.473     amueller  886:             $storeunder.'.type' => $ntype);
1.186     www       887:     my $reply='';
1.560     damieng   888:     
1.556     raeburn   889:     if ($snum>4) {
1.186     www       890: # ---------------------------------------------------------------- Store Course
                    891: #
1.560     damieng   892:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                    893:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                    894:         # Expire sheets
                    895:         &Apache::lonnet::expirespread('','','studentcalc');
                    896:         if (($snum==13) || ($snum==9) || ($snum==5)) {
                    897:             &Apache::lonnet::expirespread('','','assesscalc',$symb);
1.578     raeburn   898:         } elsif (($snum==17) || ($snum==16) || ($snum==11) || ($snum==10) || ($snum==7) || ($snum==6)) {
1.560     damieng   899:             &Apache::lonnet::expirespread('','','assesscalc',$map);
                    900:         } else {
                    901:             &Apache::lonnet::expirespread('','','assesscalc');
                    902:         }
                    903:         # Store parameter
                    904:         if ($delete) {
                    905:             $reply=&Apache::lonnet::del
                    906:             ('resourcedata',[keys(%storecontent)],$cdom,$cnum);
                    907:                 &log_parmset(\%storecontent,1);
                    908:         } else {
                    909:             $reply=&Apache::lonnet::cput
                    910:             ('resourcedata',\%storecontent,$cdom,$cnum);
                    911:             &log_parmset(\%storecontent);
1.578     raeburn   912:             if ($possreplace) {
                    913:                 my $resdata = &Apache::lonnet::get_courseresdata($cnum,$cdom);
                    914:                 if (ref($resdata) eq 'HASH') {
                    915:                     if (exists($resdata->{$possreplace})) {
                    916:                         if (&Apache::lonnet::del
                    917:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$cdom,$cnum) eq 'ok') {
                    918:                             &log_parmset({$possreplace => '', $possreplace.'.type' => $ntype},1);   
                    919:                         }
                    920:                     }
                    921:                 }
                    922:             }
1.560     damieng   923:         }
                    924:         &Apache::lonnet::devalidatecourseresdata($cnum,$cdom);
1.186     www       925:     } else {
                    926: # ------------------------------------------------------------------ Store User
                    927: #
1.560     damieng   928:         # Expire sheets
                    929:         &Apache::lonnet::expirespread($uname,$udom,'studentcalc');
                    930:         if ($snum==1) {
                    931:             &Apache::lonnet::expirespread
                    932:             ($uname,$udom,'assesscalc',$symb);
1.578     raeburn   933:         } elsif (($snum==2) || ($snum==3)) {
1.560     damieng   934:             &Apache::lonnet::expirespread
                    935:             ($uname,$udom,'assesscalc',$map);
                    936:         } else {
                    937:             &Apache::lonnet::expirespread($uname,$udom,'assesscalc');
                    938:         }
                    939:         # Store parameter
                    940:         if ($delete) {
                    941:             $reply=&Apache::lonnet::del
                    942:             ('resourcedata',[keys(%storecontent)],$udom,$uname);
                    943:             &log_parmset(\%storecontent,1,$uname,$udom);
                    944:         } else {
                    945:             $reply=&Apache::lonnet::cput
                    946:             ('resourcedata',\%storecontent,$udom,$uname);
                    947:             &log_parmset(\%storecontent,0,$uname,$udom);
1.578     raeburn   948:             if ($possreplace) {
                    949:                 my $resdata = &Apache::lonnet::get_userresdata($uname,$udom);
                    950:                 if (ref($resdata) eq 'HASH') {
                    951:                     if (exists($resdata->{$possreplace})) {
                    952:                         if (&Apache::lonnet::del
                    953:                             ('resourcedata',[$possreplace,$possreplace.'.type'],$udom,$uname) eq 'ok') {
                    954:                             &log_parmset({$possreplace => '',$possreplace.'.type' => $ntype},1,
                    955:                                           $uname,$udom);
                    956:                         }
                    957:                     }
                    958:                 }
                    959:             }
1.560     damieng   960:         }
                    961:         &Apache::lonnet::devalidateuserresdata($uname,$udom);
1.186     www       962:     }
1.446     bisitz    963: 
1.186     www       964:     if ($reply=~/^error\:(.*)/) {
1.560     damieng   965:         return "<span class=\"LC_error\">Write Error: $1</span>";
1.186     www       966:     }
                    967:     return '';
                    968: }
                    969: 
1.9       www       970: 
1.561     damieng   971: # Returns HTML with the value of the given parameter,
                    972: # using a readable format for dates, and
                    973: # a warning if there is a problem with a date.
                    974: # Used by table mode.
                    975: # Returns HTML for the editmap.png image if no value is defined and $editable is true.
                    976: #
                    977: # @param {string} $value - the parameter value
                    978: # @param {string} $type - the parameter type
                    979: # @param {boolean} $editable - Set to true to get an icon when no value is defined.
1.9       www       980: sub valout {
1.600     raeburn   981:     my ($value,$type,$editable)=@_;
1.59      matthew   982:     my $result = '';
                    983:     # Values of zero are valid.
                    984:     if (! $value && $value ne '0') {
1.528     bisitz    985:         if ($editable) {
                    986:             $result =
                    987:                 '<img src="/res/adm/pages/editmap.png"'
                    988:                .' alt="'.&mt('Change').'"'
1.539     raeburn   989:                .' title="'.&mt('Change').'" style="border:0;" />';
1.528     bisitz    990:         } else {
                    991:             $result='&nbsp;';
                    992:         }
1.59      matthew   993:     } else {
1.66      www       994:         if ($type eq 'date_interval') {
1.559     raeburn   995:             my ($totalsecs,$donesuffix) = split(/_/,$value,2);
                    996:             my ($usesdone,$donebuttontext,$proctor,$secretkey);
                    997:             if ($donesuffix =~ /^done\:([^\:]+)\:(.*)$/) {
                    998:                 $donebuttontext = $1;
                    999:                 (undef,$proctor,$secretkey) = split(/_/,$2);
                   1000:                 $usesdone = 'done';
                   1001:             } elsif ($donesuffix =~ /^done(|_.+)$/) {
                   1002:                 $donebuttontext = &mt('Done');
                   1003:                 ($usesdone,$proctor,$secretkey) = split(/_/,$donesuffix);
                   1004:             }
1.554     raeburn  1005:             my ($sec,$min,$hour,$mday,$mon,$year)=gmtime($totalsecs);
1.413     bisitz   1006:             my @timer;
1.66      www      1007:             $year=$year-70;
                   1008:             $mday--;
                   1009:             if ($year) {
1.413     bisitz   1010: #               $result.=&mt('[quant,_1,yr]',$year).' ';
                   1011:                 push(@timer,&mt('[quant,_1,yr]',$year));
1.66      www      1012:             }
                   1013:             if ($mon) {
1.413     bisitz   1014: #               $result.=&mt('[quant,_1,mth]',$mon).' ';
                   1015:                 push(@timer,&mt('[quant,_1,mth]',$mon));
1.66      www      1016:             }
                   1017:             if ($mday) {
1.413     bisitz   1018: #               $result.=&mt('[quant,_1,day]',$mday).' ';
                   1019:                 push(@timer,&mt('[quant,_1,day]',$mday));
1.66      www      1020:             }
                   1021:             if ($hour) {
1.413     bisitz   1022: #               $result.=&mt('[quant,_1,hr]',$hour).' ';
                   1023:                 push(@timer,&mt('[quant,_1,hr]',$hour));
1.66      www      1024:             }
                   1025:             if ($min) {
1.413     bisitz   1026: #               $result.=&mt('[quant,_1,min]',$min).' ';
                   1027:                 push(@timer,&mt('[quant,_1,min]',$min));
1.66      www      1028:             }
                   1029:             if ($sec) {
1.413     bisitz   1030: #               $result.=&mt('[quant,_1,sec]',$sec).' ';
                   1031:                 push(@timer,&mt('[quant,_1,sec]',$sec));
1.66      www      1032:             }
1.413     bisitz   1033: #           $result=~s/\s+$//;
                   1034:             if (!@timer) { # Special case: all entries 0 -> display "0 secs" intead of empty field to keep this field editable
                   1035:                 push(@timer,&mt('[quant,_1,sec]',0));
                   1036:             }
                   1037:             $result.=join(", ",@timer);
1.559     raeburn  1038:             if ($usesdone eq 'done') {
1.558     raeburn  1039:                 if ($secretkey) {
1.559     raeburn  1040:                     $result .= ' '.&mt('+ "[_1]" with proctor key: [_2]',$donebuttontext,$secretkey);  
1.558     raeburn  1041:                 } else {
1.559     raeburn  1042:                     $result .= ' + "'.$donebuttontext.'"';
                   1043:                 }
1.554     raeburn  1044:             }
1.213     www      1045:         } elsif (&isdateparm($type)) {
1.361     albertel 1046:             $result = &Apache::lonlocal::locallocaltime($value).
1.560     damieng  1047:                 &date_sanity_info($value);
1.59      matthew  1048:         } else {
                   1049:             $result = $value;
1.517     www      1050:             $result=~s/\,/\, /gs;
1.560     damieng  1051:             $result = &HTML::Entities::encode($result,'"<>&');
1.59      matthew  1052:         }
                   1053:     }
                   1054:     return $result;
1.9       www      1055: }
                   1056: 
1.59      matthew  1057: 
1.561     damieng  1058: # Returns HTML containing a link on a parameter value, for table mode.
                   1059: # The link uses the javascript function 'pjump'.
                   1060: #
                   1061: # @param {string} $type - parameter type
                   1062: # @param {string} $dis - dialog title for editing the parameter value and type
                   1063: # @param {string} $value - parameter value
                   1064: # @param {string} $marker - identifier for the parameter, "resource id&part_parameter name&level", will be passed as pres_marker when the user submits a change.
                   1065: # @param {string} $return - prefix for the name of the form and field names that will be used to submit the form ('parmform.pres')
                   1066: # @param {string} $call - javascript function to call to submit the form ('psub')
1.588     raeburn  1067: # @param {boolean} $recursive - true if link is for a map/folder where parameter is currently set to be recursive.
                   1068: # @param {string} $extra - optional additional information to send as tenth arg in call to javascript pjump function.
1.5       www      1069: sub plink {
1.588     raeburn  1070:     my ($type,$dis,$value,$marker,$return,$call,$recursive,$extra)=@_;
1.23      www      1071:     my $winvalue=$value;
                   1072:     unless ($winvalue) {
1.592     raeburn  1073:         if (&isdateparm($type) || (&is_specialstring($type))) {
1.190     albertel 1074:             $winvalue=$env{'form.recent_'.$type};
1.591     raeburn  1075:         } elsif ($type eq 'string_yesno') {
                   1076:             if ($env{'form.recent_string'} =~ /^(yes|no)$/i) {
                   1077:                 $winvalue=$env{'form.recent_string'};
                   1078:             }
1.23      www      1079:         } else {
1.190     albertel 1080:             $winvalue=$env{'form.recent_'.(split(/\_/,$type))[0]};
1.23      www      1081:         }
                   1082:     }
1.229     www      1083:     my ($parmname)=((split(/\&/,$marker))[1]=~/\_([^\_]+)$/);
                   1084:     my ($hour,$min,$sec,$val)=&preset_defaults($parmname);
                   1085:     unless (defined($winvalue)) { $winvalue=$val; }
1.593     raeburn  1086:     my $valout = &valout($value,$type,1);
1.429     raeburn  1087:     my $unencmarker = $marker;
1.378     albertel 1088:     foreach my $item (\$type, \$dis, \$winvalue, \$marker, \$return, \$call,
1.588     raeburn  1089:               \$hour, \$min, \$sec, \$extra) {
1.560     damieng  1090:         $$item = &HTML::Entities::encode($$item,'"<>&');
                   1091:         $$item =~ s/\'/\\\'/g;
1.378     albertel 1092:     }
1.429     raeburn  1093:     return '<table width="100%"><tr valign="top" align="right"><td><a name="'.$unencmarker.'" /></td></tr><tr><td align="center">'.
1.473     amueller 1094:     '<a href="javascript:pjump('."'".$type."','".$dis."','".$winvalue."','"
1.588     raeburn  1095:         .$marker."','".$return."','".$call."','".$hour."','".$min."','".$sec."','".$extra."'".');">'.
1.578     raeburn  1096:         $valout.'</a></td></tr>'.($recursive?'<tr><td align="center" class="LC_parm_recursive">'.
                   1097:                                               &mt('recursive').'</td></tr>' : '').'</table>';
                   1098: 
1.5       www      1099: }
                   1100: 
1.561     damieng  1101: # Javascript for table mode.
1.280     albertel 1102: sub page_js {
                   1103: 
1.81      www      1104:     my $selscript=&Apache::loncommon::studentbrowser_javascript();
1.88      matthew  1105:     my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
1.280     albertel 1106: 
                   1107:     return(<<ENDJS);
                   1108: <script type="text/javascript">
1.454     bisitz   1109: // <![CDATA[
1.44      albertel 1110: 
1.88      matthew  1111:     $pjump_def
1.44      albertel 1112: 
                   1113:     function psub() {
1.591     raeburn  1114:         var specstring = /^string_!(yesno|any)/i;
1.44      albertel 1115:         if (document.parmform.pres_marker.value!='') {
                   1116:             document.parmform.action+='#'+document.parmform.pres_marker.value;
                   1117:             var typedef=new Array();
                   1118:             typedef=document.parmform.pres_type.value.split('_');
1.562     damieng  1119:             if (document.parmform.pres_type.value!='') {
1.589     raeburn  1120:                 if ((typedef[0]=='date') || 
1.591     raeburn  1121:                     (specstring.test(document.parmform.pres_type.value)))  {
1.562     damieng  1122:                     eval('document.parmform.recent_'+
                   1123:                         document.parmform.pres_type.value+
                   1124:                         '.value=document.parmform.pres_value.value;');
                   1125:                 } else {
                   1126:                     eval('document.parmform.recent_'+typedef[0]+
                   1127:                         '.value=document.parmform.pres_value.value;');
                   1128:                 }
1.44      albertel 1129:             }
                   1130:             document.parmform.submit();
                   1131:         } else {
                   1132:             document.parmform.pres_value.value='';
                   1133:             document.parmform.pres_marker.value='';
                   1134:         }
                   1135:     }
                   1136: 
1.57      albertel 1137:     function openWindow(url, wdwName, w, h, toolbar,scrollbar) {
                   1138:         var options = "width=" + w + ",height=" + h + ",";
                   1139:         options += "resizable=yes,scrollbars="+scrollbar+",status=no,";
                   1140:         options += "menubar=no,toolbar="+toolbar+",location=no,directories=no";
                   1141:         var newWin = window.open(url, wdwName, options);
                   1142:         newWin.focus();
                   1143:     }
1.523     raeburn  1144: 
1.454     bisitz   1145: // ]]>
1.523     raeburn  1146: 
1.44      albertel 1147: </script>
1.81      www      1148: $selscript
1.280     albertel 1149: ENDJS
                   1150: 
                   1151: }
1.507     www      1152: 
1.561     damieng  1153: # Javascript to show or hide the map selection (function showHide_courseContent),
                   1154: # for table and overview modes.
1.523     raeburn  1155: sub showhide_js {
                   1156:     return <<"COURSECONTENTSCRIPT";
                   1157: 
                   1158: function showHide_courseContent() {
                   1159:     var parmlevValue=document.getElementById("parmlev").value;
                   1160:     if (parmlevValue == 'general') {
                   1161:         document.getElementById('mapmenu').style.display="none";
                   1162:     } else {
                   1163:         if ((parmlevValue == "full") || (parmlevValue == "map")) {
                   1164:             document.getElementById('mapmenu').style.display ="";
                   1165:         } else {
                   1166:             document.getElementById('mapmenu').style.display="none";
                   1167:         }
                   1168:     }
                   1169:     return;
                   1170: }
                   1171: 
                   1172: COURSECONTENTSCRIPT
                   1173: }
                   1174: 
1.561     damieng  1175: # Javascript functions showHideLenient and toggleParmTextbox, for overview mode
1.549     raeburn  1176: sub toggleparmtextbox_js {
                   1177:     return <<"ENDSCRIPT";
                   1178: 
                   1179: if (!document.getElementsByClassName) {
                   1180:     function getElementsByClassName(node, classname) {
                   1181:         var a = [];
                   1182:         var re = new RegExp('(^| )'+classname+'( |$)');
                   1183:         var els = node.getElementsByTagName("*");
                   1184:         for(var i=0,j=els.length; i<j; i++)
                   1185:             if(re.test(els[i].className))a.push(els[i]);
                   1186:         return a;
                   1187:     }
                   1188: }
                   1189: 
                   1190: function showHideLenient() {
                   1191:     var lenients;
                   1192:     var setRegExp = /^set_/;
                   1193:     if (document.getElementsByClassName) {
                   1194:         lenients = document.getElementsByClassName('LC_lenient_radio');
                   1195:     } else {
                   1196:         lenients = getElementsByClassName(document.body,'LC_lenient_radio');
                   1197:     }
                   1198:     if (lenients != 'undefined') {
                   1199:         for (var i=0; i<lenients.length; i++) {
                   1200:             if (lenients[i].checked) {
                   1201:                 if (lenients[i].value == 'weighted') {
                   1202:                     if (setRegExp.test(lenients[i].name)) {
                   1203:                         var identifier = lenients[i].name.replace(setRegExp,'');
                   1204:                         toggleParmTextbox(document.parmform,identifier);
                   1205:                     }
                   1206:                 }
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     return;
                   1211: }
                   1212: 
                   1213: function toggleParmTextbox(form,key) {
                   1214:     var divfortext = document.getElementById('LC_parmtext_'+key);
                   1215:     if (divfortext) {
                   1216:         var caller = form.elements['set_'+key];
                   1217:         if (caller.length) {
                   1218:             for (i=0; i<caller.length; i++) {
                   1219:                 if (caller[i].checked) {
                   1220:                     if (caller[i].value == 'weighted') {
                   1221:                         divfortext.style.display = 'inline';
                   1222:                     } else {
                   1223:                         divfortext.style.display = 'none';
                   1224:                     }
                   1225:                 }
                   1226:             }
                   1227:         }
                   1228:     }
                   1229:     return;
                   1230: }
                   1231: 
                   1232: ENDSCRIPT
                   1233: }
                   1234: 
1.561     damieng  1235: # Javascript function validateParms, for overview mode
1.549     raeburn  1236: sub validateparms_js {
                   1237:     return <<'ENDSCRIPT';
                   1238: 
                   1239: function validateParms() {
                   1240:     var textRegExp = /^settext_/;
                   1241:     var tailLenient = /\.lenient$/;
                   1242:     var patternRelWeight = /^\-?[\d.]+$/;
                   1243:     var patternLenientStd = /^(yes|no|default)$/;
1.597     raeburn  1244:     var ipRegExp = /^setip/;
1.549     raeburn  1245:     var ipallowRegExp = /^setipallow_/;
                   1246:     var ipdenyRegExp = /^setipdeny_/; 
1.597     raeburn  1247:     var deeplinkRegExp = /^deeplink_/;
1.601     raeburn  1248:     var dlListScopeRegExp = /^deeplink_(state|others|listing|scope)_/; 
                   1249:     var dlLinkProtectRegExp = /^deeplink_protect_/;
                   1250:     var dlLtidRegExp = /^deeplink_ltid_/;
                   1251:     var dlLticRegExp = /^deeplink_ltic_/;
1.597     raeburn  1252:     var dlKeyRegExp = /^deeplink_key_/;
                   1253:     var dlMenusRegExp = /^deeplink_menus_/;
                   1254:     var dlCollsRegExp = /^deeplink_colls_/;
1.549     raeburn  1255:     var patternIP = /[\[\]\*\.a-zA-Z\d\-]+/;
                   1256:     if ((document.parmform.elements.length != 'undefined')  && (document.parmform.elements.length) != 'null') {
                   1257:         if (document.parmform.elements.length) {
                   1258:             for (i=0; i<document.parmform.elements.length; i++) {
                   1259:                 var name=document.parmform.elements[i].name;
1.588     raeburn  1260:                 if (textRegExp.test(name)) {
1.549     raeburn  1261:                     var identifier = name.replace(textRegExp,'');
                   1262:                     if (tailLenient.test(identifier)) {
                   1263:                         if (document.parmform.elements['set_'+identifier].length) {
                   1264:                             for (var j=0; j<document.parmform.elements['set_'+identifier].length; j++) {
                   1265:                                 if (document.parmform.elements['set_'+identifier][j].checked) {
                   1266:                                     if (!(patternLenientStd.test(document.parmform.elements['set_'+identifier][j].value))) {
                   1267:                                         var relweight = document.parmform.elements[i].value;
                   1268:                                         relweight = relweight.replace(/^\s+|\s+$/g,'');
                   1269:                                         if (!patternRelWeight.test(relweight)) {
                   1270:                                             relweight = '0.0';
                   1271:                                         }
                   1272:                                         if (document.parmform.elements['set_'+identifier][j].value == 'weighted') {
                   1273:                                             document.parmform.elements['set_'+identifier][j].value = relweight;
                   1274:                                         } else {
                   1275:                                             document.parmform.elements['set_'+identifier][j].value += ','+relweight;
                   1276:                                         }
                   1277:                                     }
                   1278:                                     break;
                   1279:                                 }
                   1280:                             }
                   1281:                         }
                   1282:                     }
1.597     raeburn  1283:                 } else if (ipRegExp.test(name)) {
                   1284:                     if (ipallowRegExp.test(name)) {
                   1285:                         var identifier = name.replace(ipallowRegExp,'');
                   1286:                         var possallow = document.parmform.elements[i].value;
                   1287:                         possallow = possallow.replace(/^\s+|\s+$/g,'');
                   1288:                         if (patternIP.test(possallow)) {
                   1289:                             if (document.parmform.elements['set_'+identifier].value) {
                   1290:                                 possallow = ','+possallow;
                   1291:                             }
                   1292:                             document.parmform.elements['set_'+identifier].value += possallow;
                   1293:                         }
                   1294:                     } else if (ipdenyRegExp.test(name)) {
                   1295:                         var identifier = name.replace(ipdenyRegExp,'');
                   1296:                         var possdeny = document.parmform.elements[i].value;
                   1297:                         possdeny = possdeny.replace(/^\s+|\s+$/g,'');
                   1298:                         if (patternIP.test(possdeny)) {
                   1299:                             possdeny = '!'+possdeny;
                   1300:                             if (document.parmform.elements['set_'+identifier].value) {
                   1301:                                 possdeny = ','+possdeny;
                   1302:                             }
                   1303:                             document.parmform.elements['set_'+identifier].value += possdeny;
1.588     raeburn  1304:                         }
                   1305:                     }
                   1306:                 } else if (deeplinkRegExp.test(name)) {
1.597     raeburn  1307:                     if (dlListScopeRegExp.test(name)) {
                   1308:                         var identifier =  name.replace(dlListScopeRegExp,'');
                   1309:                         var idx = document.parmform.elements[i].selectedIndex;
                   1310:                         if (idx > 0) { 
                   1311:                             var possdeeplink = document.parmform.elements[i].options[idx].value
                   1312:                             possdeeplink = possdeeplink.replace(/^\s+|\s+$/g,'');
                   1313:                             if (document.parmform.elements['set_'+identifier].value) {
                   1314:                                 possdeeplink = ','+possdeeplink;
                   1315:                             }
                   1316:                             document.parmform.elements['set_'+identifier].value += possdeeplink;
                   1317:                         }
1.601     raeburn  1318:                     } else if (dlLinkProtectRegExp.test(name)) {
1.597     raeburn  1319:                         if (document.parmform.elements[i].checked) {
1.601     raeburn  1320:                             var identifier =  name.replace(dlLinkProtectRegExp,'');
1.597     raeburn  1321:                             var posslinkurl = document.parmform.elements[i].value;
                   1322:                             posslinkurl = posslinkurl.replace(/^\s+|\s+$/g,'');
                   1323:                             if (document.parmform.elements['set_'+identifier].value) {
                   1324:                                 posslinkurl = ','+posslinkurl;
                   1325:                             }
                   1326:                             document.parmform.elements['set_'+identifier].value += posslinkurl;
                   1327:                         }
1.601     raeburn  1328:                     } else if (dlLtidRegExp.test(name)) {
                   1329:                         var identifier = name.replace(dlLtidRegExp,'');
                   1330:                         if (isRadioSet('deeplink_protect_'+identifier,'ltid')) {
                   1331:                             var possltid = document.parmform.elements[i].value;
                   1332:                             possltid = possltid.replace(/\D+/g,'');
                   1333:                             if (possltid.length) {
1.597     raeburn  1334:                                 if (document.parmform.elements['set_'+identifier].value) {
1.601     raeburn  1335:                                     possltid = ':'+possltid;
1.597     raeburn  1336:                                 }
1.601     raeburn  1337:                                 document.parmform.elements['set_'+identifier].value += possltid;
1.597     raeburn  1338:                             } else {
                   1339:                                 document.parmform.elements['set_'+identifier].value = '';
1.601     raeburn  1340:                                 alert("A link type of 'domain LTI launch' was selected but no domain LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
1.597     raeburn  1341:                                 return false;  
                   1342:                             }
                   1343:                         }
1.601     raeburn  1344:                     } else if (dlLticRegExp.test(name)) {
                   1345:                         var identifier = name.replace(dlLticRegExp,'');
                   1346:                         if (isRadioSet('deeplink_protect_'+identifier,'ltic')) {
                   1347:                             var possltic = document.parmform.elements[i].value;
                   1348:                             possltic = possltic.replace(/\D+/g,'');
                   1349:                             if (possltic.length) {
                   1350:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1351:                                     possltic = ':'+possltic;
                   1352:                                 }
                   1353:                                 document.parmform.elements['set_'+identifier].value += possltic;
                   1354:                             } else {
                   1355:                                 document.parmform.elements['set_'+identifier].value = '';
                   1356:                                 alert("A link type of 'course LTI launch' was selected but no course LTI launcher was selected.\nPlease select one, or choose a different supported link type.");
                   1357:                                 return false;
                   1358:                             }
                   1359:                         }
1.597     raeburn  1360:                     } else if (dlKeyRegExp.test(name)) {
                   1361:                         var identifier = name.replace(dlKeyRegExp,'');
1.601     raeburn  1362:                         if (isRadioSet('deeplink_protect_'+identifier,'key')) {
1.597     raeburn  1363:                             var posskey = document.parmform.elements[i].value;
                   1364:                             posskey = posskey.replace(/^\s+|\s+$/g,'');
                   1365:                             var origlength = posskey.length;
                   1366:                             posskey = posskey.replace(/[^a-zA-Z\d_.!@#$%^&*()+=-]/g,'');
                   1367:                             var newlength = posskey.length;
                   1368:                             if (newlength > 0) {
                   1369:                                 var change = origlength - newlength;
                   1370:                                 if (change) {
                   1371:                                     alert(change+' disallowed character(s) removed from deeplink key'); 
                   1372:                                 }
                   1373:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1374:                                     posskey = ':'+posskey;
                   1375:                                 }
                   1376:                                 document.parmform.elements['set_'+identifier].value += posskey;
                   1377:                             } else {
                   1378:                                 document.parmform.elements['set_'+identifier].value = '';
                   1379:                                 if (newlength < origlength) {
                   1380:                                     alert("A link type of 'deep with key' was selected but the key value was blank, after removing disallowed characters.\nPlease enter a key using one or more of: a-zA-Z0-9_.!@#$%^&*()+=-");
                   1381:                                 } else {
                   1382:                                     alert("A link type of 'deep with key' was selected but the key value was blank.\nPlease enter a key.");
                   1383:                                 }
                   1384:                                 return false;
                   1385:                             }
                   1386:                         }
                   1387:                     } else if (dlMenusRegExp.test(name)) {
                   1388:                         if (document.parmform.elements[i].checked) {
                   1389:                             var identifier =  name.replace(dlMenusRegExp,'');
                   1390:                             var posslinkmenu = document.parmform.elements[i].value;
                   1391:                             posslinkmenu = posslinkmenu.replace(/^\s+|\s+$/g,'');
                   1392:                             if (posslinkmenu == 'std') {
                   1393:                                 posslinkmenu = '0';
                   1394:                                 if (document.parmform.elements['set_'+identifier].value) {
                   1395:                                     posslinkmenu = ','+posslinkmenu;
                   1396:                                 }
                   1397:                                 document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1398:                             }
                   1399:                         }
                   1400:                     } else if (dlCollsRegExp.test(name)) {
                   1401:                         var identifier =  name.replace(dlCollsRegExp,'');
                   1402:                         if (isRadioSet('deeplink_menus_'+identifier,'colls')) {
                   1403:                             var posslinkmenu = document.parmform.elements[i].value;
                   1404:                             if (document.parmform.elements['set_'+identifier].value) {
                   1405:                                 posslinkmenu = ','+posslinkmenu;
                   1406:                             }
                   1407:                             document.parmform.elements['set_'+identifier].value += posslinkmenu;
                   1408:                         }
1.549     raeburn  1409:                     }
                   1410:                 }
                   1411:             }
                   1412:         }
                   1413:     }
                   1414:     return true;
                   1415: }
                   1416: 
1.597     raeburn  1417: function isRadioSet(name,expected) {
                   1418:     var menuitems = document.getElementsByName(name);
                   1419:     var radioLength = menuitems.length;
                   1420:     result = false;
                   1421:     if (radioLength  > 1) {
                   1422:         for (var j=0; j<radioLength; j++) {
                   1423:             if (menuitems[j].checked) {
                   1424:                 if (menuitems[j].value == expected) {
                   1425:                     result = true;
                   1426:                     break;
                   1427:                 }
                   1428:             }
                   1429:         }
                   1430:     }
                   1431:     return result;
                   1432: }
                   1433: 
1.549     raeburn  1434: ENDSCRIPT
                   1435: }
                   1436: 
1.561     damieng  1437: # Javascript initialization, for overview mode
1.549     raeburn  1438: sub ipacc_boxes_js  {
                   1439:     my $remove = &mt('Remove');
                   1440:     return <<"END";
                   1441: \$(document).ready(function() {
                   1442:     var wrapper         = \$(".LC_string_ipacc_wrap");
                   1443:     var add_button      = \$(".LC_add_ipacc_button");
                   1444:     var ipaccRegExp     = /^LC_string_ipacc_/;
                   1445: 
                   1446:     \$(add_button).click(function(e){
                   1447:         e.preventDefault();
                   1448:         var identifier = \$(this).closest("div").attr("id");
                   1449:         identifier = identifier.replace(ipaccRegExp,'');
1.551     raeburn  1450:         \$(this).closest('div').find('.LC_string_ipacc_inner').append('<div><input type="text" name="setip'+identifier+'" /><a href="#" class="LC_remove_ipacc">$remove</a></div>');
1.549     raeburn  1451:     });
                   1452: 
                   1453:     \$(wrapper).delegate(".LC_remove_ipacc","click", function(e){
                   1454:         e.preventDefault(); \$(this).closest("div").remove();
                   1455:     })
                   1456: });
                   1457: 
                   1458: 
                   1459: END
                   1460: }
                   1461: 
1.561     damieng  1462: # Javascript function toggleSecret, for overview mode.
1.558     raeburn  1463: sub done_proctor_js {
                   1464:     return <<"END";
                   1465: function toggleSecret(form,radio,key) {
                   1466:     var radios = form[radio+key];
                   1467:     if (radios.length) {
                   1468:         for (var i=0; i<radios.length; i++) {
                   1469:             if (radios[i].checked) {
                   1470:                 if (radios[i].value == '_done_proctor') {
                   1471:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1472:                         document.getElementById('done_'+key+'_proctorkey').type='text';
                   1473:                     }
                   1474:                 } else {
                   1475:                     if (document.getElementById('done_'+key+'_proctorkey')) {
                   1476:                         document.getElementById('done_'+key+'_proctorkey').type='hidden';
                   1477:                         document.getElementById('done_'+key+'_proctorkey').value='';
                   1478:                     }
                   1479:                 }
                   1480:             }
                   1481:         }
                   1482:     }
                   1483: }
                   1484: END
                   1485: 
                   1486: }
                   1487: 
1.588     raeburn  1488: # Javascript function toggle
                   1489: sub deeplink_js {
                   1490:     return <<"END";
                   1491: function toggleDeepLink(form,item,key) {
                   1492:     var radios = form['deeplink_'+item+'_'+key];
                   1493:     if (radios.length) {
                   1494:         var keybox;
                   1495:         if (document.getElementById('deeplink_key_'+item+'_'+key)) {
                   1496:             keybox = document.getElementById('deeplink_key_'+item+'_'+key);
                   1497:         }
1.601     raeburn  1498:         var divoptions = new Array();
                   1499:         if (item == 'protect') {
                   1500:             divoptions = ['ltic','ltid'];
1.597     raeburn  1501:         } else {
                   1502:             if (item == 'menus') {
1.601     raeburn  1503:                 divoptions = ['colls'];
1.597     raeburn  1504:             }
                   1505:         }
1.601     raeburn  1506:         var seldivs = new Array();
                   1507:         if ((item == 'protect') || (item == 'menus')) {
                   1508:             for (var i=0; i<divoptions.length; i++) {
                   1509:                 if (document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key)) {
                   1510:                     seldivs[i] = document.getElementById('deeplinkdiv_'+divoptions[i]+'_'+item+'_'+key);
                   1511:                 } else {
                   1512:                     seldivs[i] = '';
                   1513:                 }
                   1514:             }
1.588     raeburn  1515:         }
                   1516:         for (var i=0; i<radios.length; i++) {
                   1517:             if (radios[i].checked) {
1.601     raeburn  1518:                 if ((item == 'protect') || (item == 'menus')) {
                   1519:                     for (var j=0; j<seldivs.length; j++) {
                   1520:                         if (radios[i].value == divoptions[j]) {
                   1521:                             if (seldivs[j] != '') {
                   1522:                                 seldivs[j].style.display = 'inline-block';
                   1523:                             }
                   1524:                             if (item == 'protect') {
                   1525:                                 keybox.type = 'hidden';
                   1526:                                 keybox.value = '';
                   1527:                             }
                   1528:                         } else {
                   1529:                             if (seldivs[j] != '') {
                   1530:                                 seldivs[j].style.display = 'none';
                   1531:                                 form['deeplink_'+divoptions[j]+'_'+key].selectedIndex = 0;
                   1532:                             }
                   1533:                         }
1.597     raeburn  1534:                     }
1.601     raeburn  1535:                     if (item == 'protect') {
1.597     raeburn  1536:                         if (radios[i].value == 'key') {
                   1537:                             keybox.type = 'text';
                   1538:                         } else {
                   1539:                             keybox.type = 'hidden';
                   1540:                         }
1.588     raeburn  1541:                     }
                   1542:                 }
                   1543:             }
                   1544:         }
                   1545:     }
                   1546: }
                   1547: END
                   1548: 
                   1549: }
                   1550: 
1.561     damieng  1551: # Prints HTML page start for table mode.
                   1552: # @param {Apache2::RequestRec} $r - the Apache request
                   1553: # @param {string} $psymb - resource symb
                   1554: # @param {string} $crstype - course type (Community / Course / Placement Test)
1.280     albertel 1555: sub startpage {
1.531     raeburn  1556:     my ($r,$psymb,$crstype) = @_;
1.281     albertel 1557: 
1.515     raeburn  1558:     my %loaditems = (
                   1559:                       'onload'   => "group_or_section('cgroup')",
                   1560:                     );
                   1561:     if (!$psymb) {
1.523     raeburn  1562:         $loaditems{'onload'} = "showHide_courseContent(); group_or_section('cgroup'); resize_scrollbox('mapmenuscroll','1','1');";
1.515     raeburn  1563:     }
1.280     albertel 1564: 
1.560     damieng  1565:     if ((($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   1566:             (!$env{'form.dis'})) || ($env{'form.symb'})) {
                   1567:         &Apache::lonhtmlcommon::add_breadcrumb({help=>'Problem_Parameters',
                   1568:             text=>"Problem Parameters"});
1.414     droeschl 1569:     } else {
1.560     damieng  1570:         &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
                   1571:             text=>"Table Mode",
                   1572:             help => 'Course_Setting_Parameters'});
1.414     droeschl 1573:     }
1.523     raeburn  1574:     my $js = &page_js().'
                   1575: <script type="text/javascript">
                   1576: // <![CDATA[
                   1577: '.
                   1578:             &Apache::lonhtmlcommon::resize_scrollbox_js('params').'
                   1579: // ]]>
                   1580: </script>
                   1581: ';
1.446     bisitz   1582:     my $start_page =
1.523     raeburn  1583:         &Apache::loncommon::start_page('Set/Modify Course Parameters',$js,
                   1584:                                        {'add_entries' => \%loaditems,});
1.446     bisitz   1585:     my $breadcrumbs =
1.473     amueller 1586:     &Apache::lonhtmlcommon::breadcrumbs('Table Mode Parameter Setting','Table_Mode');
1.506     www      1587:     my $escfilter=&Apache::lonhtmlcommon::entity_encode($env{'form.filter'});
                   1588:     my $escpart=&Apache::lonhtmlcommon::entity_encode($env{'form.part'});
1.507     www      1589:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  1590:     &startSettingsScreen($r,'parmset',$crstype);
1.280     albertel 1591:     $r->print(<<ENDHEAD);
1.193     albertel 1592: <form method="post" action="/adm/parmset?action=settable" name="parmform">
1.419     bisitz   1593: <input type="hidden" value="" name="pres_value" />
                   1594: <input type="hidden" value="" name="pres_type" />
                   1595: <input type="hidden" value="" name="pres_marker" />
                   1596: <input type="hidden" value="1" name="prevvisit" />
1.506     www      1597: <input type="hidden" value="$escfilter" name="filter" />
                   1598: <input type="hidden" value="$escpart" name="part" />
1.44      albertel 1599: ENDHEAD
                   1600: }
                   1601: 
1.209     www      1602: 
1.561     damieng  1603: # Prints a row for table mode (except for the tr start).
                   1604: # Every time a hash reference is passed, a single entry is used, so print_row
                   1605: # could just use these values, but why make it simple when it can be complicated ?
                   1606: #
                   1607: # @param {Apache2::RequestRec} $r - the Apache request
                   1608: # @param {string} $which - parameter key ('parameter_'.part.'_'.name)
                   1609: # @param {hash reference} $part - parameter key -> parameter part (can be problem part.'_'.response id for response parameters)
                   1610: # @param {hash reference} $name - parameter key -> parameter name
1.566     damieng  1611: # @param {hash reference} $symbp - map pc or resource/map id -> map src.'___(all)' or resource symb
1.561     damieng  1612: # @param {string} $rid - resource id
                   1613: # @param {hash reference} $default - parameter key -> resource parameter default value
                   1614: # @param {hash reference} $defaulttype - parameter key -> resource parameter default type
                   1615: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1616: # @param {string} $defbgone - user level and other levels background color
                   1617: # @param {string} $defbgtwo - section level background color, also used for part number
                   1618: # @param {string} $defbgthree - group level background color
                   1619: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   1620: # @param {string} $uname - user name
                   1621: # @param {string} $udom - user domain
                   1622: # @param {string} $csec - section name
                   1623: # @param {string} $cgroup - group name
                   1624: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1625: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.582     raeburn  1626: # @param {boolean} $readonly - true if no editing allowed.
                   1627: # @param {array reference} - $recurseup - list of maps containing current one, ending at top-level.
                   1628: # @param {hash reference} - $maptitles - - hash map id or src -> map title 
                   1629: # @param {hash reference} - $allmaps_inverted - hash map src -> map pc
                   1630: # @param {scalar reference} - $reclinks - number of "parameter in effect" cells with link to map where recursive param was set 
1.44      albertel 1631: sub print_row {
1.201     www      1632:     my ($r,$which,$part,$name,$symbp,$rid,$default,$defaulttype,$display,$defbgone,
1.568     raeburn  1633:     $defbgtwo,$defbgthree,$parmlev,$uname,$udom,$csec,$cgroup,$usersgroups,$noeditgrp,
1.582     raeburn  1634:     $readonly,$recurseup,$maptitles,$allmaps_inverted,$reclinks)=@_;
1.275     raeburn  1635:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   1636:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   1637:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.582     raeburn  1638:     my $numlinks = 0;
1.553     raeburn  1639: 
1.560     damieng  1640:     # get the values for the parameter in cascading order
                   1641:     # empty levels will remain empty
1.44      albertel 1642:     my ($result,@outpar)=&parmval($$part{$which}.'.'.$$name{$which},
1.473     amueller 1643:       $rid,$$default{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1644:     # get the type for the parameters
                   1645:     # problem: these may not be set for all levels
1.66      www      1646:     my ($typeresult,@typeoutpar)=&parmval($$part{$which}.'.'.
1.275     raeburn  1647:                                           $$name{$which}.'.type',$rid,
1.473     amueller 1648:          $$defaulttype{$which},$uname,$udom,$csec,$cgroup,$courseopt);
1.560     damieng  1649:     # cascade down manually
1.182     albertel 1650:     my $cascadetype=$$defaulttype{$which};
1.556     raeburn  1651:     for (my $i=18;$i>0;$i--) {
1.560     damieng  1652:         if ($typeoutpar[$i]) {
1.66      www      1653:             $cascadetype=$typeoutpar[$i];
1.560     damieng  1654:         } else {
1.66      www      1655:             $typeoutpar[$i]=$cascadetype;
                   1656:         }
                   1657:     }
1.57      albertel 1658:     my $parm=$$display{$which};
                   1659: 
1.203     www      1660:     if ($parmlev eq 'full') {
1.419     bisitz   1661:         $r->print('<td style="background-color:'.$defbgtwo.';" align="center">'
1.506     www      1662:                   .($$part{$which} eq '0'?'0 ('.&mt('default').')':$$part{$which}).'</td>');
1.433     raeburn  1663:     } else {
1.57      albertel 1664:         $parm=~s|\[.*\]\s||g;
                   1665:     }
1.231     www      1666:     my $automatic=&rulescache(($which=~/\_([^\_]+)$/)[0].'_triggers');
                   1667:     if ($automatic) {
1.560     damieng  1668:         $parm.='<span class="LC_warning"><br />'.&mt('Automatically sets').' '.join(', ',split(/\:/,$automatic)).'</span>';
1.231     www      1669:     }
1.427     bisitz   1670:     $r->print('<td>'.$parm.'</td>');
1.446     bisitz   1671: 
1.44      albertel 1672:     my $thismarker=$which;
                   1673:     $thismarker=~s/^parameter\_//;
                   1674:     my $mprefix=$rid.'&'.$thismarker.'&';
1.582     raeburn  1675:     my ($parmname)=($thismarker=~/\_([^\_]+)$/);
                   1676:     my ($othergrp,$grp_parm,$controlgrp,$effective_parm,$effparm_rec,$effparm_level,
1.588     raeburn  1677:         $eff_groupparm,$recurse_check,$recursinfo,$extra);
1.582     raeburn  1678:     if ((ref($recurseup) eq 'ARRAY') && (@{$recurseup} > 0)) {
                   1679:         if ($result eq '') {
                   1680:             $recurse_check = 1;
                   1681:         } elsif (($uname ne '') && ($result > 3)) {
                   1682:             $recurse_check = 1;
                   1683:         } elsif (($cgroup ne '') && ($result > 7)) {
                   1684:             $recurse_check = 1;
                   1685:         } elsif (($csec ne '') && ($result > 11)) {
                   1686:             $recurse_check = 1;
                   1687:         } elsif ($result > 17) {
                   1688:             $recurse_check = 1;
                   1689:         }
                   1690:         if ($recurse_check) {
                   1691:             my $what = $$part{$which}.'.'.$$name{$which};
                   1692:             my $prefix;
                   1693:             if (($uname ne '') && ($udom ne '')) {
                   1694:                 my $useropt = &Apache::lonnet::get_userresdata($uname,$udom);
                   1695:                 $prefix = $env{'request.course.id'};
                   1696:                 $recursinfo = &get_recursive($recurseup,$useropt,$what,$prefix);
                   1697:                 if (ref($recursinfo) eq 'ARRAY') {
                   1698:                     $effparm_rec = 1;
                   1699:                     $effparm_level = &mt('user: [_1]',$uname);
                   1700:                 }
                   1701:             }
                   1702:             if (($cgroup ne '') && (!$effparm_rec)) {
                   1703:                 $prefix = $env{'request.course.id'}.'.['.$cgroup.']';
                   1704:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1705:                 if (ref($recursinfo) eq 'ARRAY') {
                   1706:                     $effparm_rec = 1;
                   1707:                     $effparm_level = &mt('group: [_1]',$cgroup);
                   1708:                 }
                   1709:             }
                   1710:             if (($csec ne '') && (!$effparm_rec)) {
                   1711:                 $prefix = $env{'request.course.id'}.'.['.$csec.']';
                   1712:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix);
                   1713:                 if (ref($recursinfo) eq 'ARRAY') {
                   1714:                     $effparm_rec = 1;
                   1715:                     $effparm_level = &mt('section: [_1]',$csec);
                   1716:                 }
                   1717:             }
                   1718:             if (!$effparm_rec) {
                   1719:                 $prefix = $env{'request.course.id'};
                   1720:                 $recursinfo = &get_recursive($recurseup,$courseopt,$what,$prefix); 
                   1721:                 if (ref($recursinfo) eq 'ARRAY') {
                   1722:                     $effparm_rec = 1;
                   1723:                 }
                   1724:             }
                   1725:         }
                   1726:     }
                   1727:     if ((!$effparm_rec) && ($result == 17 || $result == 11 || $result == 7 || $result == 3)) {
                   1728:         $effparm_rec = 1;
                   1729:     }
                   1730:     if ((!$effparm_rec) && 
                   1731:         (($$name{$which} eq 'encrypturl') || ($$name{$which} eq 'hiddenresource')) && 
                   1732:         ($result == 16 || $result == 10 || $result == 6 || $result == 2)) {
1.578     raeburn  1733:         $effparm_rec = 1;
                   1734:     }
1.588     raeburn  1735:     if ($parmname eq 'deeplink') {
1.601     raeburn  1736:         my ($domltistr,$crsltistr);
1.588     raeburn  1737:         my %lti =
                   1738:             &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  1739:                                             'linkprot');
1.601     raeburn  1740:         if (keys(%lti)) {
                   1741:             foreach my $item (sort { $a <=> $b }  (keys(%lti))) {
1.604     raeburn  1742:                 if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   1743:                     $domltistr .= $item.':'.&escape(&escape($lti{$item}{'name'})).',';
1.588     raeburn  1744:                 }
                   1745:             }
1.601     raeburn  1746:             $domltistr =~ s/,$//;
                   1747:             if ($domltistr) {
                   1748:                 $extra = 'ltid_'.$domltistr;
                   1749:             }
1.588     raeburn  1750:         }
1.601     raeburn  1751:         my %courselti = &Apache::lonnet::get_course_lti($cnum,$cdom);
                   1752:         if (keys(%courselti)) {
                   1753:             foreach my $item (sort { $a <=> $b } keys(%courselti)) {
                   1754:                 if (($item =~ /^\d+$/) && (ref($courselti{$item}) eq 'HASH')) {
                   1755:                     $crsltistr .= $item.':'.&escape(&escape($courselti{$item}{'name'})).',';
                   1756:                 }
                   1757:             }
                   1758:             $crsltistr =~ s/,$//;
                   1759:             if ($crsltistr) {
                   1760:                 if ($extra) {
                   1761:                     $extra .= '&';
                   1762:                 }
                   1763:                 $extra .= 'ltic_'.$crsltistr;
1.588     raeburn  1764:             }
                   1765:         }
1.597     raeburn  1766:         if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   1767:             my @colls;
                   1768:             foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   1769:                 my ($num,$value) = split(/\%/,$item);
                   1770:                 if ($num =~ /^\d+$/) {
                   1771:                     push(@colls,$num);
                   1772:                 }
                   1773:             }
                   1774:             if (@colls) {
                   1775:                 if ($extra) {
                   1776:                     $extra .= '&';
                   1777:                 }
                   1778:                 $extra .= 'menus_'.join(',',@colls);
                   1779:             }
                   1780:         }
1.588     raeburn  1781:     }
1.57      albertel 1782:     if ($parmlev eq 'general') {
                   1783:         if ($uname) {
1.588     raeburn  1784:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.269     raeburn  1785:         } elsif ($cgroup) {
1.588     raeburn  1786:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
1.57      albertel 1787:         } elsif ($csec) {
1.588     raeburn  1788:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1789:         } else {
1.588     raeburn  1790:             &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.57      albertel 1791:         }
                   1792:     } elsif ($parmlev eq 'map') {
                   1793:         if ($uname) {
1.588     raeburn  1794:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.269     raeburn  1795:         } elsif ($cgroup) {
1.588     raeburn  1796:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
1.57      albertel 1797:         } elsif ($csec) {
1.588     raeburn  1798:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1799:         } else {
1.588     raeburn  1800:             &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
1.57      albertel 1801:         }
                   1802:     } else {
1.275     raeburn  1803:         if ($uname) {
                   1804:             if (@{$usersgroups} > 1) {
1.582     raeburn  1805:                 (my $coursereply,$othergrp,$grp_parm,$controlgrp,my $grp_is_rec) =
1.580     raeburn  1806:                     &check_other_groups($$part{$which}.'.'.$$name{$which},
1.275     raeburn  1807:                        $rid,$cgroup,$defbgone,$usersgroups,$result,$courseopt);
1.582     raeburn  1808:                 if (($coursereply) && ($result > 4)) {
1.275     raeburn  1809:                     if (defined($controlgrp)) {
                   1810:                         if ($cgroup ne $controlgrp) {
1.582     raeburn  1811:                             $eff_groupparm = $grp_parm;
                   1812:                             undef($result);
                   1813:                             undef($effparm_rec);
                   1814:                             if ($grp_is_rec) {
                   1815:                                  $effparm_rec = 1;
                   1816:                             }
1.275     raeburn  1817:                         }
                   1818:                     }
                   1819:                 }
                   1820:             }
                   1821:         }
1.57      albertel 1822: 
1.588     raeburn  1823:         &print_td($r,18,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1824:         &print_td($r,16,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1825:         &print_td($r,15,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1826:         &print_td($r,14,'#FFDDDD',$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1827:         &print_td($r,13,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1828: 
                   1829:         if ($csec) {
1.588     raeburn  1830:             &print_td($r,12,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1831:             &print_td($r,10,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1832:             &print_td($r,9,$defbgtwo,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1833:         }
1.269     raeburn  1834: 
                   1835:         if ($cgroup) {
1.588     raeburn  1836:             &print_td($r,8,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,'',$extra);
                   1837:             &print_td($r,6,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp,$readonly,1,$extra);
                   1838:             &print_td($r,5,$defbgthree,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,$noeditgrp.$readonly,'',$extra);
1.269     raeburn  1839:         }
1.446     bisitz   1840: 
1.548     raeburn  1841:         if ($uname) {
1.275     raeburn  1842:             if ($othergrp) {
                   1843:                 $r->print($othergrp);
                   1844:             }
1.588     raeburn  1845:             &print_td($r,4,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
                   1846:             &print_td($r,2,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,1,$extra);
                   1847:             &print_td($r,1,$defbgone,$result,\@outpar,$mprefix,$which,\@typeoutpar,$display,'',$readonly,'',$extra);
1.548     raeburn  1848:         }
1.57      albertel 1849:     } # end of $parmlev if/else
1.582     raeburn  1850:     if (ref($recursinfo) eq 'ARRAY') {
                   1851:         my $rectitle = &mt('recursive');
                   1852:         if ((ref($maptitles) eq 'HASH') && (exists($maptitles->{$recursinfo->[2]}))) {
                   1853:             if ((ref($allmaps_inverted) eq 'HASH') && (exists($allmaps_inverted->{$recursinfo->[2]}))) {
                   1854:                 $rectitle = &mt('set in: [_1]','"'.
                   1855:                                 '<a href="javascript:pjumprec('."'".$allmaps_inverted->{$recursinfo->[2]}."',".
                   1856:                                                               "'$parmname','$$part{$which}'".');">'.
                   1857:                                 $maptitles->{$recursinfo->[2]}.'</a>"');
                   1858:               
                   1859:                 $numlinks ++;
                   1860:             }
                   1861:         }
                   1862:         my ($parmname)=($thismarker=~/\_([^\_]+)$/);
1.593     raeburn  1863:         $effective_parm = &valout($recursinfo->[0],$recursinfo->[1]);
1.582     raeburn  1864:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1865:                   '<br /><span class="LC_parm_recursive">'.$rectitle.'&nbsp;'.
                   1866:                   $effparm_level.'</span></td>');
                   1867:     } else {
                   1868:         if ($result) {
1.593     raeburn  1869:             $effective_parm = &valout($outpar[$result],$typeoutpar[$result]);
1.582     raeburn  1870:         }
                   1871:         if ($eff_groupparm) {
                   1872:             $effective_parm = $eff_groupparm;
                   1873:         }
                   1874:         $r->print('<td style="background-color:#CCCCFF;" align="center">'.$effective_parm.
                   1875:                   ($effparm_rec?'<br /><span class="LC_parm_recursive">'.&mt('recursive').
                   1876:                                 '</span>':'').'</td>');
                   1877:     }
1.203     www      1878:     if ($parmlev eq 'full') {
1.136     albertel 1879:         my $sessionval=&Apache::lonnet::EXT('resource.'.$$part{$which}.
1.201     www      1880:                                         '.'.$$name{$which},$$symbp{$rid});
1.136     albertel 1881:         my $sessionvaltype=$typeoutpar[$result];
1.560     damieng  1882:         if (!defined($sessionvaltype)) {
                   1883:             $sessionvaltype=$$defaulttype{$which};
                   1884:         }
1.419     bisitz   1885:         $r->print('<td style="background-color:#999999;" align="center"><font color="#FFFFFF">'.
1.593     raeburn  1886:                   &valout($sessionval,$sessionvaltype).'&nbsp;'.
1.57      albertel 1887:                   '</font></td>');
1.136     albertel 1888:     }
1.44      albertel 1889:     $r->print('</tr>');
1.57      albertel 1890:     $r->print("\n");
1.582     raeburn  1891:     if (($numlinks) && (ref($reclinks))) {
                   1892:         $$reclinks = $numlinks;
                   1893:     }
1.44      albertel 1894: }
1.59      matthew  1895: 
1.561     damieng  1896: # Prints a cell for table mode.
                   1897: #
                   1898: # FIXME: some of these parameter names are uninspired ($which and $value)
                   1899: # Also, it would make more sense to pass the display for this cell rather
                   1900: # than the full display hash and the key to use.
                   1901: #
                   1902: # @param {Apache2::RequestRec} $r - the Apache request
                   1903: # @param {integer} $which - level
                   1904: # @param {string} $defbg - cell background color
                   1905: # @param {integer} $result - the most specific level that is defined for that parameter
                   1906: # @param {array reference} $outpar - array level -> parameter value (when defined)
                   1907: # @param {string} $mprefix - resource id.'&'.part.'_'.parameter name.'&'
                   1908: # @param {string} $value - parameter key ('parameter_'.part.'_'.name)
                   1909: # @param {array reference} $typeoutpar - array level -> parameter type (when defined)
                   1910: # @param {hash reference} $display - parameter key -> full title for the parameter
                   1911: # @param {boolean} $noeditgrp - true if no edit is allowed for group level parameters
1.568     raeburn  1912: # @param {boolean} $readonly -true if editing not allowed.
1.588     raeburn  1913: # @param {boolean} $ismaplevel - true if level is for a map.
1.597     raeburn  1914: # @param {string} $extra - extra information to pass to plink.
1.44      albertel 1915: sub print_td {
1.578     raeburn  1916:     my ($r,$which,$defbg,$result,$outpar,$mprefix,$value,$typeoutpar,$display,
1.588     raeburn  1917:         $noeditgrp,$readonly,$ismaplevel,$extra)=@_;
1.578     raeburn  1918:     my ($ineffect,$recursive,$currval,$currtype,$currlevel);
                   1919:     $ineffect = 0;
                   1920:     $currval = $$outpar[$which];
                   1921:     $currtype = $$typeoutpar[$which];
                   1922:     $currlevel = $which;
                   1923:     if (($result) && ($result == $which)) {
                   1924:         $ineffect = 1;
                   1925:     } 
                   1926:     if ($ismaplevel) {
                   1927:         if ($mprefix =~ /(hiddenresource|encrypturl)\&/) {
                   1928:             if (($result) && ($result == $which)) {
                   1929:                 $recursive = 1;
                   1930:             }
                   1931:         } elsif ($$outpar[$which+1] ne '') {
                   1932:             $recursive = 1;
                   1933:             $currlevel = $which+1;
                   1934:             $currval = $$outpar[$currlevel];
                   1935:             $currtype = $$typeoutpar[$currlevel];
                   1936:             if (($result) && ($result == $currlevel)) {
                   1937:                 $ineffect = 1;
                   1938:             }
                   1939:         }
                   1940:     }
                   1941:     $r->print('<td style="background-color:'.($ineffect?'#AAFFAA':$defbg).
1.419     bisitz   1942:               ';" align="center">');
1.437     raeburn  1943:     my $nolink = 0;
1.568     raeburn  1944:     if ($readonly) {
1.552     raeburn  1945:         $nolink = 1;
1.568     raeburn  1946:     } else { 
1.578     raeburn  1947:         if ($which == 14 || $which == 15 || $mprefix =~ /mapalias\&$/) {
1.553     raeburn  1948:             $nolink = 1;
1.568     raeburn  1949:         } elsif (($env{'request.course.sec'} ne '') && ($which > 12)) {
1.533     raeburn  1950:             $nolink = 1;
1.568     raeburn  1951:         } elsif ($which == 5 || $which ==  6 || $which == 7 || $which == 8) {
                   1952:             if ($noeditgrp) {
                   1953:                 $nolink = 1;
                   1954:             }
                   1955:         } elsif ($mprefix =~ /availablestudent\&$/) {
1.599     raeburn  1956:             $nolink = 1;
1.568     raeburn  1957:         } elsif ($mprefix =~ /examcode\&$/) {
                   1958:             unless ($which == 2) {
                   1959:                 $nolink = 1;
                   1960:             }
1.533     raeburn  1961:         }
1.437     raeburn  1962:     }
                   1963:     if ($nolink) {
1.577     raeburn  1964:         my ($parmname)=((split(/\&/,$mprefix))[1]=~/\_([^\_]+)$/);
1.593     raeburn  1965:         $r->print(&valout($currval,$currtype));
1.114     www      1966:     } else {
1.578     raeburn  1967:         $r->print(&plink($currtype,
                   1968:                          $$display{$value},$currval,
1.588     raeburn  1969:                          $mprefix.$currlevel,'parmform.pres','psub',$recursive,
                   1970:                          $extra));
1.114     www      1971:     }
                   1972:     $r->print('</td>'."\n");
1.57      albertel 1973: }
                   1974: 
1.561     damieng  1975: # Returns HTML and other info for the cell added when a user is selected
                   1976: # and that user is in several groups. This is the cell with the title "Control by other group".
                   1977: #
                   1978: # @param {string} $what - parameter part.'.'.parameter name
                   1979: # @param {string} $rid - resource id
                   1980: # @param {string} $cgroup - group name
                   1981: # @param {string} $defbg - cell background color
                   1982: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   1983: # @param {integer} $result - level
                   1984: # @param {hash reference} $courseopt - course parameters hash (result of lonnet::get_courseresdata, dump of course's resourcedata.db)
1.582     raeburn  1985: # @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  1986: sub check_other_groups {
                   1987:     my ($what,$rid,$cgroup,$defbg,$usersgroups,$result,$courseopt) = @_;
1.275     raeburn  1988:     my $courseid = $env{'request.course.id'};
                   1989:     my $output;
                   1990:     my $symb = &symbcache($rid);
                   1991:     my $symbparm=$symb.'.'.$what;
                   1992:     my $map=(&Apache::lonnet::decode_symb($symb))[0];
1.556     raeburn  1993:     my $recurseparm=$map.'___(rec).'.$what; 
1.275     raeburn  1994:     my $mapparm=$map.'___(all).'.$what;
                   1995:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype) =
1.556     raeburn  1996:           &parm_control_group($courseid,$usersgroups,$symbparm,$mapparm,
                   1997:                               $recurseparm,$what,$courseopt);
1.275     raeburn  1998:     my $bgcolor = $defbg;
1.582     raeburn  1999:     my ($grp_parm,$grp_is_rec);
1.446     bisitz   2000:     if (($coursereply) && ($cgroup ne $resultgroup)) {
1.582     raeburn  2001:         my ($parmname) = ($what =~ /\.([^.]+)$/);
1.275     raeburn  2002:         if ($result > 3) {
1.419     bisitz   2003:             $bgcolor = '#AAFFAA';
1.275     raeburn  2004:         }
1.593     raeburn  2005:         $grp_parm = &valout($coursereply,$resulttype);
1.419     bisitz   2006:         $output = '<td style="background-color:'.$bgcolor.';" align="center">';
1.275     raeburn  2007:         if ($resultgroup && $resultlevel) {
1.582     raeburn  2008:             if ($resultlevel eq 'recursive') {
                   2009:                 $resultlevel = 'map/folder';
                   2010:                 $grp_is_rec = 1;
                   2011:             }
                   2012:             $output .= '<small><b>'.$resultgroup.'</b> ('.$resultlevel.'): </small>'.$grp_parm.
                   2013:                        ($grp_is_rec?'<span class="LC_parm_recursive">'.&mt('recursive').'</span>':'');
                   2014:              
1.275     raeburn  2015:         } else {
                   2016:             $output .= '&nbsp;';
                   2017:         }
                   2018:         $output .= '</td>';
                   2019:     } else {
1.419     bisitz   2020:         $output .= '<td style="background-color:'.$bgcolor.';">&nbsp;</td>';
1.275     raeburn  2021:     }
1.582     raeburn  2022:     return ($coursereply,$output,$grp_parm,$resultgroup,$grp_is_rec);
1.275     raeburn  2023: }
                   2024: 
1.561     damieng  2025: # Looks for a group with a defined parameter for given user and parameter.
1.580     raeburn  2026: # Used by check_other_groups.
1.561     damieng  2027: #
                   2028: # @param {string} $courseid - the course id
                   2029: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2030: # @param {string} $symbparm - end of the course parameter hash key for the group resource level
                   2031: # @param {string} $mapparm - end of the course parameter hash key for the group map/folder level
                   2032: # @param {string} $recurseparm - end of the course parameter hash key for the group recursive level
                   2033: # @param {string} $what - parameter part.'.'.parameter name
                   2034: # @param {hash reference} $courseopt - course parameters hash
                   2035: # @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  2036: sub parm_control_group {
1.556     raeburn  2037:     my ($courseid,$usersgroups,$symbparm,$mapparm,$recurseparm,$what,$courseopt) = @_;
1.275     raeburn  2038:     my ($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2039:     my $grpfound = 0;
1.556     raeburn  2040:     my @levels = ($symbparm,$mapparm,$recurseparm,$what);
                   2041:     my @levelnames = ('resource','map/folder','recursive','general');
1.275     raeburn  2042:     foreach my $group (@{$usersgroups}) {
                   2043:         if ($grpfound) { last; }
                   2044:         for (my $i=0; $i<@levels; $i++) {
                   2045:             my $item = $courseid.'.['.$group.'].'.$levels[$i];
                   2046:             if (defined($$courseopt{$item})) {
                   2047:                 $coursereply = $$courseopt{$item};
                   2048:                 $resultitem = $item;
                   2049:                 $resultgroup = $group;
                   2050:                 $resultlevel = $levelnames[$i];
                   2051:                 $resulttype = $$courseopt{$item.'.type'};
                   2052:                 $grpfound = 1;
                   2053:                 last;
                   2054:             }
                   2055:         }
                   2056:     }
                   2057:     return($coursereply,$resultitem,$resultgroup,$resultlevel,$resulttype);
                   2058: }
1.201     www      2059: 
1.63      bowersj2 2060: 
                   2061: 
1.562     damieng  2062: # Extracts lots of information about all of the the course's resources into a variety of hashes, using lonnavmaps and lonnet::metadata.
                   2063: # All the parameters are references and are filled by the sub.
                   2064: #
1.566     damieng  2065: # @param {array reference} $ids - resource and map ids
                   2066: # @param {hash reference} $typep - hash resource/map id -> resource type (file extension)
                   2067: # @param {hash reference} $keyp - hash resource/map id -> comma-separated list of parameter keys from lonnet::metadata
1.562     damieng  2068: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2069: # @param {hash reference} $allparts - hash parameter part -> part title (a parameter part can be problem part.'_'.response id for response parameters)
1.566     damieng  2070: # @param {hash reference} $allmaps - hash map pc -> map src
                   2071: # @param {hash reference} $mapp - hash map pc or resource/map id -> enclosing map src
                   2072: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' for a map or resource symb for a resource
                   2073: # @param {hash reference} $maptitles - hash map pc or src -> map title (this should really be two separate hashes)
                   2074: # @param {hash reference} $uris - hash resource/map id -> resource src
1.562     damieng  2075: # @param {hash reference} $keyorder - hash parameter key -> appearance rank for this parameter when looking through every resource and every parameter, starting at 100 (integer)
                   2076: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.63      bowersj2 2077: sub extractResourceInformation {
                   2078:     my $ids = shift;
                   2079:     my $typep = shift;
                   2080:     my $keyp = shift;
                   2081:     my $allparms = shift;
                   2082:     my $allparts = shift;
                   2083:     my $allmaps = shift;
                   2084:     my $mapp = shift;
                   2085:     my $symbp = shift;
1.82      www      2086:     my $maptitles=shift;
1.196     www      2087:     my $uris=shift;
1.210     www      2088:     my $keyorder=shift;
1.211     www      2089:     my $defkeytype=shift;
1.603     raeburn  2090:     my $pssymb=shift;
1.196     www      2091: 
1.210     www      2092:     my $keyordercnt=100;
1.63      bowersj2 2093: 
1.196     www      2094:     my $navmap = Apache::lonnavmaps::navmap->new();
1.603     raeburn  2095:     return unless(ref($navmap));
                   2096:     my @allres;
                   2097:     if ($pssymb ne '') {
                   2098:         my $res = $navmap->getBySymb($pssymb);
                   2099:         if (ref($res)) {
                   2100:             @allres = ($res);
                   2101:         }
                   2102:     }
                   2103:     if (!@allres) { 
                   2104:         @allres=$navmap->retrieveResources(undef,undef,1,undef,1);
                   2105:     }
1.196     www      2106:     foreach my $resource (@allres) {
1.480     amueller 2107:         my $id=$resource->id();
1.196     www      2108:         my ($mapid,$resid)=split(/\./,$id);
1.480     amueller 2109:         if ($mapid eq '0') { next; }
                   2110:         $$ids[$#$ids+1]=$id;
                   2111:         my $srcf=$resource->src();
                   2112:         $srcf=~/\.(\w+)$/;
                   2113:         $$typep{$id}=$1;
1.584     raeburn  2114:         my $toolsymb;
                   2115:         if ($srcf =~ /ext\.tool$/) {
                   2116:             $toolsymb = $resource->symb();
                   2117:         }
1.480     amueller 2118:         $$keyp{$id}='';
1.196     www      2119:         $$uris{$id}=$srcf;
1.512     foxr     2120: 
1.584     raeburn  2121:         foreach my $key (split(/\,/,&Apache::lonnet::metadata($srcf,'allpossiblekeys',$toolsymb))) {
1.480     amueller 2122:             next if ($key!~/^parameter_/);
1.363     albertel 2123: 
1.209     www      2124: # Hidden parameters
1.584     raeburn  2125:             next if (&Apache::lonnet::metadata($srcf,$key.'.hidden',$toolsymb) eq 'parm');
1.209     www      2126: #
                   2127: # allparms is a hash of parameter names
                   2128: #
1.584     raeburn  2129:             my $name=&Apache::lonnet::metadata($srcf,$key.'.name',$toolsymb);
1.480     amueller 2130:             if (!exists($$allparms{$name}) || $$allparms{$name} =~ m/^\s*$/ ) {
                   2131:                 my ($display,$parmdis);
                   2132:                 $display = &standard_parameter_names($name);
                   2133:                 if ($display eq '') {
1.584     raeburn  2134:                     $display= &Apache::lonnet::metadata($srcf,$key.'.display',$toolsymb);
1.480     amueller 2135:                     $parmdis = $display;
                   2136:                     $parmdis =~ s/\s*\[Part.*$//g;
                   2137:                 } else {
                   2138:                     $parmdis = &mt($display);
                   2139:                 }
                   2140:                 $$allparms{$name}=$parmdis;
                   2141:                 if (ref($defkeytype)) {
                   2142:                     $$defkeytype{$name}=
1.584     raeburn  2143:                     &Apache::lonnet::metadata($srcf,$key.'.type',$toolsymb);
1.480     amueller 2144:                 }
                   2145:             }
1.363     albertel 2146: 
1.209     www      2147: #
                   2148: # allparts is a hash of all parts
                   2149: #
1.584     raeburn  2150:             my $part= &Apache::lonnet::metadata($srcf,$key.'.part',$toolsymb);
1.480     amueller 2151:             $$allparts{$part} = &mt('Part: [_1]',$part);
1.209     www      2152: #
                   2153: # Remember all keys going with this resource
                   2154: #
1.480     amueller 2155:             if ($$keyp{$id}) {
                   2156:                 $$keyp{$id}.=','.$key;
                   2157:             } else {
                   2158:                 $$keyp{$id}=$key;
                   2159:             }   
1.210     www      2160: #
                   2161: # Put in order
1.446     bisitz   2162: #
1.480     amueller 2163:             unless ($$keyorder{$key}) {
                   2164:                 $$keyorder{$key}=$keyordercnt;
                   2165:                 $keyordercnt++;
                   2166:             }
1.473     amueller 2167:         }
                   2168: 
                   2169: 
1.480     amueller 2170:         if (!exists($$mapp{$mapid})) {
                   2171:             $$mapp{$id}=
                   2172:             &Apache::lonnet::declutter($resource->enclosing_map_src());
                   2173:             $$mapp{$mapid}=$$mapp{$id};
                   2174:             $$allmaps{$mapid}=$$mapp{$id};
                   2175:             if ($mapid eq '1') {
1.532     raeburn  2176:                 $$maptitles{$mapid}=&mt('Main Content');
1.480     amueller 2177:             } else {
                   2178:                 $$maptitles{$mapid}=&Apache::lonnet::gettitle($$mapp{$id});
                   2179:             }
                   2180:             $$maptitles{$$mapp{$id}}=$$maptitles{$mapid};
1.556     raeburn  2181:             $$symbp{$mapid}=$$mapp{$id}.'___(all)';  # Added in rev. 1.57, but seems not to be used.
                   2182:                                                      # Lines 1038 and 1114 which use $symbp{$mapid}
                   2183:                                                      # are commented out in rev. 1.57
1.473     amueller 2184:         } else {
1.480     amueller 2185:             $$mapp{$id} = $$mapp{$mapid};
1.473     amueller 2186:         }
1.480     amueller 2187:         $$symbp{$id}=&Apache::lonnet::encode_symb($$mapp{$id},$resid,$srcf);
1.63      bowersj2 2188:     }
                   2189: }
                   2190: 
1.582     raeburn  2191: sub get_recursive {
                   2192:     my ($recurseup,$resdata,$what,$prefix) = @_; 
                   2193:     if ((ref($resdata) eq 'HASH') && (ref($recurseup) eq 'ARRAY')) {
                   2194:         foreach my $item (@{$recurseup}) {
                   2195:             my $norecursechk=$prefix.'.'.$item.'___(all).'.$what;
                   2196:             if (defined($resdata->{$norecursechk})) {
                   2197:                 if ($what =~ /\.(encrypturl|hiddenresource)$/) {
                   2198:                     my $type = $resdata->{$norecursechk.'.type'};
                   2199:                     return [$resdata->{$norecursechk},$type,$item];
                   2200:                 } else {
                   2201:                     last;
                   2202:                 }
                   2203:             }
                   2204:             my $recursechk=$prefix.'.'.$item.'___(rec).'.$what;
                   2205:             if (defined($resdata->{$recursechk})) {
                   2206:                 my $type = $resdata->{$recursechk.'.type'};
                   2207:                 return [$resdata->{$recursechk},$type,$item];
                   2208:             }
                   2209:         }
                   2210:     }
                   2211:     return;
                   2212: }
                   2213: 
1.208     www      2214: 
1.562     damieng  2215: # Tells if a parameter type is a date.
                   2216: #
                   2217: # @param {string} type - parameter type
                   2218: # @returns{boolean} - true if it is a date
1.213     www      2219: sub isdateparm {
                   2220:     my $type=shift;
                   2221:     return (($type=~/^date/) && (!($type eq 'date_interval')));
                   2222: }
                   2223: 
1.589     raeburn  2224: # Determine if parameter type is specialized string type (i.e.,
                   2225: # not just string or string_yesno.  
                   2226: 
                   2227: sub is_specialstring {
                   2228:     my $type=shift;
1.603     raeburn  2229:     return (($type=~/^string_/) && ($type ne 'string_yesno'));
1.589     raeburn  2230: }
                   2231: 
1.562     damieng  2232: # Prints the HTML and Javascript to select parameters, with various shortcuts.
1.468     amueller 2233: #
1.581     raeburn  2234: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      2235: sub parmmenu {
1.581     raeburn  2236:     my ($r)=@_;
1.208     www      2237:     $r->print(<<ENDSCRIPT);
                   2238: <script type="text/javascript">
1.454     bisitz   2239: // <![CDATA[
1.208     www      2240:     function checkall(value, checkName) {
1.453     schualex 2241: 
                   2242:         var li = "_li";
                   2243:         var displayOverview = "";
                   2244:         
                   2245:         if (value == false) {
                   2246:             displayOverview = "none"
                   2247:         }
                   2248: 
1.562     damieng  2249:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.208     www      2250:             ele = document.forms.parmform.elements[i];
                   2251:             if (ele.name == checkName) {
                   2252:                 document.forms.parmform.elements[i].checked=value;
                   2253:             }
                   2254:         }
                   2255:     }
1.210     www      2256: 
                   2257:     function checkthis(thisvalue, checkName) {
1.562     damieng  2258:         for (i=0; i<document.forms.parmform.elements.length; i++) {
1.210     www      2259:             ele = document.forms.parmform.elements[i];
                   2260:             if (ele.name == checkName) {
1.562     damieng  2261:                 if (ele.value == thisvalue) {
                   2262:                     document.forms.parmform.elements[i].checked=true;
                   2263:                 }
1.210     www      2264:             }
                   2265:         }
                   2266:     }
                   2267: 
                   2268:     function checkdates() {
1.562     damieng  2269:         checkthis('duedate','pscat');
                   2270:         checkthis('opendate','pscat');
                   2271:         checkthis('answerdate','pscat');
1.218     www      2272:     }
                   2273: 
                   2274:     function checkdisset() {
1.562     damieng  2275:         checkthis('discussend','pscat');
                   2276:         checkthis('discusshide','pscat');
                   2277:         checkthis('discussvote','pscat');
1.218     www      2278:     }
                   2279: 
                   2280:     function checkcontdates() {
1.562     damieng  2281:         checkthis('contentopen','pscat');
                   2282:         checkthis('contentclose','pscat');
1.218     www      2283:     }
1.446     bisitz   2284: 
1.210     www      2285:     function checkvisi() {
1.562     damieng  2286:         checkthis('hiddenresource','pscat');
                   2287:         checkthis('encrypturl','pscat');
                   2288:         checkthis('problemstatus','pscat');
                   2289:         checkthis('contentopen','pscat');
                   2290:         checkthis('opendate','pscat');
1.210     www      2291:     }
                   2292: 
                   2293:     function checkparts() {
1.562     damieng  2294:         checkthis('hiddenparts','pscat');
                   2295:         checkthis('display','pscat');
                   2296:         checkthis('ordered','pscat');
1.210     www      2297:     }
                   2298: 
                   2299:     function checkstandard() {
                   2300:         checkall(false,'pscat');
1.562     damieng  2301:         checkdates();
                   2302:         checkthis('weight','pscat');
                   2303:         checkthis('maxtries','pscat');
                   2304:         checkthis('type','pscat');
                   2305:         checkthis('problemstatus','pscat');
1.210     www      2306:     }
                   2307: 
1.454     bisitz   2308: // ]]>
1.208     www      2309: </script>
                   2310: ENDSCRIPT
1.453     schualex 2311: 
1.491     bisitz   2312:     $r->print('<hr />');
1.581     raeburn  2313:     &shortCuts($r);
1.491     bisitz   2314:     $r->print('<hr />');
1.453     schualex 2315: }
1.562     damieng  2316: 
                   2317: # Returns parameter categories.
                   2318: #
                   2319: # @returns {hash} - category name -> title in English
1.465     amueller 2320: sub categories {
                   2321:     return ('time_settings' => 'Time Settings',
                   2322:     'grading' => 'Grading',
                   2323:     'tries' => 'Tries',
                   2324:     'problem_appearance' => 'Problem Appearance',
                   2325:     'behaviour_of_input_fields' => 'Behaviour of Input Fields',
                   2326:     'hiding' => 'Hiding',
                   2327:     'high_level_randomization' => 'High Level Randomization',
                   2328:     'slots' => 'Slots',
                   2329:     'file_submission' => 'File Submission',
                   2330:     'misc' => 'Miscellaneous' ); 
                   2331: }
                   2332: 
1.562     damieng  2333: # Returns the category for each parameter.
                   2334: #
                   2335: # @returns {hash} - parameter name -> category name
1.465     amueller 2336: sub lookUpTableParameter {
                   2337:  
                   2338:     return ( 
                   2339:         'opendate' => 'time_settings',
                   2340:         'duedate' => 'time_settings',
                   2341:         'answerdate' => 'time_settings',
                   2342:         'interval' => 'time_settings',
                   2343:         'contentopen' => 'time_settings',
                   2344:         'contentclose' => 'time_settings',
                   2345:         'discussend' => 'time_settings',
1.560     damieng  2346:         'printstartdate' => 'time_settings',
                   2347:         'printenddate' => 'time_settings',
1.465     amueller 2348:         'weight' => 'grading',
                   2349:         'handgrade' => 'grading',
                   2350:         'maxtries' => 'tries',
                   2351:         'hinttries' => 'tries',
1.503     raeburn  2352:         'randomizeontries' => 'tries',
1.465     amueller 2353:         'type' => 'problem_appearance',
                   2354:         'problemstatus' => 'problem_appearance',
                   2355:         'display' => 'problem_appearance',
                   2356:         'ordered' => 'problem_appearance',
                   2357:         'numbubbles' => 'problem_appearance',
                   2358:         'tol' => 'behaviour_of_input_fields',
                   2359:         'sig' => 'behaviour_of_input_fields',
                   2360:         'turnoffunit' => 'behaviour_of_input_fields',
                   2361:         'hiddenresource' => 'hiding',
                   2362:         'hiddenparts' => 'hiding',
                   2363:         'discusshide' => 'hiding',
                   2364:         'buttonshide' => 'hiding',
                   2365:         'turnoffeditor' => 'hiding',
                   2366:         'encrypturl' => 'hiding',
1.587     raeburn  2367:         'deeplink' => 'hiding',
1.465     amueller 2368:         'randomorder' => 'high_level_randomization',
                   2369:         'randompick' => 'high_level_randomization',
                   2370:         'available' => 'slots',
                   2371:         'useslots' => 'slots',
                   2372:         'availablestudent' => 'slots',
                   2373:         'uploadedfiletypes' => 'file_submission',
                   2374:         'maxfilesize' => 'file_submission',
                   2375:         'cssfile' => 'misc',
                   2376:         'mapalias' => 'misc',
                   2377:         'acc' => 'misc',
                   2378:         'maxcollaborators' => 'misc',
                   2379:         'scoreformat' => 'misc',
1.514     raeburn  2380:         'lenient' => 'grading',
1.519     raeburn  2381:         'retrypartial' => 'tries',
1.521     raeburn  2382:         'discussvote'  => 'misc',
1.584     raeburn  2383:         'examcode' => 'high_level_randomization',
1.575     raeburn  2384:     );
1.465     amueller 2385: }
                   2386: 
1.562     damieng  2387: # Adds the given parameter name to an array of arrays listing all parameters for each category.
                   2388: #
                   2389: # @param {string} $name - parameter name
                   2390: # @param {array reference} $catList - array reference category name -> array reference of parameter names
1.465     amueller 2391: sub whatIsMyCategory {
                   2392:     my $name = shift;
                   2393:     my $catList = shift;
                   2394:     my @list;
                   2395:     my %lookUpList = &lookUpTableParameter; #Initilize the lookupList
                   2396:     my $cat = $lookUpList{$name};
                   2397:     if (defined($cat)) {
                   2398:         if (!defined($$catList{$cat})){
                   2399:             push @list, ($name);
                   2400:             $$catList{$cat} = \@list;
                   2401:         } else {
                   2402:             push @{${$catList}{$cat}}, ($name);     
                   2403:         }
                   2404:     } else {
                   2405:         if (!defined($$catList{'misc'})){
                   2406:             push @list, ($name);
                   2407:             $$catList{'misc'} = \@list;
                   2408:         } else {
                   2409:             push @{${$catList}{'misc'}}, ($name);     
                   2410:         }
                   2411:     }        
                   2412: }
                   2413: 
1.562     damieng  2414: # Sorts parameter names based on appearance order.
                   2415: #
                   2416: # @param {array reference} name - array reference of parameter names
                   2417: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2418: # @returns {Array} - array of parameter names
1.465     amueller 2419: sub keysindisplayorderCategory {
                   2420:     my ($name,$keyorder)=@_;
                   2421:     return sort {
1.473     amueller 2422:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b}; 
1.465     amueller 2423:     } ( @{$name});
                   2424: }
                   2425: 
1.562     damieng  2426: # Returns a hash category name -> order, starting at 1 (integer)
                   2427: #
                   2428: # @returns {hash}
1.467     amueller 2429: sub category_order {
                   2430:     return (
                   2431:         'time_settings' => 1,
                   2432:         'grading' => 2,
                   2433:         'tries' => 3,
                   2434:         'problem_appearance' => 4,
                   2435:         'hiding' => 5,
                   2436:         'behaviour_of_input_fields' => 6,
                   2437:         'high_level_randomization'  => 7,
                   2438:         'slots' => 8,
                   2439:         'file_submission' => 9,
                   2440:         'misc' => 10
                   2441:     );
                   2442: 
                   2443: }
1.453     schualex 2444: 
1.562     damieng  2445: # Prints HTML to let the user select parameters, from a list of all parameters organized by category.
                   2446: #
                   2447: # @param {Apache2::RequestRec} $r - the Apache request
                   2448: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2449: # @param {array reference} $pscat - list of selected parameter names
                   2450: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
1.453     schualex 2451: sub parmboxes {
                   2452:     my ($r,$allparms,$pscat,$keyorder)=@_;
1.548     raeburn  2453:     my %categories = &categories();
1.467     amueller 2454:     my %category_order = &category_order();
1.465     amueller 2455:     my %categoryList = (
                   2456:         'time_settings' => [],
                   2457:         'grading' => [],
                   2458:         'tries' => [],
                   2459:         'problem_appearance' => [],
                   2460:         'behaviour_of_input_fields' => [],
                   2461:         'hiding' => [],
                   2462:         'high_level_randomization' => [],
                   2463:         'slots' => [],
                   2464:         'file_submission' => [],
                   2465:         'misc' => [],
1.489     bisitz   2466:     );
1.510     www      2467: 
1.548     raeburn  2468:     foreach my $tempparameter (keys(%$allparms)) {
1.465     amueller 2469:         &whatIsMyCategory($tempparameter, \%categoryList);
                   2470:     }
1.453     schualex 2471:     #part to print the parm-list
1.536     raeburn  2472:     foreach my $key (sort { $category_order{$a} <=> $category_order{$b} } keys(%categoryList)) {
                   2473:         next if (@{$categoryList{$key}} == 0);
                   2474:         next if ($key eq '');
                   2475:         $r->print('<div class="LC_Box LC_400Box">'
                   2476:                  .'<h4 class="LC_hcell">'.&mt($categories{$key}).'</h4>'."\n");
                   2477:         foreach my $tempkey (&keysindisplayorderCategory($categoryList{$key},$keyorder)) {
1.575     raeburn  2478:             next if ($tempkey eq '');
1.536     raeburn  2479:             $r->print('<span class="LC_nobreak">'
                   2480:                      .'<label><input type="checkbox" name="pscat" '
                   2481:                      .'value="'.$tempkey.'" ');
                   2482:             if ($$pscat[0] eq "all" || grep $_ eq $tempkey, @{$pscat}) {
                   2483:                 $r->print( ' checked="checked"');
                   2484:             }
                   2485:             $r->print(' />'.($$allparms{$tempkey}=~/\S/ ? $$allparms{$tempkey}
1.465     amueller 2486:                                                       : $tempkey)
1.536     raeburn  2487:                      .'</label></span><br />'."\n");
1.465     amueller 2488:         }
1.536     raeburn  2489:         $r->print('</div>');
1.465     amueller 2490:     }
1.536     raeburn  2491:     $r->print("\n");
1.453     schualex 2492: }
1.562     damieng  2493: 
                   2494: # Prints HTML with shortcuts to select groups of parameters in one click, or deselect all.
1.468     amueller 2495: #
1.562     damieng  2496: # @param {Apache2::RequestRec} $r - the Apache request
1.453     schualex 2497: sub shortCuts {
1.581     raeburn  2498:     my ($r)=@_;
1.453     schualex 2499: 
1.491     bisitz   2500:     # Parameter Selection
                   2501:     $r->print(
                   2502:         &Apache::lonhtmlcommon::start_funclist(&mt('Parameter Selection'))
                   2503:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2504:             '<a href="javascript:checkall(true, \'pscat\')">'.&mt('Select All').'</a>')
                   2505:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2506:             '<a href="javascript:checkstandard()">'.&mt('Select Common Only').'</a>')
                   2507:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2508:             '<a href="javascript:checkall(false, \'pscat\')">'.&mt('Unselect All').'</a>')
                   2509:        .&Apache::lonhtmlcommon::end_funclist()
                   2510:     );
                   2511: 
                   2512:     # Add Selection for...
                   2513:     $r->print(
                   2514:         &Apache::lonhtmlcommon::start_funclist(&mt('Add Selection for...'))
                   2515:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2516:             '<a href="javascript:checkdates()">'.&mt('Problem Dates').'</a>')
                   2517:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2518:             '<a href="javascript:checkcontdates()">'.&mt('Content Dates').'</a>')
                   2519:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2520:             '<a href="javascript:checkdisset()">'.&mt('Discussion Settings').'</a>')
                   2521:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2522:             '<a href="javascript:checkvisi()">'.&mt('Visibilities').'</a>')
                   2523:        .&Apache::lonhtmlcommon::add_item_funclist(
                   2524:             '<a href="javascript:checkparts()">'.&mt('Part Parameters').'</a>')
                   2525:        .&Apache::lonhtmlcommon::end_funclist()
                   2526:     );
1.208     www      2527: }
                   2528: 
1.562     damieng  2529: # Prints HTML to select parts to view (except for the title).
                   2530: # Used by table and overview modes.
                   2531: #
                   2532: # @param {Apache2::RequestRec} $r - the Apache request
                   2533: # @param {hash reference} $allparts - hash parameter part -> part title
                   2534: # @param {array reference} $psprt - list of selected parameter parts
1.209     www      2535: sub partmenu {
1.446     bisitz   2536:     my ($r,$allparts,$psprt)=@_;
1.523     raeburn  2537:     my $selsize = 1+scalar(keys(%{$allparts}));
                   2538:     if ($selsize > 8) {
                   2539:         $selsize = 8;
                   2540:     }
1.446     bisitz   2541: 
1.523     raeburn  2542:     $r->print('<select multiple="multiple" name="psprt" size="'.$selsize.'">');
1.208     www      2543:     $r->print('<option value="all"');
1.562     damieng  2544:     $r->print(' selected="selected"') unless (@{$psprt}); # useless, the array is never empty
1.208     www      2545:     $r->print('>'.&mt('All Parts').'</option>');
                   2546:     my %temphash=();
                   2547:     foreach (@{$psprt}) { $temphash{$_}=1; }
1.234     albertel 2548:     foreach my $tempkey (sort {
1.560     damieng  2549:                 if ($a==$b) { return ($a cmp $b) } else { return ($a <=> $b); }
                   2550:             } keys(%{$allparts})) {
                   2551:         unless ($tempkey =~ /\./) {
                   2552:             $r->print('<option value="'.$tempkey.'"');
                   2553:             if ($$psprt[0] eq "all" ||  $temphash{$tempkey}) {
                   2554:                 $r->print(' selected="selected"');
                   2555:             }
                   2556:             $r->print('>'.$$allparts{$tempkey}.'</option>');
1.473     amueller 2557:         }
1.208     www      2558:     }
1.446     bisitz   2559:     $r->print('</select>');
1.209     www      2560: }
                   2561: 
1.562     damieng  2562: # Prints HTML to select a user and/or a group.
                   2563: # Used by table mode.
                   2564: #
                   2565: # @param {Apache2::RequestRec} $r - the Apache request
                   2566: # @param {string} $uname - selected user name
                   2567: # @param {string} $id - selected Student/Employee ID
                   2568: # @param {string} $udom - selected user domain
                   2569: # @param {string} $csec - selected section name
                   2570: # @param {string} $cgroup - selected group name
                   2571: # @param {string} $parmlev - parameter level (Resource:'full', Map:'map', Course:'general')
                   2572: # @param {array reference} $usersgroups - list of groups the user belongs to, if any
                   2573: # @param {string} $pssymb - resource symb (when a single resource is selected)
1.209     www      2574: sub usermenu {
1.553     raeburn  2575:     my ($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,$usersgroups,$pssymb)=@_;
1.209     www      2576:     my $chooseopt=&Apache::loncommon::select_dom_form($udom,'udom').' '.
1.596     raeburn  2577:                   &Apache::loncommon::selectstudent_link('parmform','uname','udom','condition').
                   2578:                   &Apache::lonhtmlcommon::scripttag(<<ENDJS);
                   2579: function setCourseadv(form,caller) {
                   2580:     if (caller.value == 'st') {
                   2581:         form.courseadv.value = 'none';
                   2582:     } else {
                   2583:         form.courseadv.value = '';
                   2584:     }
                   2585:     return;
                   2586: }
                   2587: ENDJS
1.412     bisitz   2588: 
1.596     raeburn  2589:     my (%chkroles,$stuonly,$courseadv);
                   2590:     if ($env{'form.userroles'} eq 'any') {
                   2591:         $chkroles{'any'} = ' checked="checked"';
                   2592:     } else {
                   2593:         $chkroles{'st'} = ' checked="checked"';
                   2594:         $courseadv = 'none';
                   2595:     }
                   2596:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   2597:     if ($crstype eq 'Community') {
                   2598:         $stuonly = &mt('member only');
                   2599:     } else {
                   2600:         $stuonly = &mt('student only');
                   2601:     }
                   2602:     $chooseopt .= '<br /><span class="LC_cusr_subheading">'.
                   2603:                   &mt("User's role").':&nbsp;'.
                   2604:                   '<label><input type="radio" name="userroles" value="st"'.$chkroles{'st'}.' onclick="setCourseadv(this.form,this);" />'.
                   2605:                   $stuonly.'</label>&nbsp;&nbsp;'.
                   2606:                   '<label><input type="radio" name="userroles" value="any"'.$chkroles{'any'}.' onclick="setCourseadv(this.form,this);" />'.
                   2607:                   &mt('any role').'</label><input type="hidden" id="courseadv" name="courseadv" value="'.$courseadv.'" /></span>';
1.209     www      2608:     my $sections='';
1.300     albertel 2609:     my %sectionhash = &Apache::loncommon::get_sections();
                   2610: 
1.269     raeburn  2611:     my $groups;
1.553     raeburn  2612:     my %grouphash;
                   2613:     if (($pssymb) || &Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2614:         %grouphash = &Apache::longroup::coursegroups();
                   2615:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2616:         map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2617:     }
1.299     albertel 2618: 
1.412     bisitz   2619:     my $g_s_header='';
                   2620:     my $g_s_footer='';
1.446     bisitz   2621: 
1.552     raeburn  2622:     my $currsec = $env{'request.course.sec'};
                   2623:     if ($currsec) {
                   2624:         $sections=&mt('Section:').' '.$currsec;
                   2625:         if (%grouphash) {
                   2626:             $sections .= ';'.('&nbsp;' x2);
                   2627:         }
                   2628:     } elsif (%sectionhash && $currsec eq '') {
1.412     bisitz   2629:         $sections=&mt('Section:').' <select name="csec"';
1.299     albertel 2630:         if (%grouphash && $parmlev ne 'full') {
1.269     raeburn  2631:             $sections .= qq| onchange="group_or_section('csec')" |;
                   2632:         }
                   2633:         $sections .= '>';
1.548     raeburn  2634:     foreach my $section ('',sort(keys(%sectionhash))) {
1.473     amueller 2635:         $sections.='<option value="'.$section.'" '.
                   2636:         ($section eq $csec?'selected="selected"':'').'>'.$section.
1.275     raeburn  2637:                                                               '</option>';
1.209     www      2638:         }
                   2639:         $sections.='</select>';
1.269     raeburn  2640:     }
1.412     bisitz   2641: 
1.552     raeburn  2642:     if (%sectionhash && %grouphash && $parmlev ne 'full' && $currsec eq '') {
1.412     bisitz   2643:         $sections .= '&nbsp;'.&mt('or').'&nbsp;';
1.269     raeburn  2644:         $sections .= qq|
                   2645: <script type="text/javascript">
1.454     bisitz   2646: // <![CDATA[
1.269     raeburn  2647: function group_or_section(caller) {
                   2648:    if (caller == "cgroup") {
                   2649:        if (document.parmform.cgroup.selectedIndex != 0) {
                   2650:            document.parmform.csec.selectedIndex = 0;
                   2651:        }
                   2652:    } else {
                   2653:        if (document.parmform.csec.selectedIndex != 0) {
                   2654:            document.parmform.cgroup.selectedIndex = 0;
                   2655:        }
                   2656:    }
                   2657: }
1.454     bisitz   2658: // ]]>
1.269     raeburn  2659: </script>
                   2660: |;
1.554     raeburn  2661:     } else {
1.269     raeburn  2662:         $sections .= qq|
                   2663: <script type="text/javascript">
1.454     bisitz   2664: // <![CDATA[
1.269     raeburn  2665: function group_or_section(caller) {
                   2666:     return;
                   2667: }
1.454     bisitz   2668: // ]]>
1.269     raeburn  2669: </script>
                   2670: |;
1.446     bisitz   2671:     }
1.299     albertel 2672: 
                   2673:     if (%grouphash) {
1.597     raeburn  2674:         $groups=&mt('Group').': <select name="cgroup"';
1.552     raeburn  2675:         if (%sectionhash && $env{'form.action'} eq 'settable' && $currsec eq '') {
1.269     raeburn  2676:             $groups .= qq| onchange="group_or_section('cgroup')" |;
                   2677:         }
                   2678:         $groups .= '>';
1.548     raeburn  2679:         foreach my $grp ('',sort(keys(%grouphash))) {
1.275     raeburn  2680:             $groups.='<option value="'.$grp.'" ';
                   2681:             if ($grp eq $cgroup) {
                   2682:                 unless ((defined($uname)) && ($grp eq '')) {
                   2683:                     $groups .=  'selected="selected" ';
                   2684:                 }
                   2685:             } elsif (!defined($cgroup)) {
                   2686:                 if (@{$usersgroups} == 1) {
                   2687:                     if ($grp eq $$usersgroups[0]) {
                   2688:                         $groups .=  'selected="selected" ';
                   2689:                     }
                   2690:                 }
                   2691:             }
                   2692:             $groups .= '>'.$grp.'</option>';
1.269     raeburn  2693:         }
                   2694:         $groups.='</select>';
                   2695:     }
1.412     bisitz   2696: 
1.445     neumanie 2697:     if (%sectionhash || %grouphash) {
1.446     bisitz   2698:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Group/Section')));
                   2699:         $r->print($sections.$groups);
1.448     bisitz   2700:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.554     raeburn  2701:     } else {
                   2702:         $r->print($sections); 
1.445     neumanie 2703:     }
1.446     bisitz   2704: 
                   2705:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('User')));
1.443     neumanie 2706:     $r->print(&mt('For User [_1] or Student/Employee ID [_2] at Domain [_3]'
1.412     bisitz   2707:                  ,'<input type="text" value="'.$uname.'" size="12" name="uname" />'
                   2708:                  ,'<input type="text" value="'.$id.'" size="12" name="id" /> '
1.446     bisitz   2709:                  ,$chooseopt));
1.209     www      2710: }
                   2711: 
1.562     damieng  2712: # Prints HTML to select parameters from a list of all parameters.
                   2713: # Uses parmmenu and parmboxes.
                   2714: # Used by table and overview modes.
1.468     amueller 2715: #
1.562     damieng  2716: # @param {Apache2::RequestRec} $r - the Apache request
                   2717: # @param {hash reference} $allparms - hash parameter name -> parameter title
                   2718: # @param {array reference} $pscat - list of selected parameter names
                   2719: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2720: # @param {string} [$divid] - name used to give an id to the HTML element for the scroll box
1.209     www      2721: sub displaymenu {
1.581     raeburn  2722:     my ($r,$allparms,$pscat,$keyorder,$divid)=@_;
1.510     www      2723: 
1.445     neumanie 2724:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.510     www      2725:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameters to View')));
                   2726: 
1.581     raeburn  2727:     &parmmenu($r);
1.536     raeburn  2728:     $r->print(&Apache::loncommon::start_scrollbox('480px','440px','200px',$divid));
1.510     www      2729:     &parmboxes($r,$allparms,$pscat,$keyorder);
                   2730:     $r->print(&Apache::loncommon::end_scrollbox());
                   2731: 
                   2732:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.453     schualex 2733:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.510     www      2734:  
1.209     www      2735: }
                   2736: 
1.562     damieng  2737: # Prints HTML to select a map.
                   2738: # Used by table mode and overview mode.
                   2739: #
                   2740: # @param {Apache2::RequestRec} $r - the Apache request
1.566     damieng  2741: # @param {hash reference} $allmaps - hash map pc -> map src
                   2742: # @param {string} $pschp - selected map pc, or 'all'
1.562     damieng  2743: # @param {hash reference} $maptitles - hash map id or src -> map title
1.566     damieng  2744: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.445     neumanie 2745: sub mapmenu {
1.499     raeburn  2746:     my ($r,$allmaps,$pschp,$maptitles,$symbp)=@_;
1.468     amueller 2747:     my %allmaps_inverted = reverse %$allmaps;
1.461     neumanie 2748:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2749:     my $tree=[];
                   2750:     my $treeinfo={};
                   2751:     if (defined($navmap)) {
1.499     raeburn  2752:         my $it=$navmap->getIterator(undef,undef,undef,1,1,undef);
1.461     neumanie 2753:         my $curRes;
                   2754:         my $depth = 0;
1.468     amueller 2755:         my %parent = ();
                   2756:         my $startcount = 5;
                   2757:         my $lastcontainer = $startcount;
                   2758: # preparing what is to show ...
1.461     neumanie 2759:         while ($curRes = $it->next()) {
                   2760:             if ($curRes == $it->BEGIN_MAP()) {
                   2761:                 $depth++;
1.468     amueller 2762:                 $parent{$depth}= $lastcontainer;
1.461     neumanie 2763:             }
                   2764:             if ($curRes == $it->END_MAP()) {
                   2765:                 $depth--;
1.468     amueller 2766:                 $lastcontainer = $parent{$depth};
1.461     neumanie 2767:             }
                   2768:             if (ref($curRes)) {
1.468     amueller 2769:                 my $symb = $curRes->symb();
                   2770:                 my $ressymb = $symb;
1.461     neumanie 2771:                 if (($curRes->is_sequence()) || ($curRes->is_page())) {
                   2772:                     my $type = 'sequence';
                   2773:                     if ($curRes->is_page()) {
                   2774:                         $type = 'page';
                   2775:                     }
                   2776:                     my $id= $curRes->id();
1.468     amueller 2777:                     my $srcf = $curRes->src();
                   2778:                     my $resource_name = &Apache::lonnet::gettitle($srcf);
                   2779:                     if(!exists($treeinfo->{$id})) {
                   2780:                         push(@$tree,$id);
1.473     amueller 2781:                         my $enclosing_map_folder = &Apache::lonnet::declutter($curRes->enclosing_map_src());        
1.468     amueller 2782:                         $treeinfo->{$id} = {
1.461     neumanie 2783:                                     depth => $depth,
                   2784:                                     type  => $type,
1.468     amueller 2785:                                     name  => $resource_name,
                   2786:                                     enclosing_map_folder => $enclosing_map_folder,
1.461     neumanie 2787:                                     };
1.462     neumanie 2788:                     }
1.461     neumanie 2789:                 }
                   2790:             }
                   2791:         }
1.462     neumanie 2792:     }
1.473     amueller 2793: # Show it ...    
1.484     amueller 2794:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Enclosing Map or Folder'),'','',' id="mapmenu"'));
1.461     neumanie 2795:     if ((ref($tree) eq 'ARRAY') && (ref($treeinfo) eq 'HASH')) {
                   2796:         my $icon = '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.497     bisitz   2797:         my $whitespace =
                   2798:             '<img src="'
                   2799:            .&Apache::loncommon::lonhttpdurl('/adm/lonIcons/whitespace_21.gif')
                   2800:            .'" alt="" />';
                   2801: 
1.498     bisitz   2802:         # Info about selectable folders/maps
                   2803:         $r->print(
                   2804:             '<div class="LC_info">'
1.508     www      2805:            .&mt('You can only select maps and folders which have modifiable settings.')
                   2806:            .' '.&Apache::loncommon::help_open_topic('Parameter_Set_Folder') 
1.498     bisitz   2807:            .'</div>'
                   2808:         );
                   2809: 
1.536     raeburn  2810:         $r->print(&Apache::loncommon::start_scrollbox('700px','680px','400px','mapmenuscroll'));
1.523     raeburn  2811:         $r->print(&Apache::loncommon::start_data_table(undef,'mapmenuinner'));
1.497     bisitz   2812: 
1.498     bisitz   2813:         # Display row: "All Maps or Folders"
                   2814:         $r->print(
1.523     raeburn  2815:             &Apache::loncommon::start_data_table_row(undef,'picklevel')
1.498     bisitz   2816:            .'<td>'
                   2817:            .'<label>'
                   2818:            .'<input type="radio" name="pschp"'
1.497     bisitz   2819:         );
                   2820:         $r->print(' checked="checked"') if ($pschp eq 'all' || !$pschp);
1.498     bisitz   2821:         $r->print(
                   2822:             ' value="all" />&nbsp;'.$icon.'&nbsp;'
                   2823:            .&mt('All Maps or Folders')
                   2824:            .'</label>'
                   2825:            .'<hr /></td>'
                   2826:            .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2827:         );
1.497     bisitz   2828: 
1.532     raeburn  2829:         # Display row: "Main Content"
1.468     amueller 2830:         if (exists($$allmaps{1})) {
1.498     bisitz   2831:             $r->print(
                   2832:                 &Apache::loncommon::start_data_table_row()
                   2833:                .'<td>'
                   2834:                .'<label>'
                   2835:                .'<input type="radio" name="pschp" value="1"'
1.468     amueller 2836:             );
1.497     bisitz   2837:             $r->print(' checked="checked"') if ($pschp eq '1');
1.498     bisitz   2838:             $r->print(
                   2839:                 '/>&nbsp;'.$icon.'&nbsp;'
                   2840:                .$$maptitles{1}
                   2841:                .($$allmaps{1} !~/^uploaded/?' ['.$$allmaps{1}.']':'')
                   2842:                .'</label>'
                   2843:                .'</td>'
                   2844:                .&Apache::loncommon::end_data_table_row()
1.468     amueller 2845:             );
                   2846:         }
1.497     bisitz   2847: 
                   2848:         # Display rows for all course maps and folders
1.468     amueller 2849:         foreach my $id (@{$tree}) {
                   2850:             my ($mapid,$resid)=split(/\./,$id);
1.464     bisitz   2851:             # Indentation
1.468     amueller 2852:             my $depth = $treeinfo->{$id}->{'depth'};
1.464     bisitz   2853:             my $indent;
                   2854:             for (my $i = 0; $i < $depth; $i++) {
                   2855:                 $indent.= $whitespace;
                   2856:             }
1.461     neumanie 2857:             $icon =  '<img src="/adm/lonIcons/navmap.folder.open.gif" alt="" />';
1.468     amueller 2858:             if ($treeinfo->{$id}->{'type'} eq 'page') {
1.461     neumanie 2859:                 $icon = '<img src="/adm/lonIcons/navmap.page.open.gif" alt="" />';
                   2860:             }
1.468     amueller 2861:             my $symb_name = $$symbp{$id};
                   2862:             my ($front, $tail) = split (/___${resid}___/, $symb_name);
                   2863:             $symb_name = $tail;
1.498     bisitz   2864:             $r->print(
                   2865:                 &Apache::loncommon::start_data_table_row()
                   2866:                .'<td>'
                   2867:                .'<label>'
1.463     bisitz   2868:             );
1.498     bisitz   2869:             # Only offer radio button for folders/maps which can be parameterized
                   2870:             if ($allmaps_inverted{$symb_name}) {
                   2871:                 $r->print(
                   2872:                     '<input type ="radio" name="pschp"'
                   2873:                    .' value="'.$allmaps_inverted{$symb_name}.'"'
                   2874:                 );
                   2875:                 $r->print(' checked="checked"') if ($allmaps_inverted{$symb_name} eq $pschp);
                   2876:                 $r->print('/>');
                   2877:             } else {
                   2878:                 $r->print($whitespace);
1.461     neumanie 2879:             }
1.498     bisitz   2880:             $r->print(
                   2881:                 $indent.$icon.'&nbsp;'
                   2882:                .$treeinfo->{$id}->{name}
                   2883:                .($$allmaps{$mapid}!~/^uploaded/?' ['.$$allmaps{$mapid}.']':'')
                   2884:                .'</label>'
                   2885:                .'</td>'
                   2886:                .&Apache::loncommon::end_data_table_row()
1.463     bisitz   2887:             );
1.461     neumanie 2888:         }
1.497     bisitz   2889: 
1.523     raeburn  2890:         $r->print(&Apache::loncommon::end_data_table().
                   2891:                   '<br style="line-height:2px;" />'.
                   2892:                   &Apache::loncommon::end_scrollbox());
1.209     www      2893:     }
                   2894: }
                   2895: 
1.563     damieng  2896: # Prints HTML to select the parameter level (resource, map/folder or course).
                   2897: # Used by table and overview modes.
                   2898: #
                   2899: # @param {Apache2::RequestRec} $r - the Apache request
                   2900: # @param {hash reference} $alllevs - all parameter levels, hash English title -> value
                   2901: # @param {string} $parmlev - selected level value (full|map|general), or ''
1.209     www      2902: sub levelmenu {
1.446     bisitz   2903:     my ($r,$alllevs,$parmlev)=@_;
                   2904: 
1.548     raeburn  2905:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parameter Level').
                   2906:                                                 &Apache::loncommon::help_open_topic('Course_Parameter_Levels')));
1.474     amueller 2907:     $r->print('<select id="parmlev" name="parmlev" onchange="showHide_courseContent()">');
1.548     raeburn  2908:     foreach my $lev (reverse(sort(keys(%{$alllevs})))) {
                   2909:         $r->print('<option value="'.$$alllevs{$lev}.'"');
                   2910:         if ($parmlev eq $$alllevs{$lev}) {
                   2911:             $r->print(' selected="selected"');
                   2912:         }
                   2913:         $r->print('>'.&mt($lev).'</option>');
1.208     www      2914:     }
1.446     bisitz   2915:     $r->print("</select>");
1.208     www      2916: }
                   2917: 
1.211     www      2918: 
1.563     damieng  2919: # Returns HTML to select a section (with a select HTML element).
                   2920: # Used by overview mode.
                   2921: #
                   2922: # @param {array reference} $selectedsections - list of selected section ids
                   2923: # @returns {string}
1.211     www      2924: sub sectionmenu {
1.553     raeburn  2925:     my ($selectedsections)=@_;
1.300     albertel 2926:     my %sectionhash = &Apache::loncommon::get_sections();
1.553     raeburn  2927:     return '' if (!%sectionhash);
1.300     albertel 2928: 
1.552     raeburn  2929:     my (@possibles,$disabled);
                   2930:     if ($env{'request.course.sec'} ne '') {
                   2931:         @possibles = ($env{'request.course.sec'});
                   2932:         $selectedsections = [$env{'request.course.sec'}];
                   2933:         $disabled = ' disabled="disabled"';
                   2934:     } else {
                   2935:         @possibles = ('all',sort(keys(%sectionhash)));
                   2936:     }
1.553     raeburn  2937:     my $output = '<select name="Section" multiple="multiple" size="8"'.$disabled.'>';
1.552     raeburn  2938:     foreach my $s (@possibles) {
1.553     raeburn  2939:         $output .= '    <option value="'.$s.'"';
                   2940:         if ((@{$selectedsections}) && (grep(/^\Q$s\E$/,@{$selectedsections}))) {  
                   2941:             $output .= ' selected="selected"';
1.473     amueller 2942:         }
1.553     raeburn  2943:         $output .= '>'."$s</option>\n";
1.300     albertel 2944:     }
1.553     raeburn  2945:     $output .= "</select>\n";
                   2946:     return $output;
1.269     raeburn  2947: }
                   2948: 
1.563     damieng  2949: # Returns HTML to select a group (with a select HTML element).
                   2950: # Used by overview mode.
                   2951: #
                   2952: # @param {array reference} $selectedgroups - list of selected group names
                   2953: # @returns {string}
1.269     raeburn  2954: sub groupmenu {
1.553     raeburn  2955:     my ($selectedgroups)=@_;
                   2956:     my %grouphash;
                   2957:     if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   2958:         %grouphash = &Apache::longroup::coursegroups();
                   2959:     } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  2960:          map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  2961:     }
                   2962:     return '' if (!%grouphash);
1.299     albertel 2963: 
1.553     raeburn  2964:     my $output = '<select name="Group" multiple="multiple" size="8">';
1.299     albertel 2965:     foreach my $group (sort(keys(%grouphash))) {
1.553     raeburn  2966:         $output .= '    <option value="'.$group.'"';
                   2967:         if ((@{$selectedgroups}) && (grep(/^\Q$group\E$/,\@{$selectedgroups}))) {
                   2968:             $output .=  ' selected="selected"';
1.473     amueller 2969:         }
1.553     raeburn  2970:         $output .= '>'."$group</option>\n";
1.211     www      2971:     }
1.553     raeburn  2972:     $output .= "</select>\n";
                   2973:     return $output;
1.211     www      2974: }
                   2975: 
1.563     damieng  2976: # Returns an array with the given parameter split by comma.
                   2977: # Used by assessparms (table mode).
                   2978: #
                   2979: # @param {string} $keyp - the string to split
                   2980: # @returns {Array<string>}
1.210     www      2981: sub keysplit {
                   2982:     my $keyp=shift;
                   2983:     return (split(/\,/,$keyp));
                   2984: }
                   2985: 
1.563     damieng  2986: # Returns the keys in $name, sorted using $keyorder.
                   2987: # Parameters are sorted by key, which means they are sorted by part first, then by name.
                   2988: # Used by assessparms (table mode) for resource level.
                   2989: #
                   2990: # @param {hash reference} $name - parameter key -> parameter name
                   2991: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   2992: # @returns {Array<string>}
1.210     www      2993: sub keysinorder {
                   2994:     my ($name,$keyorder)=@_;
                   2995:     return sort {
1.560     damieng  2996:         $$keyorder{$a} <=> $$keyorder{$b};
1.548     raeburn  2997:     } (keys(%{$name}));
1.210     www      2998: }
                   2999: 
1.563     damieng  3000: # Returns the keys in $name, sorted using $keyorder to sort parameters by name first, then by part.
                   3001: # Used by assessparms (table mode) for map and general levels.
                   3002: #
                   3003: # @param {hash reference} $name - parameter key -> parameter name
                   3004: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3005: # @returns {Array<string>}
1.236     albertel 3006: sub keysinorder_bytype {
                   3007:     my ($name,$keyorder)=@_;
                   3008:     return sort {
1.563     damieng  3009:         my $ta=(split('_',$a))[-1]; # parameter name
1.560     damieng  3010:         my $tb=(split('_',$b))[-1];
                   3011:         if ($$keyorder{'parameter_0_'.$ta} == $$keyorder{'parameter_0_'.$tb}) {
                   3012:             return ($a cmp $b);
                   3013:         }
                   3014:         $$keyorder{'parameter_0_'.$ta} <=> $$keyorder{'parameter_0_'.$tb};
1.548     raeburn  3015:     } (keys(%{$name}));
1.236     albertel 3016: }
                   3017: 
1.563     damieng  3018: # Returns the keys in $name, sorted using $keyorder to sort parameters by name.
                   3019: # Used by defaultsetter (parameter settings default actions).
                   3020: #
                   3021: # @param {hash reference} $name - hash parameter name -> parameter title
                   3022: # @param {hash reference} $keyorder - hash parameter key -> appearance rank
                   3023: # @returns {Array<string>}
1.211     www      3024: sub keysindisplayorder {
                   3025:     my ($name,$keyorder)=@_;
                   3026:     return sort {
1.560     damieng  3027:         $$keyorder{'parameter_0_'.$a} <=> $$keyorder{'parameter_0_'.$b};
1.548     raeburn  3028:     } (keys(%{$name}));
1.211     www      3029: }
                   3030: 
1.563     damieng  3031: # Prints HTML with a choice to sort results by realm or student first.
                   3032: # Used by overview mode.
                   3033: #
                   3034: # @param {Apache2::RequestRec} $r - the Apache request
                   3035: # @param {string} $sortorder - realmstudent|studentrealm
1.214     www      3036: sub sortmenu {
                   3037:     my ($r,$sortorder)=@_;
1.236     albertel 3038:     $r->print('<br /><label><input type="radio" name="sortorder" value="realmstudent"');
1.214     www      3039:     if ($sortorder eq 'realmstudent') {
1.422     bisitz   3040:        $r->print(' checked="checked"');
1.214     www      3041:     }
                   3042:     $r->print(' />'.&mt('Sort by realm first, then student (group/section)'));
1.236     albertel 3043:     $r->print('</label><br /><label><input type="radio" name="sortorder" value="studentrealm"');
1.214     www      3044:     if ($sortorder eq 'studentrealm') {
1.422     bisitz   3045:        $r->print(' checked="checked"');
1.214     www      3046:     }
1.236     albertel 3047:     $r->print(' />'.&mt('Sort by student (group/section) first, then realm').
1.473     amueller 3048:           '</label>');
1.214     www      3049: }
                   3050: 
1.563     damieng  3051: # Returns a hash parameter key -> order (integer) giving the order for some parameters.
                   3052: #
                   3053: # @returns {hash}
1.211     www      3054: sub standardkeyorder {
                   3055:     return ('parameter_0_opendate' => 1,
1.473     amueller 3056:         'parameter_0_duedate' => 2,
                   3057:         'parameter_0_answerdate' => 3,
                   3058:         'parameter_0_interval' => 4,
                   3059:         'parameter_0_weight' => 5,
                   3060:         'parameter_0_maxtries' => 6,
                   3061:         'parameter_0_hinttries' => 7,
                   3062:         'parameter_0_contentopen' => 8,
                   3063:         'parameter_0_contentclose' => 9,
                   3064:         'parameter_0_type' => 10,
                   3065:         'parameter_0_problemstatus' => 11,
                   3066:         'parameter_0_hiddenresource' => 12,
                   3067:         'parameter_0_hiddenparts' => 13,
                   3068:         'parameter_0_display' => 14,
                   3069:         'parameter_0_ordered' => 15,
                   3070:         'parameter_0_tol' => 16,
                   3071:         'parameter_0_sig' => 17,
                   3072:         'parameter_0_turnoffunit' => 18,
1.521     raeburn  3073:         'parameter_0_discussend' => 19,
                   3074:         'parameter_0_discusshide' => 20,
                   3075:         'parameter_0_discussvote' => 21,
1.560     damieng  3076:         'parameter_0_printstartdate'  =>  22,
                   3077:         'parameter_0_printenddate' =>  23);
1.211     www      3078: }
                   3079: 
1.59      matthew  3080: 
1.560     damieng  3081: # Table mode UI.
1.563     damieng  3082: # If nothing is selected, prints HTML forms to select resources, parts, parameters, user, group and section.
                   3083: # Otherwise, prints the parameter table, with a link to change the selection unless a single resource is selected.
                   3084: #
                   3085: # Parameters used from the request:
                   3086: # action - handler action (see handler), usermenu is checking for value 'settable'
                   3087: # cgroup - selected group
                   3088: # command - 'set': direct access to table mode for a resource
                   3089: # csec - selected section
                   3090: # dis - set when the "Update Display" button was used, used only to discard command 'set'
                   3091: # hideparmsel - can be 'hidden' to hide the parameter selection div initially and display the "Change Parameter Selection" link instead (which displays the div)
                   3092: # id - student/employee ID
                   3093: # parmlev - selected level (full|map|general)
                   3094: # part - selected part (unused ?)
                   3095: # pres_marker - &&&-separated parameter identifiers, "resource id&part_parameter name&level"
                   3096: # pres_type - &&&-separated parameter types
                   3097: # pres_value - &&&-separated parameter values
                   3098: # prevvisit - '1' if the user has submitted the form before
                   3099: # pscat (multiple values) - selected parameter names
1.566     damieng  3100: # pschp - selected map pc, or 'all'
1.563     damieng  3101: # psprt (multiple values) - list of selected parameter parts
                   3102: # filter - part of or whole parameter name, to be filtered out when parameters are displayed (unused ?)
                   3103: # recent_* (* = parameter type) - recent values entered by the user for parameter types
                   3104: # symb - resource symb (when a single resource is selected)
                   3105: # udom - selected user domain
                   3106: # uname - selected user name
                   3107: # url - used only with command 'set', the resource url
                   3108: #
                   3109: # @param {Apache2::RequestRec} $r - the Apache request
1.568     raeburn  3110: # @param $parm_permission - ref to hash of permissions
                   3111: #                           if $parm_permission->{'edit'} is true, editing is allowed.
1.30      www      3112: sub assessparms {
1.1       www      3113: 
1.568     raeburn  3114:     my ($r,$parm_permission) = @_;
1.201     www      3115: 
1.512     foxr     3116: 
                   3117: # -------------------------------------------------------- Variable declaration
1.566     damieng  3118:     my @ids=(); # resource and map ids
                   3119:     my %symbp=(); # hash map pc or resource/map id -> map src.'___(all)' or resource symb
                   3120:     my %mapp=(); # hash map pc or resource/map id -> enclosing map src
                   3121:     my %typep=(); # hash resource/map id -> resource type (file extension)
                   3122:     my %keyp=(); # hash resource/map id -> comma-separated list of parameter keys
                   3123:     my %uris=(); # hash resource/map id -> resource src
                   3124:     my %maptitles=(); # hash map pc or src -> map title
                   3125:     my %allmaps=(); # hash map pc -> map src
1.582     raeburn  3126:     my %allmaps_inverted=(); # hash map src -> map pc
1.563     damieng  3127:     my %alllevs=(); # hash English level title -> value
                   3128: 
                   3129:     my $uname; # selected user name
                   3130:     my $udom; # selected user domain
                   3131:     my $uhome; # server with the user's files, or 'no_host'
                   3132:     my $csec; # selected section name
                   3133:     my $cgroup; # selected group name
                   3134:     my @usersgroups = (); # list of the user groups
1.582     raeburn  3135:     my $numreclinks = 0;
1.446     bisitz   3136: 
1.190     albertel 3137:     my $coursename=$env{'course.'.$env{'request.course.id'}.'.description'};
1.187     www      3138: 
1.57      albertel 3139:     $alllevs{'Resource Level'}='full';
1.215     www      3140:     $alllevs{'Map/Folder Level'}='map';
1.57      albertel 3141:     $alllevs{'Course Level'}='general';
                   3142: 
1.563     damieng  3143:     my %allparms; # hash parameter name -> parameter title
                   3144:     my %allparts; # hash parameter part -> part title
1.512     foxr     3145: # ------------------------------------------------------------------------------
                   3146: 
1.210     www      3147: #
                   3148: # Order in which these parameters will be displayed
                   3149: #
1.211     www      3150:     my %keyorder=&standardkeyorder();
                   3151: 
1.512     foxr     3152: #    @ids=();
                   3153: #    %symbp=();       # These seem defined above already.
                   3154: #    %typep=();
1.43      albertel 3155: 
                   3156:     my $message='';
                   3157: 
1.190     albertel 3158:     $csec=$env{'form.csec'};
1.552     raeburn  3159:     if ($env{'request.course.sec'} ne '') {
                   3160:         $csec = $env{'request.course.sec'};    
                   3161:     }
                   3162: 
1.553     raeburn  3163: # Check group privs.
1.269     raeburn  3164:     $cgroup=$env{'form.cgroup'};
1.553     raeburn  3165:     my $noeditgrp; 
                   3166:     if ($cgroup ne '') {
                   3167:         unless (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   3168:             if (($env{'request.course.groups'} eq '') || 
1.585     raeburn  3169:                 (!grep(/^\Q$cgroup\E$/,split(/:/,$env{'request.course.groups'})))) {
1.553     raeburn  3170:                 $noeditgrp = 1;
                   3171:             }
                   3172:         }
                   3173:     }
1.188     www      3174: 
1.190     albertel 3175:     if      ($udom=$env{'form.udom'}) {
                   3176:     } elsif ($udom=$env{'request.role.domain'}) {
                   3177:     } elsif ($udom=$env{'user.domain'}) {
1.172     albertel 3178:     } else {
1.473     amueller 3179:         $udom=$r->dir_config('lonDefDomain');
1.172     albertel 3180:     }
1.468     amueller 3181:     
1.43      albertel 3182: 
1.134     albertel 3183:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
1.190     albertel 3184:     my $pschp=$env{'form.pschp'};
1.506     www      3185: 
                   3186: 
1.134     albertel 3187:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      3188:     if (!@psprt) { $psprt[0]='all'; }
1.506     www      3189:     if (($env{'form.part'}) && ($psprt[0] ne 'all')) { $psprt[0]=$env{'form.part'}; }
1.57      albertel 3190: 
1.43      albertel 3191:     my $pssymb='';
1.57      albertel 3192:     my $parmlev='';
1.446     bisitz   3193: 
1.190     albertel 3194:     unless ($env{'form.parmlev'}) {
1.57      albertel 3195:         $parmlev = 'map';
                   3196:     } else {
1.190     albertel 3197:         $parmlev = $env{'form.parmlev'};
1.57      albertel 3198:     }
1.26      www      3199: 
1.29      www      3200: # ----------------------------------------------- Was this started from grades?
                   3201: 
1.560     damieng  3202:     if (($env{'form.command'} eq 'set') && ($env{'form.url'}) &&
                   3203:             (!$env{'form.dis'})) {
1.473     amueller 3204:         my $url=$env{'form.url'};
                   3205:         $url=~s-^http://($ENV{'SERVER_NAME'}|$ENV{'HTTP_HOST'})--;
                   3206:         $pssymb=&Apache::lonnet::symbread($url);
                   3207:         if (!@pscat) { @pscat=('all'); }
                   3208:         $pschp='';
1.57      albertel 3209:         $parmlev = 'full';
1.190     albertel 3210:     } elsif ($env{'form.symb'}) {
1.473     amueller 3211:         $pssymb=$env{'form.symb'};
                   3212:         if (!@pscat) { @pscat=('all'); }
                   3213:         $pschp='';
1.57      albertel 3214:         $parmlev = 'full';
1.43      albertel 3215:     } else {
1.473     amueller 3216:         $env{'form.url'}='';
1.43      albertel 3217:     }
                   3218: 
1.190     albertel 3219:     my $id=$env{'form.id'};
1.43      albertel 3220:     if (($id) && ($udom)) {
1.555     raeburn  3221:         $uname=(&Apache::lonnet::idget($udom,[$id],'ids'))[1];
1.473     amueller 3222:         if ($uname) {
                   3223:             $id='';
                   3224:         } else {
                   3225:             $message=
1.540     bisitz   3226:                 '<p class="LC_warning">'.
                   3227:                 &mt('Unknown ID [_1] at domain [_2]',
                   3228:                     "'".$id."'","'".$udom."'").
                   3229:                 '</p>';
1.473     amueller 3230:         }
1.43      albertel 3231:     } else {
1.473     amueller 3232:         $uname=$env{'form.uname'};
1.43      albertel 3233:     }
                   3234:     unless ($udom) { $uname=''; }
                   3235:     $uhome='';
                   3236:     if ($uname) {
1.473     amueller 3237:         $uhome=&Apache::lonnet::homeserver($uname,$udom);
1.43      albertel 3238:         if ($uhome eq 'no_host') {
1.473     amueller 3239:             $message=
1.540     bisitz   3240:                 '<p class="LC_warning">'.
                   3241:                 &mt('Unknown user [_1] at domain [_2]',
                   3242:                     "'".$uname."'","'".$udom."'").
                   3243:                 '</p>';
1.473     amueller 3244:             $uname='';
1.12      www      3245:         } else {
1.473     amueller 3246:             $csec=&Apache::lonnet::getsection($udom,$uname,
                   3247:                           $env{'request.course.id'});
                   3248:             if ($csec eq '-1') {
1.596     raeburn  3249:                 my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   3250:                 if ($env{'form.userroles'} eq 'any') {
                   3251:                     if (($env{'user.name'} eq $uname) && ($env{'user.domain'} eq $udom)) {
                   3252:                         $csec = $env{'request.course.sec'};
                   3253:                         $message = '<span class="LC_info">';
                   3254:                         if ($crstype eq 'Community') {
                   3255:                             $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3256:                                             $uname,$udom);
                   3257:                         } else {
                   3258:                             $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3259:                                             $uname,$udom);
                   3260:                         }
                   3261:                         $message .= '</span>';
                   3262:                     } else {
                   3263:                         my @possroles = ('in','ep','ta','cr');
                   3264:                         if ($crstype eq 'Community') {
                   3265:                             unshift(@possroles,'co');
                   3266:                         } else {
                   3267:                             unshift(@possroles,'cc');
                   3268:                         }
                   3269:                         my %not_student_roles =
                   3270:                             &Apache::lonnet::get_my_roles($uname,$udom,'userroles',['active'],
                   3271:                                                           \@possroles,[$udom],1,1);
                   3272:                         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3273:                         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   3274:                         my %sections_by_role;
                   3275:                         foreach my $role (keys(%not_student_roles)) {
                   3276:                             if ($role =~ /^\Q$cnum:$cdom:\E([^:]+):(|[^:]+)$/) {
                   3277:                                 my ($rolename,$sec) = ($1,$2);
                   3278:                                 if ($rolename =~ m{^cr/}) {
                   3279:                                     $rolename = 'cr';
                   3280:                                 }
                   3281:                                 push(@{$sections_by_role{$rolename}},$sec);
                   3282:                             }
                   3283:                         }
                   3284:                         my $numroles = scalar(keys(%sections_by_role));
                   3285:                         if ($numroles) {
                   3286:                             foreach my $role (@possroles) {
                   3287:                                 if (ref($sections_by_role{$role}) eq 'ARRAY') {
                   3288:                                     my @secs = sort { $a <=> $b } @{$sections_by_role{$role}};
                   3289:                                     $csec = $secs[0];
                   3290:                                     last;
                   3291:                                 }
                   3292:                             }
                   3293:                         }
                   3294:                         if ($csec eq '-1') {
                   3295:                             $message = '<span class="LC_warning">';
                   3296:                             if ($crstype eq 'Community') {
                   3297:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this community',
                   3298:                                                 $uname,$udom);
                   3299:                             } else {
                   3300:                                 $message .= &mt('User [_1] at domain [_2] does not have a role in this course',
                   3301:                                                 $uname,$udom);
                   3302:                             }
                   3303:                             $message .= '</span>';
                   3304:                             $uname='';
                   3305:                             if ($env{'request.course.sec'} ne '') {
                   3306:                                 $csec=$env{'request.course.sec'};
                   3307:                             } else {
                   3308:                                 $csec=$env{'form.csec'};
                   3309:                             }
                   3310:                             $cgroup=$env{'form.cgroup'};
                   3311:                         } else {
                   3312:                             $message = '<span class="LC_info">';
                   3313:                             if ($crstype eq 'Community') {
                   3314:                                 $message .= &mt('User [_1] at domain [_2] has a non-member role in this community',
                   3315:                                          $uname,$udom);
                   3316:                             } else {
                   3317:                                 $message .= &mt('User [_1] at domain [_2] has a non-student role in this course',
                   3318:                                                 $uname,$udom);
                   3319:                             }
                   3320:                             $message .= '</span>';
                   3321:                         }
                   3322:                     }
1.594     raeburn  3323:                 } else {
1.596     raeburn  3324:                     $message = '<span class="LC_warning">';
                   3325:                     if ($crstype eq 'Community') {
                   3326:                         $message .= &mt('User [_1] at domain [_2] does not have a member role in this community',
                   3327:                                          $uname,$udom);
                   3328:                     } else {
                   3329:                          $message .= &mt('User [_1] at domain [_2] does not have a student role in this course',
                   3330:                                          $uname,$udom);
                   3331:                     }
                   3332:                     $message .= '</span>';
                   3333:                     $uname='';
                   3334:                     if ($env{'request.course.sec'} ne '') {
                   3335:                         $csec=$env{'request.course.sec'};
                   3336:                     } else {
                   3337:                         $csec=$env{'form.csec'};
                   3338:                     }
                   3339:                     $cgroup=$env{'form.cgroup'};
1.594     raeburn  3340:                 }
                   3341:             } elsif ($env{'request.course.sec'} ne '') {
                   3342:                 if ($csec ne $env{'request.course.sec'}) {
1.596     raeburn  3343:                     $message='<span class="LC_warning">'.
1.594     raeburn  3344:                               &mt("User '[_1]' at domain '[_2]' not in section '[_3]'",
                   3345:                                   $uname,$udom,$env{'request.course.sec'}).
                   3346:                               '</span>';
                   3347:                     $uname='';
                   3348:                     $csec=$env{'request.course.sec'};
                   3349:                 }
1.269     raeburn  3350:                 $cgroup=$env{'form.cgroup'};
1.596     raeburn  3351:             }
                   3352:             if ($uname ne '') {
1.473     amueller 3353:                 my %name=&Apache::lonnet::userenvironment($udom,$uname,
                   3354:                   ('firstname','middlename','lastname','generation','id'));
1.596     raeburn  3355:                 $message .= "\n<p>\n".&mt('Full Name').': '
                   3356:                             .$name{'firstname'}.' '.$name{'middlename'}.' '
                   3357:                             .$name{'lastname'}.' '.$name{'generation'}
                   3358:                             ."<br />\n".&mt('Student/Employee ID').': '.$name{'id'}.'</p>';
                   3359:                 @usersgroups = &Apache::lonnet::get_users_groups(
                   3360:                                    $udom,$uname,$env{'request.course.id'});
                   3361:                 if (@usersgroups > 0) {
                   3362:                     unless (grep(/^\Q$cgroup\E$/,@usersgroups)) {
                   3363:                         $cgroup = $usersgroups[0];
                   3364:                     }
                   3365:                 } else {
                   3366:                     $cgroup = '';
1.297     raeburn  3367:                 }
1.269     raeburn  3368:             }
1.12      www      3369:         }
1.43      albertel 3370:     }
1.2       www      3371: 
1.43      albertel 3372:     unless ($csec) { $csec=''; }
1.269     raeburn  3373:     unless ($cgroup) { $cgroup=''; }
1.12      www      3374: 
1.14      www      3375: # --------------------------------------------------------- Get all assessments
1.446     bisitz   3376:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 3377:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  3378:                 \%keyorder,undef,$pssymb);
1.63      bowersj2 3379: 
1.582     raeburn  3380:     %allmaps_inverted = reverse(%allmaps);
                   3381: 
1.57      albertel 3382:     $mapp{'0.0'} = '';
                   3383:     $symbp{'0.0'} = '';
1.99      albertel 3384: 
1.14      www      3385: # ---------------------------------------------------------- Anything to store?
1.568     raeburn  3386:     if ($env{'form.pres_marker'} && $parm_permission->{'edit'}) {
1.205     www      3387:         my @markers=split(/\&\&\&/,$env{'form.pres_marker'});
                   3388:         my @values=split(/\&\&\&/,$env{'form.pres_value'});
                   3389:         my @types=split(/\&\&\&/,$env{'form.pres_type'});
1.500     raeburn  3390:         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   3391:         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.504     raeburn  3392:         my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   3393:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   3394:         my $totalstored = 0;
1.605     raeburn  3395:         my $totalskippeduser = 0;
1.546     raeburn  3396:         my $now = time;
1.473     amueller 3397:         for (my $i=0;$i<=$#markers;$i++) {
1.557     raeburn  3398:             my ($needsrelease,$needsnewer,$name,$namematch);
1.556     raeburn  3399:             if (($env{'request.course.sec'} ne '') && ($markers[$i] =~ /\&(9|10|11|12)$/)) {
1.552     raeburn  3400:                 next if ($csec ne $env{'request.course.sec'});
                   3401:             }
1.556     raeburn  3402:             if ($markers[$i] =~ /\&(8|7|6|5)$/) {
1.553     raeburn  3403:                 next if ($noeditgrp);
1.605     raeburn  3404:             } elsif ($markers[$i] =~ /\&(4|3|2|1)$/) {
                   3405:                 if ($uname eq '') {
                   3406:                     $totalskippeduser ++;
                   3407:                     next;
                   3408:                 }
1.557     raeburn  3409:             }
                   3410:             if ($markers[$i] =~ /\&(17|11|7|3)$/) {
                   3411:                 $namematch = 'maplevelrecurse';
                   3412:             }
1.556     raeburn  3413:             if ($markers[$i] =~ /^[\d.]+\&0_availablestudent\&(1|2|3|4)$/) {
1.437     raeburn  3414:                 my (@ok_slots,@fail_slots,@del_slots);
                   3415:                 my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
                   3416:                 my ($level,@all) =
                   3417:                     &parmval_by_symb('0.availablestudent',$pssymb,'',$uname,$udom,
                   3418:                                      $csec,$cgroup,$courseopt);
                   3419:                 foreach my $slot_name (split(/:/,$values[$i])) {
                   3420:                     next if ($slot_name eq '');
                   3421:                     if (&update_slots($slot_name,$cdom,$cnum,$pssymb,$uname,$udom) eq 'ok') {
                   3422:                         push(@ok_slots,$slot_name);
                   3423: 
                   3424:                     } else {
                   3425:                         push(@fail_slots,$slot_name);
                   3426:                     }
                   3427:                 }
                   3428:                 if (@ok_slots) {
                   3429:                     $values[$i] = join(':',@ok_slots);
                   3430:                 } else {
                   3431:                     $values[$i] = '';
                   3432:                 }
                   3433:                 if ($all[$level] ne '') {
                   3434:                     my @existing = split(/:/,$all[$level]);
                   3435:                     foreach my $slot_name (@existing) {
                   3436:                         if (!grep(/^\Q$slot_name\E$/,split(/:/,$values[$i]))) {
                   3437:                             if (&delete_slots($slot_name,$cdom,$cnum,$uname,$udom,$pssymb) eq 'ok') {
                   3438:                                 push(@del_slots,$slot_name);
                   3439:                             }
                   3440:                         }
                   3441:                     }
                   3442:                 }
1.554     raeburn  3443:             } elsif ($markers[$i] =~ /_(type|lenient|retrypartial|discussvote|examcode|printstartdate|printenddate|acc|interval)\&\d+$/) {
1.514     raeburn  3444:                 $name = $1;
1.533     raeburn  3445:                 my $val = $values[$i];
1.549     raeburn  3446:                 my $valmatch = '';
1.533     raeburn  3447:                 if ($name eq 'examcode') {
1.544     raeburn  3448:                     if (&Apache::lonnet::validCODE($values[$i])) {
                   3449:                         $val = 'valid';
                   3450:                     }
1.546     raeburn  3451:                 } elsif ($name eq 'printstartdate') {
                   3452:                     if ($val =~ /^\d+$/) {
                   3453:                         if ($val > $now) {
                   3454:                             $val = 'future';
                   3455:                         }
                   3456:                     } 
                   3457:                 } elsif ($name eq 'printenddate') {
                   3458:                     if ($val =~ /^\d+$/) {
                   3459:                         if ($val < $now) {
                   3460:                             $val = 'past';
                   3461:                         }
                   3462:                     }
1.549     raeburn  3463:                 } elsif (($name eq 'lenient') || ($name eq 'acc')) {
                   3464:                     my $stringtype = &get_stringtype($name);
                   3465:                     my $stringmatch = &standard_string_matches($stringtype);
                   3466:                     if (ref($stringmatch) eq 'ARRAY') {
                   3467:                         foreach my $item (@{$stringmatch}) {
                   3468:                             if (ref($item) eq 'ARRAY') {
                   3469:                                 my ($regexpname,$pattern) = @{$item};
                   3470:                                 if ($pattern ne '') {
                   3471:                                     if ($val =~ /$pattern/) {
                   3472:                                         $valmatch = $regexpname;
                   3473:                                         $val = '';
                   3474:                                         last;
                   3475:                                     }
                   3476:                                 }
                   3477:                             }
                   3478:                         }
                   3479:                     }
1.554     raeburn  3480:                 } elsif ($name eq 'interval') {
                   3481:                     my $intervaltype = &get_intervaltype($name);
                   3482:                     my $intervalmatch = &standard_interval_matches($intervaltype);
                   3483:                     if (ref($intervalmatch) eq 'ARRAY') {
                   3484:                         foreach my $item (@{$intervalmatch}) {
                   3485:                             if (ref($item) eq 'ARRAY') {
                   3486:                                 my ($regexpname,$pattern) = @{$item};
                   3487:                                 if ($pattern ne '') {
                   3488:                                     if ($val =~ /$pattern/) {
                   3489:                                         $valmatch = $regexpname;
                   3490:                                         $val = '';
                   3491:                                         last;
                   3492:                                     }
                   3493:                                 }
                   3494:                             }
                   3495:                         }
                   3496:                     }
1.533     raeburn  3497:                 }
1.504     raeburn  3498:                 $needsrelease =
1.557     raeburn  3499:                     $Apache::lonnet::needsrelease{"parameter:$name:$val:$valmatch:"};
1.504     raeburn  3500:                 if ($needsrelease) {
1.505     raeburn  3501:                     unless ($got_chostname) {
1.514     raeburn  3502:                         ($chostname,$cmajor,$cminor) = &parameter_release_vars();
1.504     raeburn  3503:                         $got_chostname = 1;
1.546     raeburn  3504:                     } 
1.557     raeburn  3505:                     $needsnewer = &parameter_releasecheck($name,$val,$valmatch,undef,
1.514     raeburn  3506:                                                           $needsrelease,
                   3507:                                                           $cmajor,$cminor);
1.500     raeburn  3508:                 }
1.437     raeburn  3509:             }
1.504     raeburn  3510:             if ($needsnewer) {
1.557     raeburn  3511:                 undef($namematch);
                   3512:             } else {
                   3513:                 my $currneeded;
                   3514:                 if ($needsrelease) {
                   3515:                     $currneeded = $needsrelease;
                   3516:                 }
                   3517:                 if ($namematch) {
                   3518:                     $needsrelease =
                   3519:                         $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   3520:                     if (($needsrelease) && (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   3521:                         unless ($got_chostname) {
                   3522:                             ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   3523:                             $got_chostname = 1;
                   3524:                         }
                   3525:                         $needsnewer = &parameter_releasecheck(undef,undef,undef,$namematch,
                   3526:                                                               $needsrelease,
                   3527:                                                               $cmajor,$cminor);
                   3528:                     } else {
                   3529:                         undef($namematch);
                   3530:                     }
                   3531:                 }
                   3532:             }
                   3533:             if ($needsnewer) {
                   3534:                 $message .= &oldversion_warning($name,$namematch,$values[$i],$chostname,$cmajor,
1.504     raeburn  3535:                                                 $cminor,$needsrelease);
                   3536:             } else {
                   3537:                 $message.=&storeparm(split(/\&/,$markers[$i]),
                   3538:                                      $values[$i],
                   3539:                                      $types[$i],
                   3540:                                      $uname,$udom,$csec,$cgroup);
                   3541:                 $totalstored ++;
                   3542:             }
1.473     amueller 3543:         }
1.68      www      3544: # ---------------------------------------------------------------- Done storing
1.504     raeburn  3545:         if ($totalstored) {
                   3546:             $message.='<p class="LC_warning">'
1.605     raeburn  3547:                      .&mt('Changes for [quant,_1,parameter] saved.',$totalstored)
                   3548:                      .'<br />'
1.504     raeburn  3549:                      .&mt('Changes can take up to 10 minutes before being active for all students.')
                   3550:                      .&Apache::loncommon::help_open_topic('Caching')
                   3551:                      .'</p>';
1.605     raeburn  3552:         } else {
                   3553:             $message.='<p class="LC_info">'.&mt('No parameter changes saved.').'</p>';
                   3554:         }
                   3555:         if ($totalskippeduser) {
                   3556:             $message .= '<p class="LC_warning">';
                   3557:             if ($uhome eq 'no_host') {
                   3558:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the username or ID was invalid.',
                   3559:                                 $totalskippeduser);
                   3560:             } elsif ($env{'form.userroles'} eq 'any') {
                   3561:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user does not have a course role.',
                   3562:                                 $totalskippeduser);
                   3563:             } else {
                   3564:                 $message .= &mt('Changes for [quant,_1,user-specific parameter] not saved because the user is not a student.',
                   3565:                                 $totalskippeduser);
                   3566:             }
                   3567:             $message .= '</p>';
1.504     raeburn  3568:         }
1.68      www      3569:     }
1.584     raeburn  3570: 
1.57      albertel 3571: #----------------------------------------------- if all selected, fill in array
1.563     damieng  3572:     if ($pscat[0] eq "all") {
                   3573:         @pscat = (keys(%allparms));
                   3574:     }
                   3575:     if (!@pscat) {
                   3576:         @pscat=('duedate','opendate','answerdate','weight','maxtries','type','problemstatus')
                   3577:     };
                   3578:     if ($psprt[0] eq "all" || !@psprt) {
                   3579:         @psprt = (keys(%allparts));
                   3580:     }
1.2       www      3581: # ------------------------------------------------------------------ Start page
1.63      bowersj2 3582: 
1.531     raeburn  3583:     my $crstype = &Apache::loncommon::course_type();
                   3584:     &startpage($r,$pssymb,$crstype);
1.57      albertel 3585: 
1.548     raeburn  3586:     foreach my $item ('tolerance','date_default','date_start','date_end',
1.589     raeburn  3587:             'date_interval','int','float','string','string_lenient',
                   3588:             'string_examcode','string_deeplink','string_discussvote',
                   3589:             'string_useslots','string_problemstatus','string_ip',
                   3590:             'string_questiontype') {
1.473     amueller 3591:         $r->print('<input type="hidden" value="'.
1.563     damieng  3592:             &HTML::Entities::encode($env{'form.recent_'.$item},'"&<>').
                   3593:             '" name="recent_'.$item.'" />');
1.44      albertel 3594:     }
1.446     bisitz   3595: 
1.459     bisitz   3596:     # ----- Start Parameter Selection
                   3597: 
1.606   ! raeburn  3598:     # Hide parm selection and possibly table?
        !          3599:     my ($tablejs,$tabledivsty);
        !          3600:     if (((($env{'form.uname'} ne '') || ($env{'form.id'} ne '')) && ($uname eq '')) &&
        !          3601:         ($env{'form.dis'}) && ($pssymb eq '')) {
        !          3602:         $tablejs = 'document.getElementById('."'parmtable'".').style.display = "";';
        !          3603:         $tabledivsty = ' style="display:none"';
        !          3604:     }
1.459     bisitz   3605:     $r->print(<<ENDPARMSELSCRIPT);
                   3606: <script type="text/javascript">
                   3607: // <![CDATA[
                   3608: function parmsel_show() {
1.562     damieng  3609:     document.getElementById('parmsel').style.display = "";
                   3610:     document.getElementById('parmsellink').style.display = "none";
1.606   ! raeburn  3611:     $tablejs
1.459     bisitz   3612: }
                   3613: // ]]>
                   3614: </script>
                   3615: ENDPARMSELSCRIPT
1.474     amueller 3616:     
1.445     neumanie 3617:     if (!$pssymb) {
1.563     damieng  3618:         # No single resource selected, print forms to select things (hidden after first selection)
1.486     www      3619:         my $parmselhiddenstyle=' style="display:none"';
                   3620:         if($env{'form.hideparmsel'} eq 'hidden') {
                   3621:            $r->print('<div id="parmsel"'.$parmselhiddenstyle.'>');
                   3622:         } else  {
                   3623:            $r->print('<div id="parmsel">');
                   3624:         }
                   3625: 
1.491     bisitz   3626:         # Step 1
1.523     raeburn  3627:         $r->print(&Apache::lonhtmlcommon::topic_bar(1,&mt('Resource Specification'),'parmstep1'));
                   3628:         $r->print('
1.474     amueller 3629: <script type="text/javascript">
1.523     raeburn  3630: // <![CDATA['.
                   3631:                  &showhide_js().'
1.474     amueller 3632: // ]]>
                   3633: </script>
1.523     raeburn  3634: ');
                   3635:         $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.209     www      3636:         &levelmenu($r,\%alllevs,$parmlev);
1.491     bisitz   3637:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.474     amueller 3638:         &mapmenu($r,\%allmaps,$pschp,\%maptitles, \%symbp);
1.491     bisitz   3639:         $r->print(&Apache::lonhtmlcommon::row_closure());
                   3640:         $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
                   3641:         &partmenu($r,\%allparts,\@psprt);
1.474     amueller 3642:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3643:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3644: 
                   3645:         # Step 2
1.523     raeburn  3646:         $r->print(&Apache::lonhtmlcommon::topic_bar(2,&mt('Parameter Specification'),'parmstep2'));
1.581     raeburn  3647:         &displaymenu($r,\%allparms,\@pscat,\%keyorder,'parmmenuscroll');
1.491     bisitz   3648: 
                   3649:         # Step 3
1.523     raeburn  3650:         $r->print(&Apache::lonhtmlcommon::topic_bar(3,&mt('User Specification (optional)'),'parmstep3'));
1.486     www      3651:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3652:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3653:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3654:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
1.491     bisitz   3655: 
                   3656:         # Update Display Button
1.486     www      3657:         $r->print('<p>'
                   3658:              .'<input type="submit" name="dis"'
1.511     www      3659:              .' value="'.&mt('Update Display').'" />'
1.486     www      3660:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
                   3661:              .'</p>');
                   3662:         $r->print('</div>');
1.491     bisitz   3663: 
1.486     www      3664:         # Offer link to display parameter selection again
                   3665:         $r->print('<p id="parmsellink"');
                   3666:         if ($env{'form.hideparmsel'} ne 'hidden') {
                   3667:            $r->print($parmselhiddenstyle);
                   3668:         }
                   3669:         $r->print('>'
                   3670:              .'<a href="javascript:parmsel_show()">'
                   3671:              .&mt('Change Parameter Selection')
                   3672:              .'</a>'
                   3673:              .'</p>');
1.44      albertel 3674:     } else {
1.478     amueller 3675:         # parameter screen for a single resource. 
1.486     www      3676:         my ($map,$iid,$resource)=&Apache::lonnet::decode_symb($pssymb);
1.473     amueller 3677:         my $title = &Apache::lonnet::gettitle($pssymb);
1.501     bisitz   3678:         $r->print(&mt('Specific Resource: [_1] ([_2])',
                   3679:                          $title,'<span class="LC_filename">'.$resource.'</span>').
1.472     amueller 3680:                 '<input type="hidden" value="'.$pssymb.'" name="symb" />'.
1.486     www      3681:                   '<br />');
                   3682:         $r->print(&Apache::lonhtmlcommon::topic_bar('',&mt('Additional Display Specification (optional)')));
                   3683:         $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.553     raeburn  3684:         &usermenu($r,$uname,$id,$udom,$csec,$cgroup,$parmlev,\@usersgroups,$pssymb);
1.486     www      3685:         $r->print(&Apache::lonhtmlcommon::row_closure(1));
                   3686:         $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   3687:         $r->print('<p>'
1.459     bisitz   3688:              .'<input type="submit" name="dis"'
1.511     www      3689:              .' value="'.&mt('Update Display').'" />'
1.459     bisitz   3690:              .'<input type="hidden" name="hideparmsel" value="hidden" />'
1.486     www      3691:              .'</p>');
1.459     bisitz   3692:     }
1.478     amueller 3693:     
1.486     www      3694:     # ----- End Parameter Selection
1.57      albertel 3695: 
1.459     bisitz   3696:     # Display Messages
                   3697:     $r->print('<div>'.$message.'</div>');
1.210     www      3698: 
1.57      albertel 3699: 
                   3700:     my @temp_pscat;
                   3701:     map {
                   3702:         my $cat = $_;
                   3703:         push(@temp_pscat, map { $_.'.'.$cat } @psprt);
                   3704:     } @pscat;
                   3705: 
                   3706:     @pscat = @temp_pscat;
                   3707: 
1.548     raeburn  3708: 
1.209     www      3709:     if (($env{'form.prevvisit'}) || ($pschp) || ($pssymb)) {
1.10      www      3710: # ----------------------------------------------------------------- Start Table
1.57      albertel 3711:         my @catmarker=map { tr|.|_|; 'parameter_'.$_; } @pscat;
1.190     albertel 3712:         my $csuname=$env{'user.name'};
                   3713:         my $csudom=$env{'user.domain'};
1.568     raeburn  3714:         my $readonly = 1;
                   3715:         if ($parm_permission->{'edit'}) {
                   3716:             undef($readonly); 
                   3717:         }
1.606   ! raeburn  3718:         $r->print('<div id="parmtable"'.$tabledivsty.'>');
1.57      albertel 3719: 
1.203     www      3720:         if ($parmlev eq 'full') {
1.506     www      3721: #
                   3722: # This produces the cascading table output of parameters
                   3723: #
1.578     raeburn  3724:             my $coursespan=$csec?8:5;
                   3725:             my $userspan=3;
1.560     damieng  3726:             if ($cgroup ne '') {
1.578     raeburn  3727:                 $coursespan += 3;
1.560     damieng  3728:             }
1.473     amueller 3729: 
1.560     damieng  3730:             $r->print(&Apache::loncommon::start_data_table());
                   3731:             #
                   3732:             # This produces the headers
                   3733:             #
                   3734:             $r->print('<tr><td colspan="5"></td>');
                   3735:             $r->print('<th colspan="'.($coursespan).'">'.&mt('Any User').'</th>');
                   3736:             if ($uname) {
1.473     amueller 3737:                 if (@usersgroups > 1) {
1.560     damieng  3738:                     $userspan ++;
                   3739:                 }
                   3740:                 $r->print('<th colspan="'.$userspan.'" rowspan="2">');
                   3741:                 $r->print(&mt('User [_1] at Domain [_2]',"'".$uname."'","'".$udom."'").'</th>');
                   3742:             }
                   3743:             my %lt=&Apache::lonlocal::texthash(
1.473     amueller 3744:                 'pie'    => "Parameter in Effect",
                   3745:                 'csv'    => "Current Session Value",
1.472     amueller 3746:                 'rl'     => "Resource Level",
1.473     amueller 3747:                 'ic'     => 'in Course',
                   3748:                 'aut'    => "Assessment URL and Title",
                   3749:                 'type'   => 'Type',
                   3750:                 'emof'   => "Enclosing Map or Folder",
                   3751:                 'part'   => 'Part',
1.472     amueller 3752:                 'pn'     => 'Parameter Name',
1.473     amueller 3753:                 'def'    => 'default',
                   3754:                 'femof'  => 'from Enclosing Map or Folder',
                   3755:                 'gen'    => 'general',
                   3756:                 'foremf' => 'for Enclosing Map or Folder',
                   3757:                 'fr'     => 'for Resource'
                   3758:             );
1.560     damieng  3759:             $r->print(<<ENDTABLETWO);
1.419     bisitz   3760: <th rowspan="3">$lt{'pie'}</th>
1.501     bisitz   3761: <th rowspan="3">$lt{'csv'}<br />($csuname:$csudom)</th>
1.578     raeburn  3762: </tr><tr><td colspan="5"></td><th colspan="2">$lt{'ic'}</th><th colspan="2">$lt{'rl'}</th>
1.419     bisitz   3763: <th colspan="1">$lt{'ic'}</th>
1.182     albertel 3764: 
1.10      www      3765: ENDTABLETWO
1.560     damieng  3766:             if ($csec) {
1.578     raeburn  3767:                 $r->print('<th colspan="3">'.
1.560     damieng  3768:                 &mt("in Section")." $csec</th>");
                   3769:             }
                   3770:             if ($cgroup) {
1.578     raeburn  3771:                 $r->print('<th colspan="3">'.
1.472     amueller 3772:                 &mt("in Group")." $cgroup</th>");
1.560     damieng  3773:             }
                   3774:             $r->print(<<ENDTABLEHEADFOUR);
1.133     www      3775: </tr><tr><th>$lt{'aut'}</th><th>$lt{'type'}</th>
                   3776: <th>$lt{'emof'}</th><th>$lt{'part'}</th><th>$lt{'pn'}</th>
1.578     raeburn  3777: <th>$lt{'gen'}</th><th>$lt{'foremf'}</th>
1.192     albertel 3778: <th>$lt{'def'}</th><th>$lt{'femof'}</th><th>$lt{'fr'}</th>
1.10      www      3779: ENDTABLEHEADFOUR
1.57      albertel 3780: 
1.560     damieng  3781:             if ($csec) {
1.578     raeburn  3782:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3783:             }
1.473     amueller 3784: 
1.560     damieng  3785:             if ($cgroup) {
1.578     raeburn  3786:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3787:             }
                   3788: 
                   3789:             if ($uname) {
                   3790:                 if (@usersgroups > 1) {
                   3791:                     $r->print('<th>'.&mt('Control by other group?').'</th>');
                   3792:                 }
1.578     raeburn  3793:                 $r->print('<th>'.$lt{'gen'}.'</th><th>'.$lt{'foremf'}.'</th><th>'.$lt{'fr'}.'</th>');
1.560     damieng  3794:             }
                   3795: 
                   3796:             $r->print('</tr>');
1.506     www      3797: #
                   3798: # Done with the headers
                   3799: # 
1.560     damieng  3800:             my $defbgone='';
                   3801:             my $defbgtwo='';
                   3802:             my $defbgthree = '';
1.57      albertel 3803: 
1.560     damieng  3804:             foreach my $rid (@ids) {
1.57      albertel 3805: 
                   3806:                 my ($inmapid)=($rid=~/\.(\d+)$/);
1.446     bisitz   3807:                 if ((!$pssymb &&
1.560     damieng  3808:                         (($pschp eq 'all') || ($allmaps{$pschp} eq $mapp{$rid})))
                   3809:                         ||
                   3810:                         ($pssymb && $pssymb eq $symbp{$rid})) {
1.4       www      3811: # ------------------------------------------------------ Entry for one resource
1.473     amueller 3812:                     if ($defbgone eq '#E0E099') {
                   3813:                         $defbgone='#E0E0DD';
1.57      albertel 3814:                     } else {
1.419     bisitz   3815:                         $defbgone='#E0E099';
1.57      albertel 3816:                     }
1.419     bisitz   3817:                     if ($defbgtwo eq '#FFFF99') {
1.473     amueller 3818:                         $defbgtwo='#FFFFDD';
1.57      albertel 3819:                     } else {
1.473     amueller 3820:                         $defbgtwo='#FFFF99';
1.57      albertel 3821:                     }
1.419     bisitz   3822:                     if ($defbgthree eq '#FFBB99') {
                   3823:                         $defbgthree='#FFBBDD';
1.269     raeburn  3824:                     } else {
1.419     bisitz   3825:                         $defbgthree='#FFBB99';
1.269     raeburn  3826:                     }
                   3827: 
1.57      albertel 3828:                     my $thistitle='';
                   3829:                     my %name=   ();
                   3830:                     undef %name;
                   3831:                     my %part=   ();
                   3832:                     my %display=();
                   3833:                     my %type=   ();
                   3834:                     my %default=();
1.196     www      3835:                     my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3836:                     my $toolsymb;
                   3837:                     if ($uri =~ /ext\.tool$/) {
                   3838:                         $toolsymb = $symbp{$rid};
                   3839:                     }
1.57      albertel 3840: 
1.506     www      3841:                     my $filter=$env{'form.filter'};
1.548     raeburn  3842:                     foreach my $tempkeyp (&keysplit($keyp{$rid})) {
1.57      albertel 3843:                         if (grep $_ eq $tempkeyp, @catmarker) {
1.584     raeburn  3844:                             my $parmname=&Apache::lonnet::metadata($uri,$tempkeyp.'.name',$toolsymb);
1.560     damieng  3845:     # We may only want certain parameters listed
                   3846:                             if ($filter) {
                   3847:                                 unless ($filter=~/\Q$parmname\E/) { next; }
                   3848:                             }
                   3849:                             $name{$tempkeyp}=$parmname;
1.584     raeburn  3850:                             $part{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.part',$toolsymb);
1.560     damieng  3851: 
1.584     raeburn  3852:                             my $parmdis=&Apache::lonnet::metadata($uri,$tempkeyp.'.display',$toolsymb);
1.560     damieng  3853:                             if ($allparms{$name{$tempkeyp}} ne '') {
                   3854:                                 my $identifier;
                   3855:                                 if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3856:                                     $identifier = $1;
                   3857:                                 }
                   3858:                                 $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3859:                             } else {
                   3860:                                 $display{$tempkeyp} = $parmdis;
                   3861:                             }
                   3862:                             unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3863:                             $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
1.584     raeburn  3864:                             $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp,$toolsymb);
                   3865:                             $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$tempkeyp.'.type',$toolsymb);
                   3866:                             $thistitle=&Apache::lonnet::metadata($uri,$tempkeyp.'.title',$toolsymb);
1.57      albertel 3867:                         }
                   3868:                     }
1.548     raeburn  3869:                     my $totalparms=scalar(keys(%name));
1.57      albertel 3870:                     if ($totalparms>0) {
1.560     damieng  3871:                         my $firstrow=1;
1.473     amueller 3872:                         my $title=&Apache::lonnet::gettitle($symbp{$rid});
1.582     raeburn  3873:                         my $navmap = Apache::lonnavmaps::navmap->new();
                   3874:                         my @recurseup;
                   3875:                         if (ref($navmap) && $mapp{$rid}) {
                   3876:                             @recurseup = $navmap->recurseup_maps($mapp{$rid});
                   3877:                         }
1.419     bisitz   3878:                         $r->print('<tr><td style="background-color:'.$defbgone.';"'.
1.57      albertel 3879:                              ' rowspan='.$totalparms.
1.419     bisitz   3880:                              '><tt><font size="-1">'.
1.57      albertel 3881:                              join(' / ',split(/\//,$uri)).
                   3882:                              '</font></tt><p><b>'.
1.154     albertel 3883:                              "<a href=\"javascript:openWindow('".
1.473     amueller 3884:                           &Apache::lonnet::clutter($uri).'?symb='.
                   3885:                           &escape($symbp{$rid}).
1.336     albertel 3886:                              "', 'metadatafile', '450', '500', 'no', 'yes');\"".
                   3887:                              " target=\"_self\">$title");
1.57      albertel 3888: 
                   3889:                         if ($thistitle) {
1.473     amueller 3890:                             $r->print(' ('.$thistitle.')');
1.57      albertel 3891:                         }
                   3892:                         $r->print('</a></b></td>');
1.419     bisitz   3893:                         $r->print('<td style="background-color:'.$defbgtwo.';"'.
1.57      albertel 3894:                                       ' rowspan='.$totalparms.'>'.$typep{$rid}.
                   3895:                                       '</td>');
                   3896: 
1.419     bisitz   3897:                         $r->print('<td style="background-color:'.$defbgone.';"'.
1.57      albertel 3898:                                       ' rowspan='.$totalparms.
1.238     www      3899:                                       '>'.$maptitles{$mapp{$rid}}.'</td>');
1.548     raeburn  3900:                         foreach my $item (&keysinorder_bytype(\%name,\%keyorder)) {
1.57      albertel 3901:                             unless ($firstrow) {
                   3902:                                 $r->print('<tr>');
                   3903:                             } else {
                   3904:                                 undef $firstrow;
                   3905:                             }
1.548     raeburn  3906:                             &print_row($r,$item,\%part,\%name,\%symbp,$rid,\%default,
1.57      albertel 3907:                                        \%type,\%display,$defbgone,$defbgtwo,
1.269     raeburn  3908:                                        $defbgthree,$parmlev,$uname,$udom,$csec,
1.582     raeburn  3909:                                        $cgroup,\@usersgroups,$noeditgrp,$readonly,
                   3910:                                        \@recurseup,\%maptitles,\%allmaps_inverted,
                   3911:                                        \$numreclinks);
1.57      albertel 3912:                         }
                   3913:                     }
                   3914:                 }
                   3915:             } # end foreach ids
1.43      albertel 3916: # -------------------------------------------------- End entry for one resource
1.517     www      3917:             $r->print(&Apache::loncommon::end_data_table);
1.203     www      3918:         } # end of  full
1.57      albertel 3919: #--------------------------------------------------- Entry for parm level map
                   3920:         if ($parmlev eq 'map') {
1.419     bisitz   3921:             my $defbgone = '#E0E099';
                   3922:             my $defbgtwo = '#FFFF99';
                   3923:             my $defbgthree = '#FFBB99';
1.57      albertel 3924: 
                   3925:             my %maplist;
                   3926: 
                   3927:             if ($pschp eq 'all') {
1.446     bisitz   3928:                 %maplist = %allmaps;
1.57      albertel 3929:             } else {
                   3930:                 %maplist = ($pschp => $mapp{$pschp});
                   3931:             }
                   3932: 
                   3933: #-------------------------------------------- for each map, gather information
                   3934:             my $mapid;
1.560     damieng  3935:             foreach $mapid (sort {$maplist{$a} cmp $maplist{$b}} keys(%maplist)) {
1.60      albertel 3936:                 my $maptitle = $maplist{$mapid};
1.57      albertel 3937: 
                   3938: #-----------------------  loop through ids and get all parameter types for map
                   3939: #-----------------------------------------          and associated information
                   3940:                 my %name = ();
                   3941:                 my %part = ();
                   3942:                 my %display = ();
                   3943:                 my %type = ();
                   3944:                 my %default = ();
                   3945:                 my $map = 0;
                   3946: 
1.473     amueller 3947: #        $r->print("Catmarker: @catmarker<br />\n");
1.446     bisitz   3948: 
1.548     raeburn  3949:                 foreach my $id (@ids) {
                   3950:                     ($map)=($id =~ /([\d]*?)\./);
                   3951:                     my $rid = $id;
1.446     bisitz   3952: 
1.57      albertel 3953: #                  $r->print("$mapid:$map:   $rid <br /> \n");
                   3954: 
1.560     damieng  3955:                     if ($map eq $mapid) {
1.473     amueller 3956:                         my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  3957:                         my $toolsymb;
                   3958:                         if ($uri =~ /ext\.tool$/) {
                   3959:                             $toolsymb = $symbp{$rid};
                   3960:                         }
1.582     raeburn  3961: 
1.57      albertel 3962: #                    $r->print("Keys: $keyp{$rid} <br />\n");
                   3963: 
                   3964: #--------------------------------------------------------------------
                   3965: # @catmarker contains list of all possible parameters including part #s
                   3966: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   3967: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   3968: # When storing information, store as part 0
                   3969: # When requesting information, request from full part
                   3970: #-------------------------------------------------------------------
1.548     raeburn  3971:                         foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   3972:                             my $tempkeyp = $fullkeyp;
                   3973:                             $tempkeyp =~ s/_\w+_/_0_/;
1.473     amueller 3974: 
1.548     raeburn  3975:                             if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 3976:                                 $part{$tempkeyp}="0";
1.584     raeburn  3977:                                 $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   3978:                                 my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 3979:                                 if ($allparms{$name{$tempkeyp}} ne '') {
                   3980:                                     my $identifier;
                   3981:                                     if ($parmdis =~ /(\s*\[Part.*)$/) {
                   3982:                                         $identifier = $1;
                   3983:                                     }
                   3984:                                     $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   3985:                                 } else {
                   3986:                                     $display{$tempkeyp} = $parmdis;
                   3987:                                 }
                   3988:                                 unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   3989:                                 $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   3990:                                 $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  3991:                                 $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   3992:                                 $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.473     amueller 3993:                               }
                   3994:                         } # end loop through keys
1.560     damieng  3995:                     }
1.57      albertel 3996:                 } # end loop through ids
1.446     bisitz   3997: 
1.57      albertel 3998: #---------------------------------------------------- print header information
1.133     www      3999:                 my $foldermap=&mt($maptitle=~/^uploaded/?'Folder':'Map');
1.82      www      4000:                 my $showtitle=$maptitles{$maptitle}.($maptitle!~/^uploaded/?' ['.$maptitle.']':'');
1.401     bisitz   4001:                 my $tmp="";
1.57      albertel 4002:                 if ($uname) {
1.473     amueller 4003:                     my $person=&Apache::loncommon::plainname($uname,$udom);
1.401     bisitz   4004:                     $tmp.=&mt("User")." <font color=\"red\"><i>$uname \($person\) </i></font> ".
                   4005:                         &mt('in')." \n";
1.57      albertel 4006:                 } else {
1.401     bisitz   4007:                     $tmp.="<font color=\"red\"><i>".&mt('all').'</i></font> '.&mt('users in')." \n";
1.57      albertel 4008:                 }
1.269     raeburn  4009:                 if ($cgroup) {
1.401     bisitz   4010:                     $tmp.=&mt("Group")." <font color=\"red\"><i>$cgroup".
                   4011:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4012:                     $csec = '';
                   4013:                 } elsif ($csec) {
1.401     bisitz   4014:                     $tmp.=&mt("Section")." <font color=\"red\"><i>$csec".
                   4015:                               "</i></font> ".&mt('of')." \n";
1.269     raeburn  4016:                 }
1.401     bisitz   4017:                 $r->print('<div align="center"><h4>'
                   4018:                          .&mt('Set Defaults for All Resources in [_1]Specifically for [_2][_3]'
1.404     bisitz   4019:                              ,$foldermap.'<br /><font color="red"><i>'.$showtitle.'</i></font><br />'
1.401     bisitz   4020:                              ,$tmp
                   4021:                              ,'<font color="red"><i>'.$coursename.'</i></font>'
                   4022:                              )
                   4023:                          ."<br /></h4>\n"
1.422     bisitz   4024:                 );
1.57      albertel 4025: #---------------------------------------------------------------- print table
1.419     bisitz   4026:                 $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4027:                          .&Apache::loncommon::start_data_table_header_row()
                   4028:                          .'<th>'.&mt('Parameter Name').'</th>'
1.578     raeburn  4029:                          .'<th>'.&mt('Value').'</th>'
1.419     bisitz   4030:                          .'<th>'.&mt('Parameter in Effect').'</th>'
                   4031:                          .&Apache::loncommon::end_data_table_header_row()
                   4032:                 );
1.57      albertel 4033: 
1.582     raeburn  4034:                 my $navmap = Apache::lonnavmaps::navmap->new();
                   4035:                 my @recurseup;
                   4036:                 if (ref($navmap)) {
                   4037:                      my $mapres = $navmap->getByMapPc($mapid);
                   4038:                      if (ref($mapres)) {
                   4039:                          @recurseup = $navmap->recurseup_maps($mapres->src());
                   4040:                      }
                   4041:                 }
                   4042: 
                   4043: 
1.548     raeburn  4044:                 foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.473     amueller 4045:                     $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4046:                     &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.269     raeburn  4047:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
1.568     raeburn  4048:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
1.582     raeburn  4049:                            $readonly,\@recurseup,\%maptitles,\%allmaps_inverted,
                   4050:                            \$numreclinks);
1.57      albertel 4051:                 }
1.422     bisitz   4052:                 $r->print(&Apache::loncommon::end_data_table().'</p>'
                   4053:                          .'</div>'
                   4054:                 );
1.57      albertel 4055:             } # end each map
                   4056:         } # end of $parmlev eq map
                   4057: #--------------------------------- Entry for parm level general (Course level)
                   4058:         if ($parmlev eq 'general') {
1.473     amueller 4059:             my $defbgone = '#E0E099';
1.419     bisitz   4060:             my $defbgtwo = '#FFFF99';
                   4061:             my $defbgthree = '#FFBB99';
1.57      albertel 4062: 
                   4063: #-------------------------------------------- for each map, gather information
                   4064:             my $mapid="0.0";
                   4065: #-----------------------  loop through ids and get all parameter types for map
                   4066: #-----------------------------------------          and associated information
                   4067:             my %name = ();
                   4068:             my %part = ();
                   4069:             my %display = ();
                   4070:             my %type = ();
                   4071:             my %default = ();
1.446     bisitz   4072: 
1.548     raeburn  4073:             foreach $id (@ids) {
                   4074:                 my $rid = $id;
1.446     bisitz   4075: 
1.196     www      4076:                 my $uri=&Apache::lonnet::declutter($uris{$rid});
1.584     raeburn  4077:                 my $toolsymb;
                   4078:                 if ($uri =~ /ext\.tool$/) {
                   4079:                     $toolsymb = $symbp{$rid};
                   4080:                 }
1.57      albertel 4081: 
                   4082: #--------------------------------------------------------------------
                   4083: # @catmarker contains list of all possible parameters including part #s
                   4084: # $fullkeyp contains the full part/id # for the extraction of proper parameters
                   4085: # $tempkeyp contains part 0 only (no ids - ie, subparts)
                   4086: # When storing information, store as part 0
                   4087: # When requesting information, request from full part
                   4088: #-------------------------------------------------------------------
1.548     raeburn  4089:                 foreach my $fullkeyp (&keysplit($keyp{$rid})) {
                   4090:                     my $tempkeyp = $fullkeyp;
                   4091:                     $tempkeyp =~ s/_\w+_/_0_/;
                   4092:                     if ((grep $_ eq $fullkeyp, @catmarker) &&(!$name{$tempkeyp})) {
1.473     amueller 4093:                         $part{$tempkeyp}="0";
1.584     raeburn  4094:                         $name{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.name',$toolsymb);
                   4095:                         my $parmdis=&Apache::lonnet::metadata($uri,$fullkeyp.'.display',$toolsymb);
1.473     amueller 4096:                         if ($allparms{$name{$tempkeyp}} ne '') {
                   4097:                             my $identifier;
                   4098:                             if ($parmdis =~ /(\s*\[Part.*)$/) {
                   4099:                                 $identifier = $1;
                   4100:                             }
                   4101:                             $display{$tempkeyp} = $allparms{$name{$tempkeyp}}.$identifier;
                   4102:                         } else {
                   4103:                             $display{$tempkeyp} = $parmdis;
                   4104:                         }
                   4105:                         unless ($display{$tempkeyp}) { $display{$tempkeyp}=''; }
                   4106:                         $display{$tempkeyp}.=' ('.$name{$tempkeyp}.')';
                   4107:                         $display{$tempkeyp} =~ s/_\w+_/_0_/;
1.584     raeburn  4108:                         $default{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp,$toolsymb);
                   4109:                         $type{$tempkeyp}=&Apache::lonnet::metadata($uri,$fullkeyp.'.type',$toolsymb);
1.560     damieng  4110:                     }
1.57      albertel 4111:                 } # end loop through keys
                   4112:             } # end loop through ids
1.446     bisitz   4113: 
1.57      albertel 4114: #---------------------------------------------------- print header information
1.473     amueller 4115:             my $setdef=&mt("Set Defaults for All Resources in Course");
1.57      albertel 4116:             $r->print(<<ENDMAPONE);
1.419     bisitz   4117: <center>
                   4118: <h4>$setdef
1.135     albertel 4119: <font color="red"><i>$coursename</i></font><br />
1.57      albertel 4120: ENDMAPONE
                   4121:             if ($uname) {
1.473     amueller 4122:                 my $person=&Apache::loncommon::plainname($uname,$udom);
1.135     albertel 4123:                 $r->print(" ".&mt("User")."<font color=\"red\"> <i>$uname \($person\) </i></font> \n");
1.57      albertel 4124:             } else {
1.135     albertel 4125:                 $r->print("<i><font color=\"red\"> ".&mt("ALL")."</i> ".&mt("USERS")."</font> \n");
1.57      albertel 4126:             }
1.446     bisitz   4127: 
1.135     albertel 4128:             if ($csec) {$r->print(&mt("Section")."<font color=\"red\"> <i>$csec</i></font>\n")};
1.306     albertel 4129:             if ($cgroup) {$r->print(&mt("Group")."<font color=\"red\"> <i>$cgroup</i></font>\n")};
1.135     albertel 4130:             $r->print("</h4>\n");
1.57      albertel 4131: #---------------------------------------------------------------- print table
1.419     bisitz   4132:             $r->print('<p>'.&Apache::loncommon::start_data_table()
                   4133:                      .&Apache::loncommon::start_data_table_header_row()
                   4134:                      .'<th>'.&mt('Parameter Name').'</th>'
                   4135:                      .'<th>'.&mt('Default Value').'</th>'
                   4136:                      .'<th>'.&mt('Parameter in Effect').'</th>'
                   4137:                      .&Apache::loncommon::end_data_table_header_row()
                   4138:             );
1.57      albertel 4139: 
1.548     raeburn  4140:             foreach my $item (&keysinorder(\%name,\%keyorder)) {
1.419     bisitz   4141:                 $r->print(&Apache::loncommon::start_data_table_row());
1.548     raeburn  4142:                 &print_row($r,$item,\%part,\%name,\%symbp,$mapid,\%default,
1.568     raeburn  4143:                            \%type,\%display,$defbgone,$defbgtwo,$defbgthree,
                   4144:                            $parmlev,$uname,$udom,$csec,$cgroup,'',$noeditgrp,
                   4145:                            $readonly);
1.57      albertel 4146:             }
1.419     bisitz   4147:             $r->print(&Apache::loncommon::end_data_table()
                   4148:                      .'</p>'
                   4149:                      .'</center>'
                   4150:             );
1.57      albertel 4151:         } # end of $parmlev eq general
1.606   ! raeburn  4152:         $r->print('</div>');
1.43      albertel 4153:     }
1.507     www      4154:     $r->print('</form>');
1.582     raeburn  4155:     if ($numreclinks) {
                   4156:         $r->print(<<"END");
                   4157: <form name="recurseform" action="/adm/parmset?action=settable" method="post">
                   4158: <input type="hidden" name="pschp" />
                   4159: <input type="hidden" name="pscat" />
                   4160: <input type="hidden" name="psprt" />
                   4161: <input type="hidden" name="hideparmsel" value="hidden" />
                   4162: </form>
                   4163: <script type="text/javascript">
                   4164: function pjumprec(rid,name,part) {
                   4165:     document.forms.recurseform.pschp.value = rid;
                   4166:     document.forms.recurseform.pscat.value = name;
                   4167:     document.forms.recurseform.psprt.value = part;
                   4168:     document.forms.recurseform.submit();
                   4169:     return false;
                   4170: }
                   4171: </script>
                   4172: END
                   4173:     }
1.507     www      4174:     &endSettingsScreen($r);
                   4175:     $r->print(&Apache::loncommon::end_page());
1.57      albertel 4176: } # end sub assessparms
1.30      www      4177: 
1.560     damieng  4178: 
                   4179: 
1.120     www      4180: ##################################################
1.560     damieng  4181: # OVERVIEW MODE
1.207     www      4182: ##################################################
1.124     www      4183: 
1.563     damieng  4184: my $tableopen; # boolean, true if HTML table is already opened
                   4185: 
                   4186: # Returns HTML with the HTML table start tag and header, unless the table is already opened.
                   4187: # @param {boolean} $readonly - true if values cannot be edited (otherwise more columns are added)
                   4188: # @returns {string}
1.124     www      4189: sub tablestart {
1.576     raeburn  4190:     my ($readonly,$is_map) = @_;
1.124     www      4191:     if ($tableopen) {
1.552     raeburn  4192:         return '';
1.124     www      4193:     } else {
1.552     raeburn  4194:         $tableopen=1;
                   4195:         my $output = &Apache::loncommon::start_data_table().'<tr><th>'.&mt('Parameter').'</th>';
                   4196:         if ($readonly) {
                   4197:             $output .= '<th>'.&mt('Current value').'</th>';
                   4198:         } else {
1.576     raeburn  4199:             $output .= '<th>'.&mt('Delete').'</th>'.
                   4200:                        '<th>'.&mt('Set to ...').'</th>';
                   4201:             if ($is_map) {
                   4202:                 $output .= '<th>'.&mt('Recursive?').'</th>';
                   4203:             }
1.552     raeburn  4204:         }
                   4205:         $output .= '</tr>';
                   4206:         return $output;
1.124     www      4207:     }
                   4208: }
                   4209: 
1.563     damieng  4210: # Returns HTML with the HTML table end tag, unless the table is not opened.
                   4211: # @returns {string}
1.124     www      4212: sub tableend {
                   4213:     if ($tableopen) {
1.560     damieng  4214:         $tableopen=0;
                   4215:         return &Apache::loncommon::end_data_table();
1.124     www      4216:     } else {
1.560     damieng  4217:         return'';
1.124     www      4218:     }
                   4219: }
                   4220: 
1.563     damieng  4221: # Reads course and user information.
                   4222: # 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).
                   4223: # The key for student data is modified with '[useropt:'.username.':'.userdomain.'].'.
                   4224: # If the context is looking for a list, returns a list with the scalar data and the class list.
                   4225: # @param {string} $crs - course number
                   4226: # @param {string} $dom - course domain
                   4227: # @returns {hash reference|Array}
1.207     www      4228: sub readdata {
                   4229:     my ($crs,$dom)=@_;
                   4230: # Read coursedata
                   4231:     my $resourcedata=&Apache::lonnet::get_courseresdata($crs,$dom);
                   4232: # Read userdata
                   4233: 
                   4234:     my $classlist=&Apache::loncoursedata::get_classlist();
1.548     raeburn  4235:     foreach my $user (keys(%$classlist)) {
                   4236:         if ($user=~/^($match_username)\:($match_domain)$/) {
                   4237:             my ($tuname,$tudom)=($1,$2);
                   4238:             my $useropt=&Apache::lonnet::get_userresdata($tuname,$tudom);
                   4239:             foreach my $userkey (keys(%{$useropt})) {
                   4240:                 if ($userkey=~/^\Q$env{'request.course.id'}\E/) {
1.207     www      4241:                     my $newkey=$userkey;
1.548     raeburn  4242:                     $newkey=~s/^($env{'request.course.id'}\.)/$1\[useropt\:$tuname\:$tudom\]\./;
                   4243:                     $$resourcedata{$newkey}=$$useropt{$userkey};
                   4244:                 }
                   4245:             }
1.473     amueller 4246:         }
                   4247:     }
1.552     raeburn  4248:     if (wantarray) {
                   4249:         return ($resourcedata,$classlist);
                   4250:     } else {
                   4251:         return $resourcedata;
                   4252:     }
1.207     www      4253: }
                   4254: 
                   4255: 
1.563     damieng  4256: # Stores parameter data, using form parameters directly.
                   4257: #
                   4258: # 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  4259: # set_* (except settext, setipallow, setipdeny, setdeeplink) - set a parameter value
1.563     damieng  4260: # del_* - remove a parameter
                   4261: # datepointer_* - set a date parameter (value is key_* refering to a set of other form parameters)
                   4262: # dateinterval_* - set a date interval parameter (value refers to more form parameters)
                   4263: # key_* - date values
                   4264: # days_* - for date intervals
                   4265: # hours_* - for date intervals
                   4266: # minutes_* - for date intervals
                   4267: # seconds_* - for date intervals
                   4268: # done_* - for date intervals
                   4269: # typeof_* - parameter type
                   4270: # 
                   4271: # @param {Apache2::RequestRec} $r - the Apache request
                   4272: # @param {string} $crs - course number
                   4273: # @param {string} $dom - course domain
1.208     www      4274: sub storedata {
                   4275:     my ($r,$crs,$dom)=@_;
1.207     www      4276: # Set userlevel immediately
                   4277: # Do an intermediate store of course level
                   4278:     my $olddata=&readdata($crs,$dom);
1.124     www      4279:     my %newdata=();
                   4280:     undef %newdata;
                   4281:     my @deldata=();
1.576     raeburn  4282:     my @delrec=();
                   4283:     my @delnonrec=();
1.124     www      4284:     undef @deldata;
1.504     raeburn  4285:     my ($got_chostname,$chostname,$cmajor,$cminor);
1.546     raeburn  4286:     my $now = time;
1.560     damieng  4287:     foreach my $key (keys(%env)) {
                   4288:         if ($key =~ /^form\.([a-z]+)\_(.+)$/) {
                   4289:             my $cmd=$1;
                   4290:             my $thiskey=$2;
1.576     raeburn  4291:             my ($altkey,$recursive,$tkey,$tkeyrec,$tkeynonrec);
1.588     raeburn  4292:             next if ($cmd eq 'rec' || $cmd eq 'settext' || $cmd eq 'setipallow' || $cmd eq 'setipdeny' || $cmd eq 'setdeeplink');
1.576     raeburn  4293:             if ((($cmd eq 'set') || ($cmd eq 'datepointer') || ($cmd eq 'dateinterval') || ($cmd eq 'del')) && 
                   4294:                  ($thiskey =~ /(?:sequence|page)\Q___(all)\E/)) {
                   4295:                 unless ($thiskey =~ /(encrypturl|hiddenresource)$/) {
                   4296:                     $altkey = $thiskey;
                   4297:                     $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4298:                     if ($env{'form.rec_'.$thiskey}) {
                   4299:                         $recursive = 1;
                   4300:                     }
                   4301:                 }
                   4302:             }
1.560     damieng  4303:             my ($tuname,$tudom)=&extractuser($thiskey);
1.473     amueller 4304:             if ($tuname) {
1.576     raeburn  4305:                 $tkey=$thiskey;
1.560     damieng  4306:                 $tkey=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
1.576     raeburn  4307:                 if ($altkey) {
                   4308:                     $tkeynonrec = $tkey; 
                   4309:                     $tkeyrec = $altkey;
                   4310:                     $tkeyrec=~s/\.\[useropt\:$tuname\:$tudom\]\./\./;
                   4311:                 }
1.560     damieng  4312:             }
                   4313:             if ($cmd eq 'set' || $cmd eq 'datepointer' || $cmd eq 'dateinterval') {
1.563     damieng  4314:                 my ($data, $typeof, $text, $name, $valchk, $valmatch, $namematch);
                   4315:                 if ($cmd eq 'set') {
                   4316:                     $data=$env{$key};
                   4317:                     $valmatch = '';
                   4318:                     $valchk = $data;
                   4319:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4320:                     $text = &mt('Saved modified parameter for');
                   4321:                     if ($typeof eq 'string_questiontype') {
                   4322:                         $name = 'type';
1.588     raeburn  4323:                     } elsif (($typeof eq 'string_lenient') || ($typeof eq 'string_deeplink')) {
                   4324:                         ($name) = ($typeof =~ /^string_(lenient|deeplink)$/);
1.563     damieng  4325:                         my $stringmatch = &standard_string_matches($typeof);
                   4326:                         if (ref($stringmatch) eq 'ARRAY') {
                   4327:                             foreach my $item (@{$stringmatch}) {
                   4328:                                 if (ref($item) eq 'ARRAY') {
                   4329:                                     my ($regexpname,$pattern) = @{$item};
                   4330:                                     if ($pattern ne '') {
                   4331:                                         if ($data =~ /$pattern/) {
                   4332:                                             $valmatch = $regexpname;
                   4333:                                             $valchk = '';
                   4334:                                             last;
                   4335:                                         }
1.560     damieng  4336:                                     }
1.549     raeburn  4337:                                 }
                   4338:                             }
                   4339:                         }
1.563     damieng  4340:                     } elsif ($typeof eq 'string_discussvote') {
                   4341:                         $name = 'discussvote';
                   4342:                     } elsif ($typeof eq 'string_examcode') {
                   4343:                         $name = 'examcode';
                   4344:                         if (&Apache::lonnet::validCODE($data)) {
                   4345:                             $valchk = 'valid';
                   4346:                         }
                   4347:                     } elsif ($typeof eq 'string_yesno') {
                   4348:                         if ($thiskey =~ /\.retrypartial$/) {
                   4349:                             $name = 'retrypartial';
                   4350:                         }
1.549     raeburn  4351:                     }
1.563     damieng  4352:                 } elsif ($cmd eq 'datepointer') {
                   4353:                     $data=&Apache::lonhtmlcommon::get_date_from_form($env{$key});
                   4354:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4355:                     $text = &mt('Saved modified date for');
                   4356:                     if ($typeof eq 'date_start') {
                   4357:                         if ($thiskey =~ /\.printstartdate$/) {
                   4358:                             $name = 'printstartdate';
                   4359:                             if (($data) && ($data > $now)) {
                   4360:                                 $valchk = 'future';
                   4361:                             }
1.560     damieng  4362:                         }
1.563     damieng  4363:                     } elsif ($typeof eq 'date_end') {
                   4364:                         if ($thiskey =~ /\.printenddate$/) {
                   4365:                             $name = 'printenddate';
                   4366:                             if (($data) && ($data < $now)) {
                   4367:                                 $valchk = 'past';
                   4368:                             }
1.560     damieng  4369:                         }
1.504     raeburn  4370:                     }
1.563     damieng  4371:                 } elsif ($cmd eq 'dateinterval') {
                   4372:                     $data=&get_date_interval_from_form($thiskey);
                   4373:                     if ($thiskey =~ /\.interval$/) {
                   4374:                         $name = 'interval';
                   4375:                         my $intervaltype = &get_intervaltype($name);
                   4376:                         my $intervalmatch = &standard_interval_matches($intervaltype);
                   4377:                         if (ref($intervalmatch) eq 'ARRAY') {
                   4378:                             foreach my $item (@{$intervalmatch}) {
                   4379:                                 if (ref($item) eq 'ARRAY') {
                   4380:                                     my ($regexpname,$pattern) = @{$item};
                   4381:                                     if ($pattern ne '') {
                   4382:                                         if ($data =~ /$pattern/) {
                   4383:                                             $valmatch = $regexpname;
                   4384:                                             $valchk = '';
                   4385:                                             last;
                   4386:                                         }
1.560     damieng  4387:                                     }
1.554     raeburn  4388:                                 }
                   4389:                             }
                   4390:                         }
                   4391:                     }
1.563     damieng  4392:                     $typeof=$env{'form.typeof_'.$thiskey};
                   4393:                     $text = &mt('Saved modified date for');
1.554     raeburn  4394:                 }
1.576     raeburn  4395:                 if ($recursive) {
1.563     damieng  4396:                     $namematch = 'maplevelrecurse';
1.560     damieng  4397:                 }
1.563     damieng  4398:                 if (($name ne '') || ($namematch ne '')) {
                   4399:                     my ($needsrelease,$needsnewer);
                   4400:                     if ($name ne '') {
                   4401:                         $needsrelease = $Apache::lonnet::needsrelease{"parameter:$name:$valchk:$valmatch:"};
1.560     damieng  4402:                         if ($needsrelease) {
                   4403:                             unless ($got_chostname) {
1.563     damieng  4404:                                 ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.560     damieng  4405:                                 $got_chostname = 1;
                   4406:                             }
1.563     damieng  4407:                             $needsnewer = &parameter_releasecheck($name,$valchk,$valmatch,undef,
                   4408:                                                                 $needsrelease,
                   4409:                                                                 $cmajor,$cminor);
                   4410:                         }
                   4411:                     }
                   4412:                     if ($namematch ne '') {
                   4413:                         if ($needsnewer) {
                   4414:                             undef($namematch);
1.560     damieng  4415:                         } else {
1.563     damieng  4416:                             my $currneeded;
                   4417:                             if ($needsrelease) {
                   4418:                                 $currneeded = $needsrelease;
                   4419:                             }
                   4420:                             $needsrelease =
                   4421:                                 $Apache::lonnet::needsrelease{"parameter::::$namematch"};
                   4422:                             if (($needsrelease) &&
                   4423:                                     (($currneeded eq '') || ($needsrelease < $currneeded))) {
                   4424:                                 unless ($got_chostname) {
                   4425:                                     ($chostname,$cmajor,$cminor) = &parameter_release_vars();
                   4426:                                     $got_chostname = 1;
                   4427:                                 }
                   4428:                                 $needsnewer = &parameter_releasecheck(undef,$valchk,$valmatch,
                   4429:                                     $namematch, $needsrelease,$cmajor,$cminor);
                   4430:                             } else {
                   4431:                                 undef($namematch);
                   4432:                             }
1.560     damieng  4433:                         }
1.557     raeburn  4434:                     }
1.563     damieng  4435:                     if ($needsnewer) {
                   4436:                         $r->print('<br />'.&oldversion_warning($name,$namematch,$data,
                   4437:                                                             $chostname,$cmajor,
                   4438:                                                             $cminor,$needsrelease));
                   4439:                         next;
                   4440:                     }
1.504     raeburn  4441:                 }
1.576     raeburn  4442:                 my ($reconlychg,$haschange,$storekey);
                   4443:                 if ($tuname) {
                   4444:                     my $ustorekey;
                   4445:                     if ($altkey) {
                   4446:                         if ($recursive) {
                   4447:                             if (exists($$olddata{$thiskey})) {
                   4448:                                 if ($$olddata{$thiskey} eq $data) {
                   4449:                                     $reconlychg = 1;
                   4450:                                 }
                   4451:                                 &Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname);
                   4452:                             }
                   4453:                             if (exists($$olddata{$altkey})) {
                   4454:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4455:                                     $haschange = 1;
                   4456:                                 }
                   4457:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4458:                                 $haschange = 1;
                   4459:                             }
                   4460:                             $ustorekey = $tkeyrec;
                   4461:                         } else {
                   4462:                             if (exists($$olddata{$altkey})) {
                   4463:                                 if ($$olddata{$altkey} eq $data) {
                   4464:                                     $reconlychg = 1;
                   4465:                                 }
                   4466:                                 &Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname);
                   4467:                             }
                   4468:                             if (exists($$olddata{$thiskey})) {
                   4469:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4470:                                     $haschange = 1;
                   4471:                                 }
                   4472:                             } elsif ((!$reconlychg) && ($data ne '')) {
                   4473:                                 $haschange = 1;
                   4474:                             }
                   4475:                             $ustorekey = $tkeynonrec;
                   4476:                         }
                   4477:                     } else {
                   4478:                         if (exists($$olddata{$tkey})) {
                   4479:                             if (defined($data) && $$olddata{$tkey} ne $data) {
                   4480:                                 $haschange = 1;
                   4481:                             }
                   4482:                             $ustorekey = $tkey;
                   4483:                         }
                   4484:                     }
                   4485:                     if ($haschange || $reconlychg)  {
                   4486:                         unless ($env{'form.del_'.$thiskey}) {
                   4487:                             if (&Apache::lonnet::put('resourcedata',{$ustorekey=>$data,
                   4488:                                                                      $ustorekey.'.type' => $typeof},
                   4489:                                                                      $tudom,$tuname) eq 'ok') {
                   4490:                                 &log_parmset({$ustorekey=>$data,$ustorekey.'.type' => $typeof},0,$tuname,$tudom);
                   4491:                                 $r->print('<br />'.$text.' '.
                   4492:                                           &Apache::loncommon::plainname($tuname,$tudom));
                   4493:                             } else {
                   4494:                                 $r->print('<div class="LC_error">'.
                   4495:                                           &mt('Error saving parameters').'</div>');
                   4496:                             }
                   4497:                             &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4498:                         }
                   4499:                     }
                   4500:                 } else {
                   4501:                     if ($altkey) {
                   4502:                         if ($recursive) {
                   4503:                             if (exists($$olddata{$thiskey})) {
                   4504:                                 if ($$olddata{$thiskey} eq $data) {
                   4505:                                     $reconlychg = 1;
                   4506:                                 }
                   4507:                                 push(@delnonrec,($thiskey,$thiskey.'.type'));
                   4508:                             }
                   4509:                             if (exists($$olddata{$altkey})) {
                   4510:                                 if (defined($data) && $$olddata{$altkey} ne $data) {
                   4511:                                     $haschange = 1;
                   4512:                                 }
                   4513:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4514:                                 $haschange = 1;
                   4515:                             }
                   4516:                             $storekey = $altkey;
1.563     damieng  4517:                         } else {
1.576     raeburn  4518:                             if (exists($$olddata{$altkey})) {
                   4519:                                 if ($$olddata{$altkey} eq $data) {
                   4520:                                     $reconlychg = 1;
                   4521:                                 }
                   4522:                                 push(@delrec,($altkey,$altkey.'.type'));
                   4523:                             } 
                   4524:                             if (exists($$olddata{$thiskey})) {
                   4525:                                 if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4526:                                     $haschange = 1;
                   4527:                                 }
                   4528:                             } elsif (($data ne '') && (!$reconlychg)) {
                   4529:                                 $haschange = 1;
                   4530:                             }
                   4531:                             $storekey = $thiskey;
1.563     damieng  4532:                         }
1.560     damieng  4533:                     } else {
1.576     raeburn  4534:                         if (defined($data) && $$olddata{$thiskey} ne $data) {
                   4535:                             $haschange = 1;
                   4536:                             $storekey = $thiskey;
                   4537:                         }
                   4538:                     }
                   4539:                 }
                   4540:                 if ($reconlychg || $haschange) {
                   4541:                     unless ($env{'form.del_'.$thiskey}) {
                   4542:                         $newdata{$storekey}=$data;
                   4543:                         $newdata{$storekey.'.type'}=$typeof;
1.560     damieng  4544:                     }
                   4545:                 }
                   4546:             } elsif ($cmd eq 'del') {
                   4547:                 if ($tuname) {
1.576     raeburn  4548:                     my $error;
                   4549:                     if ($altkey) {  
                   4550:                         if (exists($$olddata{$altkey})) {
                   4551:                             if (&Apache::lonnet::del('resourcedata',[$tkeyrec,$tkeyrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4552:                                 &log_parmset({$tkeyrec=>''},1,$tuname,$tudom);
                   4553:                                 if ($recursive) {
                   4554:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4555:                                 }
                   4556:                             } elsif ($recursive) {
                   4557:                                 $error = 1;
                   4558:                             }
                   4559:                         }
                   4560:                         if (exists($$olddata{$thiskey})) {
                   4561:                             if (&Apache::lonnet::del('resourcedata',[$tkeynonrec,$tkeynonrec.'.type'],$tudom,$tuname) eq 'ok') {
                   4562:                                 &log_parmset({$tkeynonrec=>''},1,$tuname,$tudom);
                   4563:                                 unless ($recursive) {
                   4564:                                     $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4565:                                 }
                   4566:                             } elsif (!$recursive) {
                   4567:                                 $error = 1;
                   4568:                             }
                   4569:                         }
1.560     damieng  4570:                     } else {
1.576     raeburn  4571:                         if (exists($$olddata{$thiskey})) {
                   4572:                             if (&Apache::lonnet::del('resourcedata',[$tkey,$tkey.'.type'],$tudom,$tuname) eq 'ok') {
                   4573:                                 &log_parmset({$tkey=>''},1,$tuname,$tudom);
                   4574:                                 $r->print('<br />'.&mt('Deleted parameter for').' '.&Apache::loncommon::plainname($tuname,$tudom));
                   4575:                             } else {
                   4576:                                 $error = 1;
                   4577:                             }
                   4578:                         }
                   4579:                     }
                   4580:                     if ($error) { 
1.560     damieng  4581:                         $r->print('<div class="LC_error">'.
                   4582:                             &mt('Error deleting parameters').'</div>');
                   4583:                     }
                   4584:                     &Apache::lonnet::devalidateuserresdata($tuname,$tudom);
                   4585:                 } else {
1.576     raeburn  4586:                     if ($altkey) {
                   4587:                         if (exists($$olddata{$altkey})) {
                   4588:                             unless (grep(/^\Q$altkey\E$/,@delrec)) {
                   4589:                                 push(@deldata,($altkey,$altkey.'.type'));
                   4590:                             }
                   4591:                         }
                   4592:                         if (exists($$olddata{$thiskey})) {
                   4593:                             unless (grep(/^\Q$thiskey\E$/,@delnonrec)) {
                   4594:                                 push(@deldata,($thiskey,$thiskey.'.type'));
                   4595:                             }
                   4596:                         }
                   4597:                     } elsif (exists($$olddata{$thiskey})) {
                   4598:                         push(@deldata,($thiskey,$thiskey.'.type'));
                   4599:                     }
1.560     damieng  4600:                 }
1.473     amueller 4601:             }
                   4602:         }
                   4603:     }
1.207     www      4604: # Store all course level
1.144     www      4605:     my $delentries=$#deldata+1;
1.576     raeburn  4606:     my @alldels;
                   4607:     if (@delrec) {
                   4608:         push(@alldels,@delrec);
                   4609:     }
                   4610:     if (@delnonrec) {
                   4611:         push(@alldels,@delnonrec);
                   4612:     }
                   4613:     if (@deldata) {
                   4614:         push(@alldels,@deldata);
                   4615:     }
1.548     raeburn  4616:     my @newdatakeys=keys(%newdata);
1.144     www      4617:     my $putentries=$#newdatakeys+1;
1.576     raeburn  4618:     my ($delresult,$devalidate);
                   4619:     if (@alldels) {
                   4620:         if (&Apache::lonnet::del('resourcedata',\@alldels,$dom,$crs) eq 'ok') {
                   4621:             my %loghash=map { $_ => '' } @alldels;
1.560     damieng  4622:             &log_parmset(\%loghash,1);
1.576     raeburn  4623:             if ($delentries) {
                   4624:                 $r->print('<h2>'.&mt('Deleted [quant,_1,parameter]',$delentries/2).'</h2>');
                   4625:             }
                   4626:         } elsif ($delentries) {
1.560     damieng  4627:             $r->print('<div class="LC_error">'.
                   4628:                 &mt('Error deleting parameters').'</div>');
                   4629:         }
1.576     raeburn  4630:         $devalidate = 1; 
1.144     www      4631:     }
                   4632:     if ($putentries) {
1.560     damieng  4633:         if (&Apache::lonnet::put('resourcedata',\%newdata,$dom,$crs) eq 'ok') {
                   4634:                     &log_parmset(\%newdata,0);
                   4635:             $r->print('<h3>'.&mt('Saved [quant,_1,parameter]',$putentries/2).'</h3>');
                   4636:         } else {
                   4637:             $r->print('<div class="LC_error">'.
                   4638:                 &mt('Error saving parameters').'</div>');
                   4639:         }
1.576     raeburn  4640:         $devalidate = 1; 
                   4641:     }
                   4642:     if ($devalidate) {
1.560     damieng  4643:         &Apache::lonnet::devalidatecourseresdata($crs,$dom);
1.144     www      4644:     }
1.208     www      4645: }
1.207     www      4646: 
1.563     damieng  4647: # Returns the username and domain from a key created in readdata from a resourcedata key.
                   4648: #
                   4649: # @param {string} $key - the key
                   4650: # @returns {Array}
1.208     www      4651: sub extractuser {
                   4652:     my $key=shift;
1.350     albertel 4653:     return ($key=~/^$env{'request.course.id'}.\[useropt\:($match_username)\:($match_domain)\]\./);
1.208     www      4654: }
1.206     www      4655: 
1.563     damieng  4656: # Parses a parameter key and returns the components.
                   4657: #
                   4658: # @param {string} $key - 
                   4659: # @param {hash reference} $listdata - 
                   4660: # @return {Array} - (student, resource, part, parameter)
1.381     albertel 4661: sub parse_listdata_key {
                   4662:     my ($key,$listdata) = @_;
                   4663:     # split into student/section affected, and
                   4664:     # the realm (folder/resource part and parameter
1.446     bisitz   4665:     my ($student,$realm) =
1.473     amueller 4666:     ($key=~/^\Q$env{'request.course.id'}\E\.\[([^\.]+)\]\.(.+)$/);
1.381     albertel 4667:     # if course wide student would be undefined
                   4668:     if (!defined($student)) {
1.560     damieng  4669:         ($realm)=($key=~/^\Q$env{'request.course.id'}\E\.(.+)$/);
1.381     albertel 4670:     }
                   4671:     # strip off the .type if it's not the Question type parameter
                   4672:     if ($realm=~/\.type$/ && !exists($listdata->{$key.'.type'})) {
1.560     damieng  4673:         $realm=~s/\.type//;
1.381     albertel 4674:     }
                   4675:     # split into resource+part and parameter name
1.388     albertel 4676:     my ($res,    $parm) = ($realm=~/^(.*)\.(.*)$/);
                   4677:        ($res, my $part) = ($res  =~/^(.*)\.(.*)$/);
1.381     albertel 4678:     return ($student,$res,$part,$parm);
                   4679: }
                   4680: 
1.563     damieng  4681: # Prints HTML with forms for the given parameter data in overview mode (newoverview or overview).
                   4682: #
                   4683: # @param {Apache2::RequestRec} $r - the Apache request
                   4684: # @param {hash reference} $resourcedata - parameter data returned by readdata
                   4685: # @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
                   4686: # @param {string} $sortorder - realmstudent|studentrealm
                   4687: # @param {string} $caller - name of the calling sub (overview|newoverview)
                   4688: # @param {hash reference} $classlist - from loncoursedata::get_classlist
1.568     raeburn  4689: # @param {boolean} $readonly - true if editing not allowed
1.563     damieng  4690: # @returns{integer} - number of $listdata parameters processed
1.208     www      4691: sub listdata {
1.568     raeburn  4692:     my ($r,$resourcedata,$listdata,$sortorder,$caller,$classlist,$readonly)=@_;
1.552     raeburn  4693:     
1.207     www      4694: # Start list output
1.206     www      4695: 
1.122     www      4696:     my $oldsection='';
                   4697:     my $oldrealm='';
                   4698:     my $oldpart='';
1.123     www      4699:     my $pointer=0;
1.124     www      4700:     $tableopen=0;
1.145     www      4701:     my $foundkeys=0;
1.248     albertel 4702:     my %keyorder=&standardkeyorder();
1.594     raeburn  4703:     my $readonlyall = $readonly;
1.381     albertel 4704: 
1.552     raeburn  4705:     my ($secidx,%grouphash);
                   4706:     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4707:         $secidx = &Apache::loncoursedata::CL_SECTION();
1.553     raeburn  4708:         if (&Apache::lonnet::allowed('mdg',$env{'request.course.id'})) {
                   4709:             %grouphash = &Apache::longroup::coursegroups();
                   4710:         } elsif ($env{'request.course.groups'} ne '') {
1.585     raeburn  4711:             map { $grouphash{$_} = 1; } split(/:/,$env{'request.course.groups'});
1.553     raeburn  4712:         }
1.552     raeburn  4713:     }
                   4714: 
1.576     raeburn  4715:     foreach my $key (sort {
1.560     damieng  4716:         my ($astudent,$ares,$apart,$aparm) = &parse_listdata_key($a,$listdata);
                   4717:         my ($bstudent,$bres,$bpart,$bparm) = &parse_listdata_key($b,$listdata);
1.381     albertel 4718: 
1.560     damieng  4719:         # get the numerical order for the param
                   4720:         $aparm=$keyorder{'parameter_0_'.$aparm};
                   4721:         $bparm=$keyorder{'parameter_0_'.$bparm};
1.381     albertel 4722: 
1.560     damieng  4723:         my $result=0;
1.381     albertel 4724: 
1.560     damieng  4725:         if ($sortorder eq 'realmstudent') {
1.381     albertel 4726:             if ($ares     ne $bres    ) {
1.560     damieng  4727:                 $result = ($ares     cmp $bres);
1.446     bisitz   4728:             } elsif ($astudent ne $bstudent) {
1.560     damieng  4729:                 $result = ($astudent cmp $bstudent);
                   4730:             } elsif ($apart    ne $bpart   ) {
                   4731:                 $result = ($apart    cmp $bpart);
                   4732:             }
                   4733:         } else {
                   4734:             if      ($astudent ne $bstudent) {
                   4735:                 $result = ($astudent cmp $bstudent);
                   4736:             } elsif ($ares     ne $bres    ) {
                   4737:                 $result = ($ares     cmp $bres);
                   4738:             } elsif ($apart    ne $bpart   ) {
                   4739:                 $result = ($apart    cmp $bpart);
                   4740:             }
1.473     amueller 4741:         }
1.446     bisitz   4742: 
1.560     damieng  4743:         if (!$result) {
1.381     albertel 4744:             if (defined($aparm) && defined($bparm)) {
1.560     damieng  4745:                 $result = ($aparm <=> $bparm);
1.381     albertel 4746:             } elsif (defined($aparm)) {
1.560     damieng  4747:                 $result = -1;
1.381     albertel 4748:             } elsif (defined($bparm)) {
1.560     damieng  4749:                 $result = 1;
                   4750:             }
1.473     amueller 4751:         }
1.381     albertel 4752: 
1.560     damieng  4753:         $result;
                   4754:         
1.576     raeburn  4755:     } keys(%{$listdata})) { # foreach my $key
                   4756:         my $thiskey = $key;
1.560     damieng  4757:         if ($$listdata{$thiskey.'.type'}) {
                   4758:             my $thistype=$$listdata{$thiskey.'.type'};
                   4759:             if ($$resourcedata{$thiskey.'.type'}) {
                   4760:                 $thistype=$$resourcedata{$thiskey.'.type'};
                   4761:             }
                   4762:             my ($middle,$part,$name)=
1.572     damieng  4763:                 ($thiskey=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.560     damieng  4764:             my $section=&mt('All Students');
1.594     raeburn  4765:             $readonly = $readonlyall;
1.599     raeburn  4766:             my $userscope;
1.576     raeburn  4767:             my $showval = $$resourcedata{$thiskey}; 
1.560     damieng  4768:             if ($middle=~/^\[(.*)\]/) {
                   4769:                 my $issection=$1;
                   4770:                 if ($issection=~/^useropt\:($match_username)\:($match_domain)/) {
                   4771:                     my ($stuname,$studom) = ($1,$2);
                   4772:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4773:                         if (ref($classlist) eq 'HASH') {
                   4774:                             if (ref($classlist->{$stuname.':'.$studom}) eq 'ARRAY') {
                   4775:                                 next unless ($classlist->{$stuname.':'.$studom}->[$secidx] eq $env{'request.course.sec'}); 
                   4776:                             }
                   4777:                         }
                   4778:                     }
                   4779:                     $section=&mt('User').": ".&Apache::loncommon::plainname($stuname,$studom);
1.599     raeburn  4780:                     $userscope = 1;
1.560     damieng  4781:                 } else {
                   4782:                     if (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4783:                         if (exists($grouphash{$issection})) {
                   4784:                             $section=&mt('Group').': '.$issection;
                   4785:                         } elsif ($issection eq $env{'request.course.sec'}) {
                   4786:                             $section = &mt('Section').': '.$issection;
                   4787:                         } else {
                   4788:                             next; 
1.552     raeburn  4789:                         }
1.560     damieng  4790:                     } else {
                   4791:                         $section=&mt('Group/Section').': '.$issection;
1.552     raeburn  4792:                     }
                   4793:                 }
1.560     damieng  4794:                 $middle=~s/^\[(.*)\]//;
                   4795:             } elsif (($env{'request.course.sec'} ne '') && ($caller eq 'overview')) {
                   4796:                 $readonly = 1;
                   4797:             }
                   4798:             $middle=~s/\.+$//;
                   4799:             $middle=~s/^\.+//;
                   4800:             my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.576     raeburn  4801:             my ($is_map,$is_recursive,$mapurl,$maplevel);
                   4802:             if ($caller eq 'overview') {
                   4803:                 if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   4804:                     $mapurl = $1;
                   4805:                     $maplevel = $2;
                   4806:                     $is_map = 1;
                   4807:                 }
                   4808:             } elsif ($caller eq 'newoverview') {
                   4809:                 if ($middle=~/^(.+)\_\_\_\((all)\)$/) {
                   4810:                     $mapurl = $1;
                   4811:                     $maplevel = $2;
                   4812:                     $is_map = 1;
                   4813:                 }
                   4814:             }
                   4815:             if ($is_map) {
1.560     damieng  4816:                 my $leveltitle = &mt('Folder/Map');
1.576     raeburn  4817:                 unless (($name eq 'hiddenresource') || ($name eq 'encrypturl')) {   
                   4818:                     if ($caller eq 'newoverview') {
                   4819:                         my $altkey = $thiskey;
                   4820:                         $altkey =~ s/\Q___(all)\E/___(rec)/;
                   4821:                         if ((exists($$resourcedata{$altkey})) & (!exists($$resourcedata{$thiskey}))) {
                   4822:                             $is_recursive = 1;
                   4823:                             if ($$resourcedata{$altkey.'.type'}) {
                   4824:                                 $thistype=$$resourcedata{$altkey.'.type'};
                   4825:                             }
                   4826:                             $showval = $$resourcedata{$altkey};
                   4827:                         }
                   4828:                     } elsif (($caller eq 'overview') && ($maplevel eq 'rec')) {
                   4829:                         $thiskey =~ s/\Q___(rec)\E/___(all)/;
                   4830:                         $is_recursive = 1;
                   4831:                     }
1.560     damieng  4832:                 }
                   4833:                 $realm='<span class="LC_parm_scope_folder">'.$leveltitle.': '.&Apache::lonnet::gettitle($mapurl).' <br /><span class="LC_parm_folder">('.$mapurl.')</span></span>';
                   4834:             } elsif ($middle) {
                   4835:                 my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   4836:                 $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   4837:                     ': '.&Apache::lonnet::gettitle($middle).
                   4838:                     ' <br /><span class="LC_parm_symb">('.$url.' in '.$map.' id: '.
                   4839:                     $id.')</span></span>';
                   4840:             }
                   4841:             if ($sortorder eq 'realmstudent') {
                   4842:                 if ($realm ne $oldrealm) {
                   4843:                     $r->print(&tableend()."\n<hr /><h1>$realm</h1>");
                   4844:                     $oldrealm=$realm;
                   4845:                     $oldsection='';
                   4846:                 }
                   4847:                 if ($section ne $oldsection) {
                   4848:                     $r->print(&tableend()."\n<h2>$section</h2>");
                   4849:                     $oldsection=$section;
                   4850:                     $oldpart='';
                   4851:                 }
1.552     raeburn  4852:             } else {
1.560     damieng  4853:                 if ($section ne $oldsection) {
                   4854:                     $r->print(&tableend()."\n<hr /><h1>$section</h1>");
                   4855:                     $oldsection=$section;
                   4856:                     $oldrealm='';
                   4857:                 }
                   4858:                 if ($realm ne $oldrealm) {
                   4859:                     $r->print(&tableend()."\n<h2>$realm</h2>");
                   4860:                     $oldrealm=$realm;
                   4861:                     $oldpart='';
1.552     raeburn  4862:                 }
                   4863:             }
1.560     damieng  4864:             if ($part ne $oldpart) {
                   4865:                 $r->print(&tableend().
                   4866:                     "\n".'<span class="LC_parm_part">'.&mt('Part').": $part</span>");
                   4867:                 $oldpart=$part;
1.556     raeburn  4868:             }
1.560     damieng  4869:     #
                   4870:     # Ready to print
                   4871:     #
1.470     raeburn  4872:             my $parmitem = &standard_parameter_names($name);
1.576     raeburn  4873:             $r->print(&tablestart($readonly,$is_map).
1.560     damieng  4874:                 &Apache::loncommon::start_data_table_row().
                   4875:                 '<td><b>'.&mt($parmitem).
                   4876:                 '</b></td>');
                   4877:             unless ($readonly) {
1.599     raeburn  4878:                 my $disabled;
                   4879:                 if (($name eq 'availablestudent') &&
                   4880:                     (($showval eq '') || ($userscope))) {
                   4881:                     $disabled = ' disabled="disabled"';
                   4882:                 }
1.560     damieng  4883:                 $r->print('<td><input type="checkbox" name="del_'.
1.599     raeburn  4884:                         $thiskey.'"'.$disabled.' /></td>');
1.560     damieng  4885:             }
                   4886:             $r->print('<td>');
                   4887:             $foundkeys++;
                   4888:             if (&isdateparm($thistype)) {
                   4889:                 my $jskey='key_'.$pointer;
                   4890:                 my $state;
                   4891:                 $pointer++;
                   4892:                 if ($readonly) {
                   4893:                     $state = 'disabled';
                   4894:                 }
                   4895:                 $r->print(
                   4896:                     &Apache::lonhtmlcommon::date_setter('parmform',
                   4897:                                                         $jskey,
1.576     raeburn  4898:                                                         $showval,
1.560     damieng  4899:                                                         '',1,$state));
                   4900:                 unless  ($readonly) {
                   4901:                     $r->print(
                   4902:     '<input type="hidden" name="datepointer_'.$thiskey.'" value="'.$jskey.'" />'.
1.576     raeburn  4903:     (($showval!=0)?'<span class="LC_nobreak"><a href="/adm/parmset?&action=dateshift1&timebase='.$showval.'">'.
1.560     damieng  4904:     &mt('Shift all dates based on this date').'</a></span>':'').
1.576     raeburn  4905:     &date_sanity_info($showval)
1.560     damieng  4906:                     );
                   4907:                 }
                   4908:             } elsif ($thistype eq 'date_interval') {
                   4909:                 $r->print(&date_interval_selector($thiskey,$name,
1.576     raeburn  4910:                           $showval,$readonly));
1.560     damieng  4911:             } elsif ($thistype =~ m/^string/) {
1.599     raeburn  4912:                 if ($name eq 'availablestudent') {
                   4913:                     $readonly = 1;
                   4914:                 }
1.560     damieng  4915:                 $r->print(&string_selector($thistype,$thiskey,
1.576     raeburn  4916:                           $showval,$name,$readonly));
1.560     damieng  4917:             } else {
1.576     raeburn  4918:                 $r->print(&default_selector($thiskey,$showval,$readonly));
1.552     raeburn  4919:             }
1.560     damieng  4920:             unless ($readonly) {
                   4921:                 $r->print('<input type="hidden" name="typeof_'.$thiskey.'" value="'.
                   4922:                         $thistype.'" />');
1.552     raeburn  4923:             }
1.576     raeburn  4924:             $r->print('</td>');
                   4925:             if ($is_map) {
                   4926:                 if (($name eq 'encrypturl') || ($name eq 'hiddenresource')) {
                   4927:                     $r->print('<td><table><tr><td>'.&mt('Yes').'</td></tr></table></td>');
                   4928:                 } else {
                   4929:                     my ($disabled,$recon,$recoff);
                   4930:                     if ($readonly) {
                   4931:                         $disabled = ' disabled="disabled"';
                   4932:                     }
                   4933:                     if ($is_recursive) {
                   4934:                         $recon = ' checked="checked"';
                   4935:                     } else {
                   4936:                         $recoff = ' checked="checked"';
                   4937:                     }
                   4938:                     $r->print('<td><table><tr><td><label><input type="radio" name="rec_'.$thiskey.'" value="1"'.$recon.$disabled.' />'.&mt('Yes').'</label>'.
                   4939:                               '</td><td><label><input type="radio" name="rec_'.$thiskey.'" value="0"'.$recoff.$disabled.' />'.&mt('No').'</label></td></tr></table></td>');
                   4940:                 }
                   4941:             }
                   4942:             $r->print(&Apache::loncommon::end_data_table_row());
1.473     amueller 4943:         }
1.121     www      4944:     }
1.208     www      4945:     return $foundkeys;
                   4946: }
                   4947: 
1.563     damieng  4948: # Returns a string representing the interval, directly using form data matching the given key.
                   4949: # The returned string may also include information related to proctored exams.
                   4950: # Format: seconds['_done'[':'done button title':']['_proctor'['_'proctor key]]]
                   4951: #
                   4952: # @param {string} $key - suffix for form fields related to the interval
                   4953: # @returns {string}
1.385     albertel 4954: sub get_date_interval_from_form {
                   4955:     my ($key) = @_;
                   4956:     my $seconds = 0;
                   4957:     foreach my $which (['days', 86400],
1.473     amueller 4958:                ['hours', 3600],
                   4959:                ['minutes', 60],
                   4960:                ['seconds',  1]) {
1.560     damieng  4961:         my ($name, $factor) = @{ $which };
                   4962:         if (defined($env{'form.'.$name.'_'.$key})) {
                   4963:             $seconds += $env{'form.'.$name.'_'.$key} * $factor;
                   4964:         }
1.473     amueller 4965:     }
1.560     damieng  4966:     if (($key =~ /\.interval$/) &&
                   4967:             (($env{'form.done_'.$key} eq '_done') || ($env{'form.done_'.$key} eq '_done_proctor'))) {
1.559     raeburn  4968:         if ($env{'form.done_'.$key.'_buttontext'}) {
                   4969:             $env{'form.done_'.$key.'_buttontext'} =~ s/\://g;
                   4970:             $seconds .= '_done:'.$env{'form.done_'.$key.'_buttontext'}.':';
                   4971:             if ($env{'form.done_'.$key} eq '_done_proctor') {
                   4972:                 $seconds .= '_proctor';
                   4973:             }
                   4974:         } else {
                   4975:             $seconds .= $env{'form.done_'.$key}; 
                   4976:         }
                   4977:         if (($env{'form.done_'.$key} eq '_done_proctor') && 
1.560     damieng  4978:                 ($env{'form.done_'.$key.'_proctorkey'})) {
1.558     raeburn  4979:             $seconds .= '_'.$env{'form.done_'.$key.'_proctorkey'};
                   4980:         }
1.554     raeburn  4981:     }
1.385     albertel 4982:     return $seconds;
                   4983: }
                   4984: 
                   4985: 
1.563     damieng  4986: # Returns HTML to enter a text value for a parameter.
                   4987: #
                   4988: # @param {string} $thiskey - parameter key
                   4989: # @param {string} $showval - the current value
                   4990: # @param {boolean} $readonly - true if the field should not be made editable
                   4991: # @returns {string}
1.383     albertel 4992: sub default_selector {
1.552     raeburn  4993:     my ($thiskey, $showval, $readonly) = @_;
                   4994:     my $disabled;
                   4995:     if ($readonly) {
                   4996:         $disabled = ' disabled="disabled"';
                   4997:     }
                   4998:     return '<input type="text" name="set_'.$thiskey.'" value="'.$showval.'"'.$disabled.' />';
1.383     albertel 4999: }
                   5000: 
1.563     damieng  5001: # Returns HTML to enter allow/deny rules related to IP addresses.
                   5002: #
                   5003: # @param {string} $thiskey - parameter key
                   5004: # @param {string} $showval - the current value
                   5005: # @param {boolean} $readonly - true if the fields should not be made editable
                   5006: # @returns {string}
1.549     raeburn  5007: sub string_ip_selector {
1.552     raeburn  5008:     my ($thiskey, $showval, $readonly) = @_;
1.549     raeburn  5009:     my %access = (
                   5010:                    allow => [],
                   5011:                    deny  => [],
                   5012:                  );
                   5013:     if ($showval ne '') {
                   5014:         my @current;
                   5015:         if ($showval =~ /,/) {
                   5016:             @current = split(/,/,$showval);
                   5017:         } else {
                   5018:             @current = ($showval);
                   5019:         }
                   5020:         foreach my $item (@current) {
                   5021:             if ($item =~ /^\!([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5022:                 push(@{$access{'deny'}},$1);
                   5023:             } elsif ($item =~ /^([\[\]a-zA-Z\.\d\*\-]+)$/) {
                   5024:                 push(@{$access{'allow'}},$item);
                   5025:             }
                   5026:         }
                   5027:     }
                   5028:     if (!@{$access{'allow'}}) {
                   5029:         @{$access{'allow'}} = ('');
                   5030:     }
                   5031:     if (!@{$access{'deny'}}) {
                   5032:         @{$access{'deny'}} = ('');
                   5033:     }
1.552     raeburn  5034:     my ($disabled,$addmore);
1.567     raeburn  5035:     if ($readonly) {
1.552     raeburn  5036:         $disabled=' disabled="disabled"';
                   5037:     } else {
                   5038:         $addmore = "\n".'<button class="LC_add_ipacc_button">'.&mt('Add more').'</button>';
                   5039:     }
1.549     raeburn  5040:     my $output = '<input type="hidden" name="set_'.$thiskey.'" />
                   5041: <table><tr><th>'.&mt('Allow from').'</th><th>'.&mt('Deny from').'</th></tr><tr>';
                   5042:     foreach my $acctype ('allow','deny') {
                   5043:         $output .= '
                   5044: <td valign="top">
                   5045: <div class="LC_string_ipacc_wrap" id="LC_string_ipacc_'.$acctype.'_'.$thiskey.'">
                   5046:   <div class="LC_string_ipacc_inner">'."\n";
                   5047:         my $num = 0;
                   5048:         foreach my $curr (@{$access{$acctype}}) {
1.552     raeburn  5049:             $output .= '<div><input type="text" name="setip'.$acctype.'_'.$thiskey.'" value="'.$curr.'"'.$disabled.' />';
1.549     raeburn  5050:             if ($num > 0) {
                   5051:                 $output .= '<a href="#" class="LC_remove_ipacc">'.&mt('Remove').'</a>'; 
                   5052:             }
                   5053:             $output .= '</div>'."\n";
                   5054:             $num ++;
                   5055:         }
                   5056:         $output .= '
1.552     raeburn  5057:   </div>'.$addmore.'
1.549     raeburn  5058: </div>
                   5059: </td>';
                   5060:    }
                   5061:    $output .= '
                   5062: </tr>
                   5063: </table>'."\n";
                   5064:     return $output;
                   5065: }
                   5066: 
1.588     raeburn  5067: sub string_deeplink_selector {
                   5068:     my ($thiskey, $showval, $readonly) = @_;
1.597     raeburn  5069:     my (@components,%values,@current,%titles,%options,%optiontext,%defaults,
1.601     raeburn  5070:         %selectnull,%domlti,%crslti,@possmenus);
                   5071:     @components = ('state','others','listing','scope','protect','menus');
1.588     raeburn  5072:     %titles = &Apache::lonlocal::texthash (
1.601     raeburn  5073:                   state   => 'Access status',
                   5074:                   others  => 'Hide other resources',
1.588     raeburn  5075:                   listing => 'In Contents and/or Gradebook',
                   5076:                   scope   => 'Access scope for link',
1.601     raeburn  5077:                   protect => 'Link protection',
1.597     raeburn  5078:                   menus   => 'Menu Items Displayed',
1.588     raeburn  5079:               );
                   5080:     %options = (
1.601     raeburn  5081:                    state   => ['only','off','both'],
                   5082:                    others  => ['hide','unhide'],
1.588     raeburn  5083:                    listing => ['full','absent','grades','details','datestatus'],
                   5084:                    scope   => ['res','map','rec'],
1.601     raeburn  5085:                    protect => ['none','key','ltid','ltic'],
1.597     raeburn  5086:                    menus   => ['std','colls'],
1.588     raeburn  5087:                );
                   5088:     %optiontext = &Apache::lonlocal::texthash (
1.601     raeburn  5089:                     only       => 'deep only',
                   5090:                     off        => 'deeplink off',
                   5091:                     both       => 'regular + deep',
                   5092:                     hide       => 'Hidden',
                   5093:                     unhide     => 'Unhidden',
1.588     raeburn  5094:                     full       => 'Listed (linked) in both',
                   5095:                     absent     => 'Not listed',
                   5096:                     grades     => 'Listed in grades only',
                   5097:                     details    => 'Listed (unlinked) in both',
                   5098:                     datestatus => 'Listed (unlinked) inc. status in both',
                   5099:                     res        => 'resource only',
                   5100:                     map        => 'enclosing map/folder',
                   5101:                     rec        => 'recursive map/folder',
1.601     raeburn  5102:                     none       => 'not in use',
                   5103:                     key        => 'key access',
                   5104:                     ltic       => 'LTI access (course)',
                   5105:                     ltid       => 'LTI access (domain)' ,
1.597     raeburn  5106:                     std        => 'Standard (all menus)',
                   5107:                     colls      => 'Numbered collection',
                   5108:                   );
                   5109:     %selectnull = &Apache::lonlocal::texthash (
1.601     raeburn  5110:                     ltic => 'Select Launcher',
                   5111:                     ltid => 'Select Launcher', 
1.597     raeburn  5112:                     colls => 'Select',
1.588     raeburn  5113:                   );
                   5114:     if ($showval =~ /,/) {
1.597     raeburn  5115:         %values=();
1.588     raeburn  5116:         @current = split(/,/,$showval);
1.601     raeburn  5117:         ($values{'state'}) = ($current[0] =~ /^(only|off|both)$/);
                   5118:         ($values{'others'}) = ($current[1] =~ /^(hide|unhide)$/);
                   5119:         ($values{'listing'}) = ($current[2] =~ /^(full|absent|grades|details|datestatus)$/);
                   5120:         ($values{'scope'}) = ($current[3] =~ /^(res|map|rec)$/);
                   5121:         ($values{'protect'}) = ($current[4] =~ /^(key:[a-zA-Z\d_.!\@#\$%^&*()+=-]+|ltic:\d+|ltid:\d+)$/);
                   5122:         ($values{'menus'}) = ($current[5] =~ /^(\d+)$/);
1.588     raeburn  5123:     } else {
1.601     raeburn  5124:         $defaults{'state'} = 'off',
                   5125:         $defaults{'others'} = 'unhide',
1.588     raeburn  5126:         $defaults{'listing'} = 'full';
                   5127:         $defaults{'scope'} = 'res';
1.601     raeburn  5128:         $defaults{'protect'} = 'none';
1.597     raeburn  5129:         $defaults{'menus'} = '0';
1.588     raeburn  5130:     }
                   5131:     my $disabled;
                   5132:     if ($readonly) {
                   5133:         $disabled=' disabled="disabled"';
                   5134:     }
1.601     raeburn  5135:     my %courselti =
                   5136:         &Apache::lonnet::get_course_lti($env{'course.'.$env{'request.course.id'}.'.num'},
                   5137:                                         $env{'course.'.$env{'request.course.id'}.'.domain'});
                   5138:     foreach my $item (keys(%courselti)) {
                   5139:         if (ref($courselti{$item}) eq 'HASH') {
                   5140:             $crslti{$item} = $courselti{$item}{'name'};
                   5141:         }
                   5142:     }
                   5143:     my %lti =
1.588     raeburn  5144:         &Apache::lonnet::get_domain_lti($env{'course.'.$env{'request.course.id'}.'.domain'},
1.604     raeburn  5145:                                         'linkprot');
1.588     raeburn  5146:     foreach my $item (keys(%lti)) {
1.604     raeburn  5147:         if (($item =~ /^\d+$/) && (ref($lti{$item}) eq 'HASH')) {
                   5148:             $domlti{$item} = $lti{$item}{'name'};
1.588     raeburn  5149:         }
                   5150:     }
1.597     raeburn  5151:     if ($env{'course.'.$env{'request.course.id'}.'.menucollections'}) {
                   5152:         foreach my $item (split(/;/,$env{'course.'.$env{'request.course.id'}.'.menucollections'})) {
                   5153:             my ($num,$value) = split(/\%/,$item);
                   5154:             if ($num =~ /^\d+$/) {
                   5155:                 push(@possmenus,$num);
                   5156:             }
                   5157:         }
                   5158:     }
                   5159: 
1.588     raeburn  5160:     my $output = '<input type="hidden" name="set_'.$thiskey.'" /><table><tr>';
1.597     raeburn  5161:     foreach my $item (@components) {
1.588     raeburn  5162:         $output .= '<th>'.$titles{$item}.'</th>';
                   5163:     }
                   5164:     $output .= '</tr><tr>';
                   5165:     foreach my $item (@components) {
                   5166:         $output .= '<td>';
1.601     raeburn  5167:         if (($item eq 'protect') || ($item eq 'menus')) {
1.588     raeburn  5168:             my $selected = $values{$item};
                   5169:             foreach my $option (@{$options{$item}}) {
1.601     raeburn  5170:                 if ($item eq 'protect') { 
                   5171:                     if ($option eq 'ltid') {
                   5172:                         next unless (keys(%domlti));
                   5173:                     } elsif ($option eq 'ltic') {
                   5174:                         next unless (keys(%crslti));
                   5175:                     }
1.597     raeburn  5176:                 } elsif (($item eq 'menus') && ($option eq 'colls')) {
                   5177:                     next unless (@possmenus);
1.588     raeburn  5178:                 }
                   5179:                 my $checked;
1.597     raeburn  5180:                 if ($item eq 'menus') {
                   5181:                     if (($selected =~ /^\d+$/) && (@possmenus) &&
                   5182:                         (grep(/^\Q$selected\E$/,@possmenus))) {
                   5183:                         if ($option eq 'colls') {
                   5184:                             $checked = ' checked="checked"';
                   5185:                         }
                   5186:                     } elsif (($option eq 'std') && ($selected == 0) && ($selected ne '')) {
                   5187:                         $checked = ' checked="checked"';
                   5188:                     }
                   5189:                 } elsif ($selected =~ /^\Q$option\E/) {
1.588     raeburn  5190:                     $checked = ' checked="checked"';
                   5191:                 }
                   5192:                 my $onclick;
                   5193:                 unless ($readonly) {
                   5194:                     my $esc_key = &js_escape($thiskey);
                   5195:                     $onclick = ' onclick="toggleDeepLink(this.form,'."'$item','$esc_key'".');"';
                   5196:                 }
                   5197:                 $output .= '<span class="LC_nobreak"><label>'.
                   5198:                            '<input type="radio" name="deeplink_'.$item.'_'.$thiskey.'" value="'.$option.'"'.$onclick.$disabled.$checked.' />'."\n".
                   5199:                            $optiontext{$option}.'</label>';
1.601     raeburn  5200:                 if (($item eq 'protect') && ($option eq 'key')) {
1.588     raeburn  5201:                     my $visibility="hidden";
                   5202:                     my $currkey;
                   5203:                     if ($checked) {
                   5204:                         $visibility = "text";
                   5205:                         $currkey = (split(/\:/,$values{$item}))[1];
                   5206:                     }
                   5207:                     $output .= '&nbsp;'.
1.597     raeburn  5208:                         '<input type="'.$visibility.'" name="deeplink_'.$option.'_'.$thiskey.'" id="deeplink_'.$option.'_'.$item.'_'.$thiskey.'" value="'.$currkey.'" size="10"'.$disabled.' />';
1.601     raeburn  5209:                 } elsif (($option eq 'ltic') || ($option eq 'ltid') || ($option eq 'colls')) {
1.588     raeburn  5210:                     my $display="none";
1.597     raeburn  5211:                     my ($current,$blankcheck,@possibles);
1.588     raeburn  5212:                     if ($checked) {
                   5213:                         $display = 'inline-block';
1.601     raeburn  5214:                         if (($option eq 'ltic') || ($option eq 'ltid'))  {
1.597     raeburn  5215:                             $current = (split(/\:/,$selected))[1];
                   5216:                         } else {
                   5217:                             $current = $selected;
                   5218:                         }
1.588     raeburn  5219:                     } else {
                   5220:                         $blankcheck = ' selected="selected"';
                   5221:                     }
1.601     raeburn  5222:                     if ($option eq 'ltid') {
                   5223:                         @possibles = keys(%domlti);
                   5224:                     } elsif ($option eq 'ltic') {
                   5225:                         @possibles = keys(%crslti); 
1.597     raeburn  5226:                     } else {
                   5227:                         @possibles = @possmenus;
                   5228:                     }
1.588     raeburn  5229:                     $output .= '<div id="deeplinkdiv_'.$option.'_'.$item.'_'.$thiskey.'"'.
                   5230:                                ' style="display: '.$display.'">&nbsp;<select name="'.
1.597     raeburn  5231:                                'deeplink_'.$option.'_'.$thiskey.'"'.$disabled.'>';
                   5232:                     if (@possibles > 1) {
                   5233:                         $output .= '<option value=""'.$blankcheck.'>'.$selectnull{$option}.
                   5234:                                    '</option>'."\n";
                   5235:                     }
                   5236:                     foreach my $poss (sort { $a <=> $b } @possibles) {
1.588     raeburn  5237:                         my $selected;
1.597     raeburn  5238:                         if (($poss == $current) || (scalar(@possibles) ==1)) {
1.588     raeburn  5239:                             $selected = ' selected="selected"';
                   5240:                         }
1.597     raeburn  5241:                         my $shown = $poss;
1.601     raeburn  5242:                         if ($option eq 'ltid') {
                   5243:                             $shown = $domlti{$poss};
                   5244:                         } elsif ($option eq 'ltic') {
                   5245:                             $shown = $crslti{$poss};
1.597     raeburn  5246:                         }
                   5247:                         $output .= '<option value="'.$poss.'"'.$selected.'>'.$shown.'</option>';
1.588     raeburn  5248:                     }
                   5249:                     $output .= '</select></div>';
                   5250:                 }
                   5251:                 $output .= '</span> ';
                   5252:             }
                   5253:         } else {
                   5254:             my $selected = $values{$item};
                   5255:             my $defsel;
                   5256:             if ($selected eq '') {
                   5257:                 $defsel = ' selected="selected"';
                   5258:             }
                   5259:             $output .= '<select name="deeplink_'.$item.'_'.$thiskey.'"'.$disabled.'>'."\n".
                   5260:                        '<option value=""'.$defsel.'>'.&mt('Please select').'</option>'."\n";
                   5261:             foreach my $option (@{$options{$item}}) {
                   5262:                 $output .= '<option value="'.$option.'"';
                   5263:                 if ($option eq $selected) {
                   5264:                     $output .= ' selected="selected"';
                   5265:                 }
                   5266:                 $output .= '>'.$optiontext{$option}.'</option>';
                   5267:             }
                   5268:             $output .= '</select>';
                   5269:         }
                   5270:         $output .= '</td>';
                   5271:     }
                   5272:     $output .= '</tr></table>'."\n";
                   5273:     return $output;
                   5274: }
                   5275: 
1.560     damieng  5276: 
                   5277: { # block using some constants related to parameter types (overview mode)
                   5278: 
1.446     bisitz   5279: my %strings =
1.383     albertel 5280:     (
                   5281:      'string_yesno'
                   5282:              => [[ 'yes', 'Yes' ],
1.560     damieng  5283:                  [ 'no', 'No' ]],
1.383     albertel 5284:      'string_problemstatus'
                   5285:              => [[ 'yes', 'Yes' ],
1.473     amueller 5286:          [ 'answer', 'Yes, and show correct answer if they exceed the maximum number of tries.' ],
                   5287:          [ 'no', 'No, don\'t show correct/incorrect feedback.' ],
                   5288:          [ 'no_feedback_ever', 'No, show no feedback at all.' ]],
1.504     raeburn  5289:      'string_questiontype'
                   5290:              => [[ 'problem', 'Standard Problem'],
                   5291:                  [ 'survey', 'Survey'],
                   5292:                  [ 'anonsurveycred', 'Anonymous Survey (credit for submission)'],
1.530     bisitz   5293:                  [ 'exam', 'Bubblesheet Exam'],
1.504     raeburn  5294:                  [ 'anonsurvey', 'Anonymous Survey'],
                   5295:                  [ 'randomizetry', 'New Randomization Each N Tries (default N=1)'],
                   5296:                  [ 'practice', 'Practice'],
                   5297:                  [ 'surveycred', 'Survey (credit for submission)']],
1.514     raeburn  5298:      'string_lenient'
                   5299:              => [['yes', 'Yes' ],
                   5300:                  [ 'no', 'No' ],
1.549     raeburn  5301:                  [ 'default', 'Default - only bubblesheet grading is lenient' ],
                   5302:                  [ 'weighted', 'Yes, weighted (optionresponse in checkbox mode)' ]],
1.521     raeburn  5303:      'string_discussvote'
                   5304:              => [['yes','Yes'],
                   5305:                  ['notended','Yes, unless discussion ended'],
                   5306:                  ['no','No']],
1.549     raeburn  5307:      'string_ip'
                   5308:              => [['_allowfrom_','Hostname(s), or IP(s) from which access is allowed'],
1.587     raeburn  5309:                  ['_denyfrom_','Hostname(s) or IP(s) from which access is disallowed']], 
                   5310:      'string_deeplink'
1.597     raeburn  5311:              => [['on','Set choices for link protection, resource listing, access scope, and shown menu items']],
1.587     raeburn  5312:     );
                   5313:    
1.383     albertel 5314: 
1.549     raeburn  5315: my %stringmatches = (
                   5316:          'string_lenient'
                   5317:               => [['weighted','^\-?[.\d]+,\-?[.\d]+,\-?[.\d]+,\-?[.\d]+$'],],
                   5318:          'string_ip'
                   5319:               => [['_allowfrom_','[^\!]+'],
                   5320:                   ['_denyfrom_','\!']],
1.588     raeburn  5321:          'string_deeplink'
1.602     raeburn  5322:               => [['on','^(only|off|both)\,(hide|unhide)\,(full|absent|grades|details|datestatus)\,(res|map|rec)\,(none|key\:\w+|ltic\:\d+|ltid\:\d+)\,(\d+|)$']],
1.549     raeburn  5323:     );
                   5324: 
                   5325: my %stringtypes = (
                   5326:                     type         => 'string_questiontype',
                   5327:                     lenient      => 'string_lenient',
                   5328:                     retrypartial => 'string_yesno',
                   5329:                     discussvote  => 'string_discussvote',
                   5330:                     examcode     => 'string_examcode',
                   5331:                     acc          => 'string_ip',
1.587     raeburn  5332:                     deeplink     => 'string_deeplink',
1.549     raeburn  5333:                   );
                   5334: 
1.563     damieng  5335: # Returns the possible values and titles for a given string type, or undef if there are none.
                   5336: # Used by courseprefs.
                   5337: #
                   5338: # @param {string} $string_type - a parameter type for strings
                   5339: # @returns {array reference} - 2D array, containing values and English titles
1.505     raeburn  5340: sub standard_string_options {
                   5341:     my ($string_type) = @_;
                   5342:     if (ref($strings{$string_type}) eq 'ARRAY') {
                   5343:         return $strings{$string_type};
                   5344:     }
                   5345:     return;
                   5346: }
1.383     albertel 5347: 
1.563     damieng  5348: # Returns regular expressions to match kinds of string types, or undef if there are none.
                   5349: #
                   5350: # @param {string} $string_type - a parameter type for strings
                   5351: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.549     raeburn  5352: sub standard_string_matches {
                   5353:     my ($string_type) = @_;
                   5354:     if (ref($stringmatches{$string_type}) eq 'ARRAY') {
                   5355:         return $stringmatches{$string_type};
                   5356:     }
                   5357:     return;
                   5358: }
                   5359: 
1.563     damieng  5360: # Returns a parameter type for a given parameter with a string type, or undef if not known.
                   5361: #
                   5362: # @param {string} $name - parameter name
                   5363: # @returns {string}
1.549     raeburn  5364: sub get_stringtype {
                   5365:     my ($name) = @_;
                   5366:     if (exists($stringtypes{$name})) {
                   5367:         return $stringtypes{$name};
                   5368:     }
                   5369:     return;
                   5370: }
                   5371: 
1.563     damieng  5372: # Returns HTML to edit a string parameter.
                   5373: #
                   5374: # @param {string} $thistype - parameter type
                   5375: # @param {string} $thiskey - parameter key
                   5376: # @param {string} $showval - parameter current value
                   5377: # @param {string} $name - parameter name
                   5378: # @param {boolean} $readonly - true if the values should not be made editable
                   5379: # @returns {string}
1.383     albertel 5380: sub string_selector {
1.552     raeburn  5381:     my ($thistype, $thiskey, $showval, $name, $readonly) = @_;
1.446     bisitz   5382: 
1.383     albertel 5383:     if (!exists($strings{$thistype})) {
1.552     raeburn  5384:         return &default_selector($thiskey,$showval,$readonly);
1.383     albertel 5385:     }
                   5386: 
1.504     raeburn  5387:     my %skiptype;
1.514     raeburn  5388:     if (($thistype eq 'string_questiontype') || 
1.560     damieng  5389:             ($thistype eq 'string_lenient') ||
                   5390:             ($thistype eq 'string_discussvote') ||
                   5391:             ($thistype eq 'string_ip') ||
1.588     raeburn  5392:             ($thistype eq 'string_deeplink') ||
1.560     damieng  5393:             ($name eq 'retrypartial')) {
1.504     raeburn  5394:         my ($got_chostname,$chostname,$cmajor,$cminor); 
                   5395:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5396:             next unless (ref($possibilities) eq 'ARRAY');
1.514     raeburn  5397:             my ($parmval, $description) = @{ $possibilities };
1.549     raeburn  5398:             my $parmmatch;
                   5399:             if (ref($stringmatches{$thistype}) eq 'ARRAY') {
                   5400:                 foreach my $item (@{$stringmatches{$thistype}}) {
                   5401:                     if (ref($item) eq 'ARRAY') {
                   5402:                         if ($parmval eq $item->[0]) {
                   5403:                             $parmmatch = $parmval;
                   5404:                             $parmval = '';
                   5405:                             last;
                   5406:                         }
                   5407:                     }
                   5408:                 }
                   5409:             }
                   5410:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"}; 
1.504     raeburn  5411:             if ($needsrelease) {
                   5412:                 unless ($got_chostname) {
1.514     raeburn  5413:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
1.504     raeburn  5414:                     $got_chostname = 1;
                   5415:                 }
1.557     raeburn  5416:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.549     raeburn  5417:                                                        $needsrelease,$cmajor,$cminor);
1.504     raeburn  5418:                 if ($needsnewer) {
1.549     raeburn  5419:                     if ($parmmatch ne '') {
                   5420:                         $skiptype{$parmmatch} = 1;
                   5421:                     } elsif ($parmval ne '') {
                   5422:                         $skiptype{$parmval} = 1;
                   5423:                     }
1.504     raeburn  5424:                 }
                   5425:             }
                   5426:         }
                   5427:     }
1.549     raeburn  5428: 
                   5429:     if ($thistype eq 'string_ip') {
1.552     raeburn  5430:         return &string_ip_selector($thiskey,$showval,$readonly); 
1.588     raeburn  5431:     } elsif ($thistype eq 'string_deeplink') {
                   5432:         return &string_deeplink_selector($thiskey,$showval,$readonly);
1.549     raeburn  5433:     }
1.504     raeburn  5434: 
1.552     raeburn  5435:     my ($result,$disabled);
                   5436: 
                   5437:     if ($readonly) {
                   5438:         $disabled = ' disabled="disabled"';
                   5439:     }
1.504     raeburn  5440:     my $numinrow = 3;
                   5441:     if ($thistype eq 'string_problemstatus') {
                   5442:         $numinrow = 2;
                   5443:     } elsif ($thistype eq 'string_questiontype') {
                   5444:         if (keys(%skiptype) > 0) {
                   5445:              $numinrow = 4;
                   5446:         }
                   5447:     }
                   5448:     my $rem;
                   5449:     if (ref($strings{$thistype}) eq 'ARRAY') {
                   5450:         my $i=0;
                   5451:         foreach my $possibilities (@{ $strings{$thistype} }) {
                   5452:             next unless (ref($possibilities) eq 'ARRAY');
                   5453:             my ($name, $description) = @{ $possibilities };
1.549     raeburn  5454:             next if ($skiptype{$name});
1.504     raeburn  5455:             $rem = $i%($numinrow);
                   5456:             if ($rem == 0) {
                   5457:                 if ($i > 0) {
                   5458:                     $result .= '</tr>';
                   5459:                 }
                   5460:                 $result .= '<tr>';
                   5461:             }
1.549     raeburn  5462:             my $colspan;
                   5463:             if ($i == @{ $strings{$thistype} }-1) {
                   5464:                 $rem = @{ $strings{$thistype} }%($numinrow);
                   5465:                 if ($rem) {
                   5466:                     my $colsleft = $numinrow - $rem;
                   5467:                     if ($colsleft) {
                   5468:                         $colspan = $colsleft+1;
                   5469:                         $colspan = ' colspan="'.$colspan.'"';
                   5470:                     }
                   5471:                 }
                   5472:             }
                   5473:             my ($add,$onchange,$css_class);
                   5474:             if ($thistype eq 'string_lenient') {
                   5475:                 if ($name eq 'weighted') {
                   5476:                     my $display;
                   5477:                     my %relatives = &Apache::lonlocal::texthash(
                   5478:                                         corrchkd     => 'Correct (checked)',
                   5479:                                         corrunchkd   => 'Correct (unchecked)',
                   5480:                                         incorrchkd   => 'Incorrect (checked)',
                   5481:                                         incorrunchkd => 'Incorrect (unchecked)',
                   5482:                     );
                   5483:                     my %textval = (
                   5484:                                     corrchkd     => '1.0',
                   5485:                                     corrunchkd   => '1.0',
                   5486:                                     incorrchkd   => '0.0',
                   5487:                                     incorrunchkd => '0.0',
                   5488:                     );
                   5489:                     if ($showval =~ /^([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)\,([\-\d\.]+)$/) {
                   5490:                         $textval{'corrchkd'} = $1;
                   5491:                         $textval{'corrunchkd'} = $2;
                   5492:                         $textval{'incorrchkd'} = $3;
                   5493:                         $textval{'incorrunchkd'} = $4;
                   5494:                         $display = 'inline';
                   5495:                         $showval = $name;
                   5496:                     } else {
                   5497:                         $display = 'none';
                   5498:                     }
                   5499:                     $add = ' <div id="LC_parmtext_'.$thiskey.'" style="display:'.$display.'"><table>'.
                   5500:                            '<tr><th colspan="2">'.&mt("Foil's submission status").'</th><th>'.&mt('Points').'</th></tr>';  
                   5501:                     foreach my $reltype ('corrchkd','corrunchkd','incorrchkd','incorrunchkd') {
                   5502:                         $add .= '<tr><td>&nbsp;</td><td>'.$relatives{$reltype}.'</td>'."\n".
                   5503:                                 '<td><input type="text" name="settext_'.$thiskey.'"'.
1.552     raeburn  5504:                                 ' value="'.$textval{$reltype}.'" size="3"'.$disabled.' />'.
1.549     raeburn  5505:                                 '</td></tr>';
                   5506:                     }
                   5507:                     $add .= '</table></div>'."\n";
                   5508:                 }
                   5509:                 $onchange = ' onclick="javascript:toggleParmTextbox(this.form,'."'$thiskey'".');"';
                   5510:                 $css_class = ' class="LC_lenient_radio"';
                   5511:             }
                   5512:             $result .= '<td class="LC_left_item"'.$colspan.'>'.
1.504     raeburn  5513:                        '<span class="LC_nobreak"><label>'.
                   5514:                        '<input type="radio" name="set_'.$thiskey.
1.552     raeburn  5515:                        '" value="'.$name.'"'.$onchange.$css_class.$disabled;
1.504     raeburn  5516:             if ($showval eq $name) {
                   5517:                 $result .= ' checked="checked"';
                   5518:             }
1.549     raeburn  5519:             $result .= ' />'.&mt($description).'</label>'.$add.'</span></td>';
1.504     raeburn  5520:             $i++;
                   5521:         }
                   5522:         $result .= '</tr>';
1.473     amueller 5523:     }
1.504     raeburn  5524:     if ($result) {
                   5525:         $result = '<table border="0">'.$result.'</table>';
1.383     albertel 5526:     }
                   5527:     return $result;
                   5528: }
                   5529: 
1.554     raeburn  5530: my %intervals =
                   5531:     (
                   5532:      'date_interval'
                   5533:              => [[ 'done', 'Yes' ],
1.558     raeburn  5534:                  [ 'done_proctor', 'Yes, with proctor key'],                  
1.554     raeburn  5535:                  [ '', 'No' ]],
                   5536:     );
                   5537: 
                   5538: my %intervalmatches = (
                   5539:          'date_interval'
1.559     raeburn  5540:               => [['done','\d+_done(|\:[^\:]+\:)$'],
                   5541:                   ['done_proctor','\d+_done(|\:[^\:]+\:)_proctor_']],
1.554     raeburn  5542:     );
                   5543: 
                   5544: my %intervaltypes = (
                   5545:                       interval => 'date_interval',
                   5546:     );
                   5547: 
1.563     damieng  5548: # Returns regular expressions to match kinds of interval type, or undef if there are none.
                   5549: #
                   5550: # @param {string} $interval_type - a parameter type for intervals
                   5551: # @returns {array reference}  - 2D array, containing regular expression names and regular expressions
1.554     raeburn  5552: sub standard_interval_matches {
                   5553:     my ($interval_type) = @_;
                   5554:     if (ref($intervalmatches{$interval_type}) eq 'ARRAY') {
                   5555:         return $intervalmatches{$interval_type};
                   5556:     }
                   5557:     return;
                   5558: }
                   5559: 
1.563     damieng  5560: # Returns a parameter type for a given parameter with an interval type, or undef if not known.
                   5561: #
                   5562: # @param {string} $name - parameter name
                   5563: # @returns {string}
1.554     raeburn  5564: sub get_intervaltype {
                   5565:     my ($name) = @_;
                   5566:     if (exists($intervaltypes{$name})) {
                   5567:         return $intervaltypes{$name};
                   5568:     }
                   5569:     return;
                   5570: }
                   5571: 
1.563     damieng  5572: # Returns the possible values and titles for a given interval type, or undef if there are none.
                   5573: # Used by courseprefs.
                   5574: #
                   5575: # @param {string} $interval_type - a parameter type for intervals
                   5576: # @returns {array reference} - 2D array, containing values and English titles
1.554     raeburn  5577: sub standard_interval_options {
                   5578:     my ($interval_type) = @_;
                   5579:     if (ref($intervals{$interval_type}) eq 'ARRAY') {
                   5580:         return $intervals{$interval_type};
                   5581:     }
                   5582:     return;
                   5583: }
                   5584: 
1.563     damieng  5585: # Returns HTML to edit a date interval parameter.
                   5586: #
                   5587: # @param {string} $thiskey - parameter key
                   5588: # @param {string} $name - parameter name
                   5589: # @param {string} $showval - parameter current value
                   5590: # @param {boolean} $readonly - true if the values should not be made editable
                   5591: # @returns {string}
1.554     raeburn  5592: sub date_interval_selector {
                   5593:     my ($thiskey, $name, $showval, $readonly) = @_;
                   5594:     my ($result,%skipval);
                   5595:     if ($name eq 'interval') {
                   5596:         my $intervaltype = &get_intervaltype($name);
                   5597:         my ($got_chostname,$chostname,$cmajor,$cminor);
                   5598:         foreach my $possibilities (@{ $intervals{$intervaltype} }) {
                   5599:             next unless (ref($possibilities) eq 'ARRAY');
                   5600:             my ($parmval, $description) = @{ $possibilities };
                   5601:             my $parmmatch;
                   5602:             if (ref($intervalmatches{$intervaltype}) eq 'ARRAY') {
                   5603:                 foreach my $item (@{$intervalmatches{$intervaltype}}) {
                   5604:                     if (ref($item) eq 'ARRAY') {
                   5605:                         if ($parmval eq $item->[0]) {
                   5606:                             $parmmatch = $parmval;
                   5607:                             $parmval = '';
                   5608:                             last;
                   5609:                         }
                   5610:                     }
                   5611:                 }
                   5612:             }
                   5613:             my $needsrelease=$Apache::lonnet::needsrelease{"parameter:$name:$parmval:$parmmatch"};
                   5614:             if ($needsrelease) {
                   5615:                 unless ($got_chostname) {
                   5616:                     ($chostname,$cmajor,$cminor)=&parameter_release_vars();
                   5617:                     $got_chostname = 1;
                   5618:                 }
1.557     raeburn  5619:                 my $needsnewer=&parameter_releasecheck($name,$parmval,$parmmatch,undef,
1.554     raeburn  5620:                                                        $needsrelease,$cmajor,$cminor);
                   5621:                 if ($needsnewer) {
                   5622:                     if ($parmmatch ne '') {
                   5623:                         $skipval{$parmmatch} = 1;
                   5624:                     } elsif ($parmval ne '') {
                   5625:                         $skipval{$parmval} = 1;
                   5626:                     }
                   5627:                 }
                   5628:             }
                   5629:         }
                   5630:     }
                   5631: 
                   5632:     my $currval = $showval;
                   5633:     foreach my $which (['days', 86400, 31],
                   5634:                ['hours', 3600, 23],
                   5635:                ['minutes', 60, 59],
                   5636:                ['seconds',  1, 59]) {
1.560     damieng  5637:         my ($name, $factor, $max) = @{ $which };
                   5638:         my $amount = int($showval/$factor);
                   5639:         $showval  %= $factor;
                   5640:         my %select = ((map {$_ => $_} (0..$max)),
                   5641:                 'select_form_order' => [0..$max]);
                   5642:         $result .= &Apache::loncommon::select_form($amount,$name.'_'.$thiskey,
                   5643:                             \%select,'',$readonly);
                   5644:         $result .= ' '.&mt($name);
1.554     raeburn  5645:     }
                   5646:     if ($name eq 'interval') {
                   5647:         unless ($skipval{'done'}) {
                   5648:             my $checkedon = '';
1.558     raeburn  5649:             my $checkedproc = '';
                   5650:             my $currproctorkey = '';
                   5651:             my $currprocdisplay = 'hidden';
1.559     raeburn  5652:             my $currdonetext = &mt('Done');
1.554     raeburn  5653:             my $checkedoff = ' checked="checked"';
1.559     raeburn  5654:             if ($currval =~ /^(?:\d+)_done$/) {
                   5655:                 $checkedon = ' checked="checked"';
                   5656:                 $checkedoff = '';
                   5657:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:$/) {
                   5658:                 $currdonetext = $1;
1.554     raeburn  5659:                 $checkedon = ' checked="checked"';
                   5660:                 $checkedoff = '';
1.558     raeburn  5661:             } elsif ($currval =~ /^(?:\d+)_done_proctor_(.+)$/) {
                   5662:                 $currproctorkey = $1;
                   5663:                 $checkedproc = ' checked="checked"';
                   5664:                 $checkedoff = '';
                   5665:                 $currprocdisplay = 'text';
1.559     raeburn  5666:             } elsif ($currval =~ /^(?:\d+)_done\:([^\:]+)\:_proctor_(.+)$/) {
                   5667:                 $currdonetext = $1;
                   5668:                 $currproctorkey = $2;
                   5669:                 $checkedproc = ' checked="checked"';
                   5670:                 $checkedoff = '';
                   5671:                 $currprocdisplay = 'text';
1.554     raeburn  5672:             }
1.558     raeburn  5673:             my $onclick = ' onclick="toggleSecret(this.form,'."'done_','$thiskey'".');"';
1.567     raeburn  5674:             my $disabled;
                   5675:             if ($readonly) {
                   5676:                 $disabled = ' disabled="disabled"';
                   5677:             }
1.558     raeburn  5678:             $result .= '<br /><span class="LC_nobreak">'.&mt('Include "done" button').
1.567     raeburn  5679:                        '<label><input type="radio" value="" name="done_'.$thiskey.'"'.$checkedoff.$onclick.$disabled.' />'.
1.558     raeburn  5680:                        &mt('No').'</label>'.('&nbsp;'x2).
1.567     raeburn  5681:                        '<label><input type="radio" value="_done" name="done_'.$thiskey.'"'.$checkedon.$onclick.$disabled.' />'.
1.558     raeburn  5682:                        &mt('Yes').'</label>'.('&nbsp;'x2).
1.567     raeburn  5683:                        '<label><input type="radio" value="_done_proctor" name="done_'.$thiskey.'"'.$checkedproc.$onclick.$disabled.' />'.
1.558     raeburn  5684:                        &mt('Yes, with proctor key').'</label>'.
                   5685:                        '<input type="'.$currprocdisplay.'" id="done_'.$thiskey.'_proctorkey" '.
1.567     raeburn  5686:                        'name="done_'.$thiskey.'_proctorkey" value="'.&HTML::Entities::encode($currproctorkey,'"<>&').'"'.$disabled.' /></span><br />'.
1.559     raeburn  5687:                        '<span class="LC_nobreak">'.&mt('Button text').': '.
1.567     raeburn  5688:                        '<input type="text" name="done_'.$thiskey.'_buttontext" value="'.&HTML::Entities::encode($currdonetext,'"<>&').'"'.$disabled.' /></span>';
1.554     raeburn  5689:         }
                   5690:     }
                   5691:     unless ($readonly) {
                   5692:         $result .= '<input type="hidden" name="dateinterval_'.$thiskey.'" />';
                   5693:     }
                   5694:     return $result;
                   5695: }
                   5696: 
1.563     damieng  5697: # Returns HTML with a warning if a parameter requires a more recent version of LON-CAPA.
                   5698: #
                   5699: # @param {string} $name - parameter name
                   5700: # @param {string} $namematch - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   5701: # @param {string} $value - parameter value
                   5702: # @param {string} $chostname - course server name
                   5703: # @param {integer} $cmajor - major version number
                   5704: # @param {integer} $cminor - minor version number
                   5705: # @param {string} $needsrelease - release version needed (major.minor)
                   5706: # @returns {string}
1.549     raeburn  5707: sub oldversion_warning {
1.557     raeburn  5708:     my ($name,$namematch,$value,$chostname,$cmajor,$cminor,$needsrelease) = @_;
                   5709:     my $standard_name = &standard_parameter_names($name);
                   5710:     if ($namematch) {
                   5711:         my $level = &standard_parameter_levels($namematch);
                   5712:         my $msg = '';
                   5713:         if ($level) {
                   5714:             $msg = &mt('[_1] was [_2]not[_3] set at the level of: [_4].',
                   5715:                        $standard_name,'<b>','</b>','"'.$level.'"');
                   5716:         } else {
                   5717:             $msg = &mt('[_1] was [_2]not[_3] set.',
                   5718:                       $standard_name,'<b>','</b>');
                   5719:         }
                   5720:         return '<p class="LC_warning">'.$msg.'<br />'.
                   5721:                &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5722:                    $cmajor.'.'.$cminor,$chostname,
                   5723:                    $needsrelease).
                   5724:                    '</p>';
                   5725:     }
1.549     raeburn  5726:     my $desc;
                   5727:     my $stringtype = &get_stringtype($name);
                   5728:     if ($stringtype ne '') {
                   5729:         if ($name eq 'examcode') {
                   5730:             $desc = $value;
                   5731:         } elsif (ref($strings{$stringtypes{$name}}) eq 'ARRAY') {
                   5732:             foreach my $possibilities (@{ $strings{$stringtypes{$name}} }) {
                   5733:                 next unless (ref($possibilities) eq 'ARRAY');
                   5734:                 my ($parmval, $description) = @{ $possibilities };
                   5735:                 my $parmmatch;
                   5736:                 if (ref($stringmatches{$stringtypes{$name}}) eq 'ARRAY') {
                   5737:                     foreach my $item (@{$stringmatches{$stringtypes{$name}}}) {
                   5738:                         if (ref($item) eq 'ARRAY') {
                   5739:                             my ($regexpname,$pattern) = @{$item};
                   5740:                             if ($parmval eq $regexpname) {
                   5741:                                 if ($value =~ /$pattern/) {
                   5742:                                     $desc = $description; 
                   5743:                                     $parmmatch = 1;
                   5744:                                     last;
                   5745:                                 }
                   5746:                             }
                   5747:                         }
                   5748:                     }
                   5749:                     last if ($parmmatch);
                   5750:                 } elsif ($parmval eq $value) {
                   5751:                     $desc = $description;
                   5752:                     last;
                   5753:                 }
                   5754:             }
                   5755:         }
                   5756:     } elsif (($name eq 'printstartdate') || ($name eq 'printenddate')) {
                   5757:         my $now = time;
                   5758:         if ($value =~ /^\d+$/) {
                   5759:             if ($name eq 'printstartdate') {
                   5760:                 if ($value > $now) {
                   5761:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5762:                 }
                   5763:             } elsif ($name eq 'printenddate') {
                   5764:                 if ($value < $now) {
                   5765:                     $desc = &Apache::lonlocal::locallocaltime($value);
                   5766:                 }
                   5767:             }
                   5768:         }
                   5769:     }
                   5770:     return '<p class="LC_warning">'.
1.557     raeburn  5771:        &mt('[_1] was [_2]not[_3] set to [_4].',
                   5772:            $standard_name,'<b>','</b>','"'.$desc.'"').'<br />'.
                   5773:        &mt('LON-CAPA version ([_1]) installed on home server ([_2]) does not meet version requirements ([_3] or newer).',
                   5774:        $cmajor.'.'.$cminor,$chostname,
                   5775:        $needsrelease).
                   5776:        '</p>';
1.549     raeburn  5777: }
                   5778: 
1.560     damieng  5779: } # end of block using some constants related to parameter types
                   5780: 
1.549     raeburn  5781: 
1.563     damieng  5782: 
                   5783: # Shifts all start and end dates in the current course by $shift.
1.389     www      5784: #
1.563     damieng  5785: # @param {integer} $shift - time to shift, in seconds
                   5786: # @returns {string} - error name or 'ok'
1.389     www      5787: sub dateshift {
1.594     raeburn  5788:     my ($shift,$numchanges)=@_;
1.389     www      5789:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5790:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  5791:     my $sec = $env{'request.course.sec'};
1.595     raeburn  5792:     my $secgrpregex;
                   5793:     if ($sec ne '') {
                   5794:         my @groups;
                   5795:         if ($env{'request.course.groups'} ne '') {
                   5796:             @groups = split(/:/,$env{'request.course.groups'});
                   5797:         }
                   5798:         if (@groups) {
                   5799:             $secgrpregex = '(?:'.join('|',($sec,@groups)).')';
                   5800:         } else {
                   5801:             $secgrpregex = $sec;
                   5802:         }
                   5803:     }
1.389     www      5804:     my %data=&Apache::lonnet::dump('resourcedata',$dom,$crs);
                   5805: # ugly retro fix for broken version of types
1.548     raeburn  5806:     foreach my $key (keys(%data)) {
1.389     www      5807:         if ($key=~/\wtype$/) {
                   5808:             my $newkey=$key;
                   5809:             $newkey=~s/type$/\.type/;
                   5810:             $data{$newkey}=$data{$key};
                   5811:             delete $data{$key};
                   5812:         }
                   5813:     }
1.391     www      5814:     my %storecontent=();
1.389     www      5815: # go through all parameters and look for dates
1.548     raeburn  5816:     foreach my $key (keys(%data)) {
1.389     www      5817:        if ($data{$key.'.type'}=~/^date_(start|end)$/) {
1.594     raeburn  5818:           if ($sec ne '') {
1.595     raeburn  5819:               next unless ($key =~ /^$env{'request.course.id'}\.\[$secgrpregex\]\./);
1.594     raeburn  5820:           }
1.389     www      5821:           my $newdate=$data{$key}+$shift;
1.594     raeburn  5822:           $$numchanges ++;
1.391     www      5823:           $storecontent{$key}=$newdate;
1.389     www      5824:        }
                   5825:     }
1.391     www      5826:     my $reply=&Apache::lonnet::cput
                   5827:                 ('resourcedata',\%storecontent,$dom,$crs);
                   5828:     if ($reply eq 'ok') {
                   5829:        &log_parmset(\%storecontent);
                   5830:     }
                   5831:     &Apache::lonnet::devalidatecourseresdata($crs,$dom);
                   5832:     return $reply;
1.389     www      5833: }
                   5834: 
1.563     damieng  5835: # Overview mode UI to edit course parameters.
                   5836: #
                   5837: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      5838: sub newoverview {
1.568     raeburn  5839:     my ($r,$parm_permission) = @_;
1.280     albertel 5840: 
1.208     www      5841:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   5842:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  5843:     my $crstype =  $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  5844:     my $readonly = 1;
                   5845:     if ($parm_permission->{'edit'}) {
                   5846:         undef($readonly);
                   5847:     }
1.414     droeschl 5848:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 5849:         text=>"Overview Mode"});
1.523     raeburn  5850: 
                   5851:     my %loaditems = (
1.549     raeburn  5852:                       'onload'   => "showHide_courseContent(); resize_scrollbox('mapmenuscroll','1','1'); showHideLenient();",
1.523     raeburn  5853:                     );
                   5854:     my $js = '
                   5855: <script type="text/javascript">
                   5856: // <![CDATA[
                   5857: '.
                   5858:             &Apache::lonhtmlcommon::resize_scrollbox_js('params')."\n".
                   5859:             &showhide_js()."\n".
1.549     raeburn  5860:             &toggleparmtextbox_js()."\n".
                   5861:             &validateparms_js()."\n".
                   5862:             &ipacc_boxes_js()."\n".
1.558     raeburn  5863:             &done_proctor_js()."\n".
1.588     raeburn  5864:             &deeplink_js()."\n".
1.523     raeburn  5865: '// ]]>
                   5866: </script>
                   5867: ';
1.549     raeburn  5868: 
1.523     raeburn  5869:     my $start_page = &Apache::loncommon::start_page('Set Parameters',$js,
                   5870:                                                     {'add_entries' => \%loaditems,});
1.298     albertel 5871:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      5872:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  5873:     &startSettingsScreen($r,'parmset',$crstype);
1.208     www      5874:     $r->print(<<ENDOVER);
1.549     raeburn  5875: <form method="post" action="/adm/parmset?action=newoverview" name="parmform" onsubmit="return validateParms();">
1.208     www      5876: ENDOVER
1.211     www      5877:     my @ids=();
                   5878:     my %typep=();
                   5879:     my %keyp=();
                   5880:     my %allparms=();
                   5881:     my %allparts=();
                   5882:     my %allmaps=();
                   5883:     my %mapp=();
                   5884:     my %symbp=();
                   5885:     my %maptitles=();
                   5886:     my %uris=();
                   5887:     my %keyorder=&standardkeyorder();
                   5888:     my %defkeytype=();
                   5889: 
                   5890:     my %alllevs=();
                   5891:     $alllevs{'Resource Level'}='full';
1.215     www      5892:     $alllevs{'Map/Folder Level'}='map';
1.211     www      5893:     $alllevs{'Course Level'}='general';
                   5894: 
                   5895:     my $csec=$env{'form.csec'};
1.269     raeburn  5896:     my $cgroup=$env{'form.cgroup'};
1.211     www      5897: 
                   5898:     my @pscat=&Apache::loncommon::get_env_multiple('form.pscat');
                   5899:     my $pschp=$env{'form.pschp'};
1.506     www      5900: 
1.211     www      5901:     my @psprt=&Apache::loncommon::get_env_multiple('form.psprt');
1.516     www      5902:     if (!@psprt) { $psprt[0]='all'; }
1.211     www      5903: 
1.446     bisitz   5904:     my @selected_sections =
1.473     amueller 5905:     &Apache::loncommon::get_env_multiple('form.Section');
1.211     www      5906:     @selected_sections = ('all') if (! @selected_sections);
1.374     albertel 5907:     foreach my $sec (@selected_sections) {
                   5908:         if ($sec eq 'all') {
1.211     www      5909:             @selected_sections = ('all');
                   5910:         }
                   5911:     }
1.552     raeburn  5912:     if ($env{'request.course.sec'} ne '') {
                   5913:         @selected_sections = ($env{'request.course.sec'});
                   5914:     }
1.269     raeburn  5915:     my @selected_groups =
                   5916:         &Apache::loncommon::get_env_multiple('form.Group');
1.211     www      5917: 
                   5918:     my $pssymb='';
                   5919:     my $parmlev='';
1.446     bisitz   5920: 
1.211     www      5921:     unless ($env{'form.parmlev'}) {
                   5922:         $parmlev = 'map';
                   5923:     } else {
                   5924:         $parmlev = $env{'form.parmlev'};
                   5925:     }
                   5926: 
1.446     bisitz   5927:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 5928:                 \%mapp, \%symbp,\%maptitles,\%uris,
1.603     raeburn  5929:                 \%keyorder,\%defkeytype,$pssymb);
1.211     www      5930: 
1.374     albertel 5931:     if (grep {$_ eq 'all'} (@psprt)) {
1.481     amueller 5932:         @psprt = keys(%allparts);
1.374     albertel 5933:     }
1.211     www      5934: # Menu to select levels, etc
                   5935: 
1.456     bisitz   5936:     $r->print('<div class="LC_Box">');
1.445     neumanie 5937:     #$r->print('<h2 class="LC_hcell">Step 1</h2>');
1.452     bisitz   5938:     $r->print('<div>');
1.523     raeburn  5939:     $r->print(&Apache::lonhtmlcommon::start_pick_box(undef,'parmlevel'));
1.211     www      5940:     &levelmenu($r,\%alllevs,$parmlev);
                   5941:     if ($parmlev ne 'general') {
1.447     bisitz   5942:         $r->print(&Apache::lonhtmlcommon::row_closure());
1.483     amueller 5943:         &mapmenu($r,\%allmaps,$pschp,\%maptitles,\%symbp);
1.211     www      5944:     }
1.447     bisitz   5945:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5946:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5947:     $r->print('</div></div>');
1.446     bisitz   5948: 
1.456     bisitz   5949:     $r->print('<div class="LC_Box">');
1.452     bisitz   5950:     $r->print('<div>');
1.581     raeburn  5951:     &displaymenu($r,\%allparms,\@pscat,\%keyorder);
1.453     schualex 5952:     $r->print(&Apache::lonhtmlcommon::start_pick_box());
1.446     bisitz   5953:     $r->print(&Apache::lonhtmlcommon::row_title(&mt('Select Parts to View')));
1.553     raeburn  5954:     my $sectionselector = &sectionmenu(\@selected_sections);
                   5955:     my $groupselector = &groupmenu(\@selected_groups);
1.481     amueller 5956:     $r->print('<table>'.
1.553     raeburn  5957:               '<tr><th>'.&mt('Parts').'</th>');
                   5958:     if ($sectionselector) {
                   5959:         $r->print('<th>'.&mt('Section(s)').'</th>');
                   5960:     }
                   5961:     if ($groupselector) {
                   5962:         $r->print('<th>'.&mt('Group(s)').'</th>');
                   5963:     }
                   5964:     $r->print('</tr><tr><td>');
1.211     www      5965:     &partmenu($r,\%allparts,\@psprt);
1.553     raeburn  5966:     $r->print('</td>');
                   5967:     if ($sectionselector) { 
                   5968:         $r->print('<td>'.$sectionselector.'</td>');
                   5969:     }
                   5970:     if ($groupselector) {
                   5971:         $r->print('<td>'.$groupselector.'</td>');
                   5972:     }
                   5973:     $r->print('</tr></table>');
1.447     bisitz   5974:     $r->print(&Apache::lonhtmlcommon::row_closure(1));
1.445     neumanie 5975:     $r->print(&Apache::lonhtmlcommon::end_pick_box());
                   5976:     $r->print('</div></div>');
                   5977: 
1.456     bisitz   5978:     $r->print('<div class="LC_Box">');
1.452     bisitz   5979:     $r->print('<div>');
1.214     www      5980:     my $sortorder=$env{'form.sortorder'};
                   5981:     unless ($sortorder) { $sortorder='realmstudent'; }
                   5982:     &sortmenu($r,$sortorder);
1.445     neumanie 5983:     $r->print('</div></div>');
1.446     bisitz   5984: 
1.214     www      5985:     $r->print('<p><input type="submit" name="dis" value="'.&mt('Display').'" /></p>');
1.446     bisitz   5986: 
1.211     www      5987: # Build the list data hash from the specified parms
                   5988: 
                   5989:     my $listdata;
                   5990:     %{$listdata}=();
                   5991: 
                   5992:     foreach my $cat (@pscat) {
1.269     raeburn  5993:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_sections,\%defkeytype,\%allmaps,\@ids,\%symbp);
                   5994:         &secgroup_lister($cat,$pschp,$parmlev,$listdata,\@psprt,\@selected_groups,\%defkeytype,\%allmaps,\@ids,\%symbp);
1.211     www      5995:     }
                   5996: 
1.212     www      5997:     if (($env{'form.store'}) || ($env{'form.dis'})) {
1.211     www      5998: 
1.481     amueller 5999:         if ($env{'form.store'}) { &storedata($r,$crs,$dom); }
1.211     www      6000: 
                   6001: # Read modified data
                   6002: 
1.481     amueller 6003:         my $resourcedata=&readdata($crs,$dom);
1.211     www      6004: 
                   6005: # List data
                   6006: 
1.568     raeburn  6007:         &listdata($r,$resourcedata,$listdata,$sortorder,'newoverview',undef,$readonly);
                   6008:     }
                   6009:     $r->print(&tableend());
                   6010:     unless ($readonly) {
                   6011:         $r->print( ((($env{'form.store'}) || ($env{'form.dis'}))?'<p><input type="submit" name="store" value="'.&mt('Save').'" /></p>':'') );
1.211     www      6012:     }
1.568     raeburn  6013:     $r->print('</form>');
1.507     www      6014:     &endSettingsScreen($r);
                   6015:     $r->print(&Apache::loncommon::end_page());
1.208     www      6016: }
                   6017: 
1.563     damieng  6018: # Fills $listdata with parameter information.
                   6019: # Keys use the format course id.[section id].part.name and course id.[section id].part.name.type.
                   6020: # The non-type value is always 1.
                   6021: #
                   6022: # @param {string} $cat - parameter name
1.566     damieng  6023: # @param {string} $pschp - selected map pc, or 'all'
1.563     damieng  6024: # @param {string} $parmlev - selected level value (full|map|general), or ''
                   6025: # @param {hash reference} $listdata - the parameter data that will be modified
                   6026: # @param {array reference} $psprt - selected parts
                   6027: # @param {array reference} $selections - selected sections
                   6028: # @param {hash reference} $defkeytype - hash parameter name -> parameter type
1.566     damieng  6029: # @param {hash reference} $allmaps - hash map pc -> map src
                   6030: # @param {array reference} $ids - resource and map ids
                   6031: # @param {hash reference} $symbp - hash map pc or resource/map id -> map src.'___(all)' or resource symb
1.269     raeburn  6032: sub secgroup_lister {
                   6033:     my ($cat,$pschp,$parmlev,$listdata,$psprt,$selections,$defkeytype,$allmaps,$ids,$symbp) = @_;
                   6034:     foreach my $item (@{$selections}) {
                   6035:         foreach my $part (@{$psprt}) {
                   6036:             my $rootparmkey=$env{'request.course.id'};
                   6037:             if (($item ne 'all') && ($item ne 'none') && ($item)) {
                   6038:                 $rootparmkey.='.['.$item.']';
                   6039:             }
                   6040:             if ($parmlev eq 'general') {
                   6041: # course-level parameter
                   6042:                 my $newparmkey=$rootparmkey.'.'.$part.'.'.$cat;
                   6043:                 $$listdata{$newparmkey}=1;
                   6044:                 $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6045:             } elsif ($parmlev eq 'map') {
                   6046: # map-level parameter
1.548     raeburn  6047:                 foreach my $mapid (keys(%{$allmaps})) {
1.269     raeburn  6048:                     if (($pschp ne 'all') && ($pschp ne $mapid)) { next; }
                   6049:                     my $newparmkey=$rootparmkey.'.'.$$allmaps{$mapid}.'___(all).'.$part.'.'.$cat;
                   6050:                     $$listdata{$newparmkey}=1;
                   6051:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6052:                 }
                   6053:             } else {
                   6054: # resource-level parameter
                   6055:                 foreach my $rid (@{$ids}) {
                   6056:                     my ($map,$resid,$url)=&Apache::lonnet::decode_symb($$symbp{$rid});
                   6057:                     if (($pschp ne 'all') && ($$allmaps{$pschp} ne $map)) { next; }
                   6058:                     my $newparmkey=$rootparmkey.'.'.$$symbp{$rid}.'.'.$part.'.'.$cat;
                   6059:                     $$listdata{$newparmkey}=1;
                   6060:                     $$listdata{$newparmkey.'.type'}=$$defkeytype{$cat};
                   6061:                 }
                   6062:             }
                   6063:         }
                   6064:     }
                   6065: }
                   6066: 
1.563     damieng  6067: # UI to edit parameter settings starting with a list of all existing parameters.
                   6068: # (called by setoverview action)
                   6069: #
                   6070: # @param {Apache2::RequestRec} $r - the Apache request
1.208     www      6071: sub overview {
1.568     raeburn  6072:     my ($r,$parm_permission) = @_;
1.208     www      6073:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6074:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6075:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.568     raeburn  6076:     my $readonly = 1;
                   6077:     if ($parm_permission->{'edit'}) {
                   6078:         undef($readonly);
                   6079:     }
1.549     raeburn  6080:     my $js = '<script type="text/javascript">'."\n".
                   6081:              '// <![CDATA['."\n".
                   6082:              &toggleparmtextbox_js()."\n".
                   6083:              &validateparms_js()."\n".
                   6084:              &ipacc_boxes_js()."\n".
1.558     raeburn  6085:              &done_proctor_js()."\n".
1.588     raeburn  6086:              &deeplink_js()."\n".
1.549     raeburn  6087:              '// ]]>'."\n".
                   6088:              '</script>'."\n";
1.414     droeschl 6089:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setoverview',
1.473     amueller 6090:     text=>"Overview Mode"});
1.549     raeburn  6091:     my %loaditems = (
                   6092:                       'onload'   => "showHideLenient();",
                   6093:                     );
                   6094: 
                   6095:     my $start_page=&Apache::loncommon::start_page('Modify Parameters',$js,{'add_entries' => \%loaditems,});
1.298     albertel 6096:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Overview');
1.507     www      6097:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6098:     &startSettingsScreen($r,'parmset',$crstype);
1.549     raeburn  6099:     $r->print('<form method="post" action="/adm/parmset?action=setoverview" name="parmform" onsubmit="return validateParms();">');
1.507     www      6100: 
1.208     www      6101: # Store modified
                   6102: 
1.568     raeburn  6103:     unless ($readonly) {
                   6104:         &storedata($r,$crs,$dom);
                   6105:     }
1.208     www      6106: 
                   6107: # Read modified data
                   6108: 
1.552     raeburn  6109:     my ($resourcedata,$classlist)=&readdata($crs,$dom);
1.208     www      6110: 
1.214     www      6111: 
                   6112:     my $sortorder=$env{'form.sortorder'};
                   6113:     unless ($sortorder) { $sortorder='realmstudent'; }
                   6114:     &sortmenu($r,$sortorder);
                   6115: 
1.568     raeburn  6116:     my $submitbutton = '<input type="submit" value="'.&mt('Save').'" />';
                   6117: 
                   6118:     if ($readonly) {
                   6119:         $r->print('<p>'.$submitbutton.'</p>');
                   6120:     }
                   6121: 
1.208     www      6122: # List data
                   6123: 
1.568     raeburn  6124:     my $foundkeys=&listdata($r,$resourcedata,$resourcedata,$sortorder,'overview',$classlist,$readonly);
                   6125:     $r->print(&tableend().'<p>');
                   6126:     if ($foundkeys) {
                   6127:         unless ($readonly) {
                   6128:             $r->print('<p>'.$submitbutton.'</p>');
                   6129:         }
                   6130:     } else {
                   6131:         $r->print('<p class="LC_info">'.&mt('There are no parameters.').'</p>');
                   6132:     }
                   6133:     $r->print('</form>'.&Apache::loncommon::end_page());
1.120     www      6134: }
1.121     www      6135: 
1.560     damieng  6136: # Unused sub.
1.563     damieng  6137: #
                   6138: # @param {Apache2::RequestRec} $r - the Apache request
1.333     albertel 6139: sub clean_parameters {
                   6140:     my ($r) = @_;
                   6141:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6142:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6143: 
1.414     droeschl 6144:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=cleanparameters',
1.473     amueller 6145:         text=>"Clean Parameters"});
1.333     albertel 6146:     my $start_page=&Apache::loncommon::start_page('Clean Parameters');
                   6147:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Clean');
                   6148:     $r->print(<<ENDOVER);
                   6149: $start_page
                   6150: $breadcrumbs
                   6151: <form method="post" action="/adm/parmset?action=cleanparameters" name="parmform">
                   6152: ENDOVER
                   6153: # Store modified
                   6154: 
                   6155:     &storedata($r,$crs,$dom);
                   6156: 
                   6157: # Read modified data
                   6158: 
                   6159:     my $resourcedata=&readdata($crs,$dom);
                   6160: 
                   6161: # List data
                   6162: 
                   6163:     $r->print('<h3>'.
1.473     amueller 6164:           &mt('These parameters refer to resources that do not exist.').
                   6165:           '</h3>'.
                   6166:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.'<br />'.
                   6167:           '<br />');
1.333     albertel 6168:     $r->print(&Apache::loncommon::start_data_table().
1.473     amueller 6169:           '<tr>'.
                   6170:           '<th>'.&mt('Delete').'</th>'.
                   6171:           '<th>'.&mt('Parameter').'</th>'.
                   6172:           '</tr>');
1.333     albertel 6173:     foreach my $thiskey (sort(keys(%{$resourcedata}))) {
1.560     damieng  6174:         next if (!exists($resourcedata->{$thiskey.'.type'})
                   6175:             && $thiskey=~/\.type$/);
                   6176:         my %data = &parse_key($thiskey);
                   6177:         if (1) { #exists($data{'realm_exists'})
                   6178:             #&& !$data{'realm_exists'}) {
                   6179:             $r->print(&Apache::loncommon::start_data_table_row().
                   6180:                 '<tr>'.
                   6181:                 '<td><input type="checkbox" name="del_'.$thiskey.'" /></td>'              );
                   6182: 
                   6183:             $r->print('<td>');
                   6184:             my $display_value = $resourcedata->{$thiskey};
                   6185:             if (&isdateparm($resourcedata->{$thiskey.'.type'})) {
                   6186:             $display_value =
                   6187:                 &Apache::lonlocal::locallocaltime($display_value);
                   6188:             }
1.470     raeburn  6189:             my $parmitem = &standard_parameter_names($data{'parameter_name'});
                   6190:             $parmitem = &mt($parmitem);
1.560     damieng  6191:             $r->print(&mt('Parameter: "[_1]" with value: "[_2]"',
                   6192:                 $parmitem,$resourcedata->{$thiskey}));
                   6193:             $r->print('<br />');
                   6194:             if ($data{'scope_type'} eq 'all') {
                   6195:                 $r->print(&mt('All users'));
                   6196:             } elsif ($data{'scope_type'} eq 'user') {
                   6197:                 $r->print(&mt('User: [_1]',join(':',@{$data{'scope'}})));
1.581     raeburn  6198:             } elsif ($data{'scope_type'} eq 'secgroup') {
                   6199:                 $r->print(&mt('Group/Section: [_1]',$data{'scope'}));
1.560     damieng  6200:             }
                   6201:             $r->print('<br />');
                   6202:             if ($data{'realm_type'} eq 'all') {
                   6203:                 $r->print(&mt('All Resources'));
                   6204:             } elsif ($data{'realm_type'} eq 'folder') {
                   6205:                 $r->print(&mt('Folder: [_1]'),$data{'realm'});
                   6206:             } elsif ($data{'realm_type'} eq 'symb') {
                   6207:             my ($map,$resid,$url) =
                   6208:                 &Apache::lonnet::decode_symb($data{'realm'});
                   6209:             $r->print(&mt('Resource: [_1]with ID: [_2]in folder [_3]',
                   6210:                         $url.' <br />&nbsp;&nbsp;&nbsp;',
                   6211:                         $resid.' <br />&nbsp;&nbsp;&nbsp;',$map));
                   6212:             }
                   6213:             $r->print(' <br />&nbsp;&nbsp;&nbsp;'.&mt('Part: [_1]',$data{'parameter_part'}));
                   6214:             $r->print('</td></tr>');
                   6215: 
1.473     amueller 6216:         }
1.333     albertel 6217:     }
                   6218:     $r->print(&Apache::loncommon::end_data_table().'<p>'.
1.473     amueller 6219:           '<input type="submit" value="'.&mt('Delete Selected').'" />'.
1.507     www      6220:           '</p></form>');
                   6221:     &endSettingsScreen($r);
                   6222:     $r->print(&Apache::loncommon::end_page());
1.333     albertel 6223: }
                   6224: 
1.563     damieng  6225: # UI to shift all dates (called by dateshift1 action).
                   6226: # Used by overview mode.
                   6227: #
                   6228: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6229: sub date_shift_one {
                   6230:     my ($r) = @_;
                   6231:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6232:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6233:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.594     raeburn  6234:     my $sec = $env{'request.course.sec'};
1.414     droeschl 6235:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6236:         text=>"Shifting Dates"});
1.594     raeburn  6237:     my $submit_text = &mt('Shift all dates accordingly');
                   6238:     if ($sec ne '') {
1.595     raeburn  6239:         my @groups;
                   6240:         if ($env{'request.course.groups'} ne '') {
                   6241:             @groups = split(/:/,$env{'request.course.groups'});
                   6242:         }
                   6243:         if (@groups) {
                   6244:             $submit_text = &mt("Shift dates set just for your section/group(s), accordingly");
                   6245:         } else {
                   6246:             $submit_text = &mt("Shift dates set just for your section, accordingly");
                   6247:         }
1.594     raeburn  6248:     }
1.390     www      6249:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6250:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6251:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6252:     &startSettingsScreen($r,'parmset',$crstype);
1.538     bisitz   6253:     $r->print('<form name="shiftform" method="post" action="">'.
1.390     www      6254:               '<table><tr><td>'.&mt('Currently set date:').'</td><td>'.
                   6255:               &Apache::lonlocal::locallocaltime($env{'form.timebase'}).'</td></tr>'.
                   6256:               '<tr><td>'.&mt('Shifted date:').'</td><td>'.
1.541     bisitz   6257:                     &Apache::lonhtmlcommon::date_setter('shiftform',
1.390     www      6258:                                                         'timeshifted',
                   6259:                                                         $env{'form.timebase'},,
                   6260:                                                         '').
                   6261:               '</td></tr></table>'.
                   6262:               '<input type="hidden" name="action" value="dateshift2" />'.
                   6263:               '<input type="hidden" name="timebase" value="'.$env{'form.timebase'}.'" />'.
1.594     raeburn  6264:               '<input type="submit" value="'.$submit_text.'" /></form>');
1.507     www      6265:     &endSettingsScreen($r);
1.390     www      6266:     $r->print(&Apache::loncommon::end_page());
                   6267: }
                   6268: 
1.563     damieng  6269: # UI to shift all dates (second form).
                   6270: #
                   6271: # @param {Apache2::RequestRec} $r - the Apache request
1.390     www      6272: sub date_shift_two {
                   6273:     my ($r) = @_;
                   6274:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6275:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.594     raeburn  6276:     my $sec = $env{'request.course.sec'};
1.531     raeburn  6277:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 6278:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=dateshift1&timebase='.$env{'form.timebase'},
1.473     amueller 6279:         text=>"Shifting Dates"});
1.390     www      6280:     my $start_page=&Apache::loncommon::start_page('Shift Dates');
                   6281:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Shift');
1.507     www      6282:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6283:     &startSettingsScreen($r,'parmset',$crstype);
1.390     www      6284:     my $timeshifted=&Apache::lonhtmlcommon::get_date_from_form('timeshifted');
1.594     raeburn  6285:     $r->print('<h2>'.&mt('Shift Dates').'</h2>');
                   6286:     if ($sec ne '') {
1.595     raeburn  6287:         my @groups;
                   6288:         if ($env{'request.course.groups'} ne '') {
                   6289:             @groups = split(/:/,$env{'request.course.groups'});
                   6290:         }
                   6291:         if (@groups) {
                   6292:             $r->print('<p>'.
                   6293:                       &mt("Shift dates set just for your section/group(s), such that [_1] becomes [_2]",
                   6294:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6295:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6296:                       '</p>');
                   6297:         } else {
                   6298:             $r->print('<p>'.
                   6299:                       &mt("Shift dates set just for your section, such that [_1] becomes [_2]",
                   6300:                           &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6301:                           &Apache::lonlocal::locallocaltime($timeshifted)).
                   6302:                       '</p>');
                   6303:         }
1.594     raeburn  6304:     } else {
                   6305:         $r->print('<p>'.&mt('Shifting all dates such that [_1] becomes [_2]',
                   6306:                             &Apache::lonlocal::locallocaltime($env{'form.timebase'}),
                   6307:                             &Apache::lonlocal::locallocaltime($timeshifted)).
                   6308:                   '</p>');
                   6309:     }
1.390     www      6310:     my $delta=$timeshifted-$env{'form.timebase'};
1.594     raeburn  6311:     my $numchanges = 0;
                   6312:     my $result = &dateshift($delta,\$numchanges);
                   6313:     if ($result eq 'ok') {
                   6314:         $r->print(
                   6315:             &Apache::lonhtmlcommon::confirm_success(&mt('Completed shifting of [quant,_1,date setting]',
                   6316:                                                     $numchanges)));
                   6317:     } elsif ($result eq 'con_delayed') {
                   6318:         $r->print(
                   6319:             &Apache::lonhtmlcommon::confirm_success(&mt('Queued shifting of [quant,_1,date setting]',
                   6320:                                                         $numchanges)));
                   6321:     } else {
                   6322:         $r->print(
                   6323:             &Apache::lonhtmlcommon::confirm_success(&mt('An error occurred attempting to shift dates'),1));
                   6324:     }
1.543     bisitz   6325:     $r->print(
                   6326:         '<br /><br />'.
                   6327:         &Apache::lonhtmlcommon::actionbox(
                   6328:             ['<a href="/adm/parmset">'.&mt('Content and Problem Settings').'</a>']));
1.507     www      6329:     &endSettingsScreen($r);
1.390     www      6330:     $r->print(&Apache::loncommon::end_page());
                   6331: }
                   6332: 
1.563     damieng  6333: # Returns the different components of a resourcedata key.
                   6334: # Keys: scope_type, scope, realm_type, realm, realm_title,
                   6335: #       realm_exists, parameter_part, parameter_name.
                   6336: # Was used by clean_parameters (which is unused).
                   6337: #
                   6338: # @param {string} $key - the parameter key
                   6339: # @returns {hash}
1.333     albertel 6340: sub parse_key {
                   6341:     my ($key) = @_;
                   6342:     my %data;
                   6343:     my ($middle,$part,$name)=
1.572     damieng  6344:     ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.333     albertel 6345:     $data{'scope_type'} = 'all';
                   6346:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  6347:         $data{'scope'} = $1;
                   6348:         if ($data{'scope'}=~/^useropt\:($match_username)\:($match_domain)/) {
                   6349:             $data{'scope_type'} = 'user';
                   6350:             $data{'scope'} = [$1,$2];
                   6351:         } else {
1.581     raeburn  6352:             $data{'scope_type'} = 'secgroup';
1.560     damieng  6353:         }
                   6354:         $middle=~s/^\[(.*)\]//;
1.333     albertel 6355:     }
                   6356:     $middle=~s/\.+$//;
                   6357:     $middle=~s/^\.+//;
                   6358:     $data{'realm_type'}='all';
                   6359:     if ($middle=~/^(.+)\_\_\_\(all\)$/) {
1.560     damieng  6360:         $data{'realm'} = $1;
                   6361:         $data{'realm_type'} = 'folder';
                   6362:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6363:         ($data{'realm_exists'}) = &Apache::lonnet::is_on_map($data{'realm'});
1.333     albertel 6364:     } elsif ($middle) {
1.560     damieng  6365:         $data{'realm'} = $middle;
                   6366:         $data{'realm_type'} = 'symb';
                   6367:         $data{'realm_title'} = &Apache::lonnet::gettitle($data{'realm'});
                   6368:         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($data{'realm'});
                   6369:         $data{'realm_exists'} = &Apache::lonnet::symbverify($data{'realm'},$url);
1.333     albertel 6370:     }
1.446     bisitz   6371: 
1.333     albertel 6372:     $data{'parameter_part'} = $part;
                   6373:     $data{'parameter_name'} = $name;
                   6374: 
                   6375:     return %data;
                   6376: }
                   6377: 
1.239     raeburn  6378: 
1.563     damieng  6379: # Calls loncommon::start_page with the "Settings" title.
1.416     jms      6380: sub header {
1.507     www      6381:     return &Apache::loncommon::start_page('Settings');
1.416     jms      6382: }
1.193     albertel 6383: 
                   6384: 
                   6385: 
1.560     damieng  6386: ##################################################
                   6387: # MAIN MENU
                   6388: ##################################################
                   6389: 
1.563     damieng  6390: # Content and problem settings main menu.
                   6391: #
                   6392: # @param {Apache2::RequestRec} $r - the Apache request
                   6393: # @param {boolean} $parm_permission - true if the user has permission to edit the current course or section
1.193     albertel 6394: sub print_main_menu {
                   6395:     my ($r,$parm_permission)=@_;
                   6396:     #
1.414     droeschl 6397:     $r->print(&header());
1.507     www      6398:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Content and Problem Settings'));
1.531     raeburn  6399:     my $crstype = &Apache::loncommon::course_type();
                   6400:     my $lc_crstype = lc($crstype);
                   6401: 
                   6402:     &startSettingsScreen($r,'parmset',$crstype);
1.193     albertel 6403:     $r->print(<<ENDMAINFORMHEAD);
                   6404: <form method="post" enctype="multipart/form-data"
                   6405:       action="/adm/parmset" name="studentform">
                   6406: ENDMAINFORMHEAD
                   6407: #
1.195     albertel 6408:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6409:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.268     albertel 6410:     my $vgr  = &Apache::lonnet::allowed('vgr',$env{'request.course.id'});
1.366     albertel 6411:     my $mgr  = &Apache::lonnet::allowed('mgr',$env{'request.course.id'});
1.520     raeburn  6412:     my $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'});
1.568     raeburn  6413:     my $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'});
                   6414:     my $vpa = &Apache::lonnet::allowed('vpa',$env{'request.course.id'});
1.520     raeburn  6415:     if ((!$dcm) && ($env{'request.course.sec'} ne '')) {
                   6416:         $dcm = &Apache::lonnet::allowed('dcm',$env{'request.course.id'}.
                   6417:                                         '/'.$env{'request.course.sec'});
                   6418:     }
1.568     raeburn  6419:     if ((!$vcb) && ($env{'request.course.sec'} ne '')) {
                   6420:         $vcb = &Apache::lonnet::allowed('vcb',$env{'request.course.id'}.
                   6421:                                         '/'.$env{'request.course.sec'});
                   6422:     }
                   6423:     my (%linktext,%linktitle,%url);
                   6424:     if ($parm_permission->{'edit'}) {
                   6425:         %linktext = (
                   6426:                      newoverview     => 'Edit Resource Parameters - Overview Mode',
                   6427:                      settable        => 'Edit Resource Parameters - Table Mode',
                   6428:                      setoverview     => 'Modify Resource Parameters - Overview Mode',
                   6429:                     );
                   6430:         %linktitle = (
                   6431:                      newoverview     => 'Set/Modify resource parameters in overview mode.',
                   6432:                      settable        => 'Set/Modify resource parameters in table mode.',
                   6433:                      setoverview     => 'Set/Modify existing resource parameters in overview mode.',
                   6434:                      );
                   6435:     } else {
                   6436:         %linktext = (
                   6437:                      newoverview     => 'View Resource Parameters - Overview Mode',
                   6438:                      settable        => 'View Resource Parameters - Table Mode',
                   6439:                      setoverview     => 'View Resource Parameters - Overview Mode',
                   6440:                    );
                   6441:         %linktitle = (
                   6442:                      newoverview     => 'Display resource parameters in overview mode.',
                   6443:                      settable        => 'Display resource parameters in table mode.',
                   6444:                      setoverview     => 'Display existing resource parameters in overview mode.',
                   6445:                      );
                   6446:     }
                   6447:     if ($mgr) {
                   6448:         $linktext{'resettimes'} = 'Reset Student Access Times';
                   6449:         $linktitle{'resettimes'} = "Reset access times for folders/maps, resources or the $lc_crstype.";
                   6450:         $url{'resettimes'} = '/adm/helper/resettimes.helper';
                   6451:     } elsif ($vgr) {
                   6452:         $linktext{'resettimes'} = 'Display Student Access Times',
                   6453:         $linktitle{'resettimes'} = "Display access times for folders/maps, resources or the $lc_crstype.",
                   6454:         $url{'resettimes'} = '/adm/accesstimes';
                   6455:     }
1.193     albertel 6456:     my @menu =
1.507     www      6457:         ( { categorytitle=>"Content Settings for this $crstype",
1.473     amueller 6458:         items => [
                   6459:           { linktext => 'Portfolio Metadata',
                   6460:             url => '/adm/parmset?action=setrestrictmeta',
1.568     raeburn  6461:             permission => $parm_permission->{'setrestrictmeta'},
1.477     raeburn  6462:             linktitle => "Restrict metadata for this $lc_crstype." ,
1.473     amueller 6463:             icon =>'contact-new.png'   ,
                   6464:             },
1.568     raeburn  6465:           { linktext => $linktext{'resettimes'},
                   6466:             url => $url{'resettimes'},
                   6467:             permission => ($vgr || $mgr),
                   6468:             linktitle => $linktitle{'resettimes'},
                   6469:             icon => 'start-here.png',
1.473     amueller 6470:             },
1.520     raeburn  6471:           { linktext => 'Blocking Communication/Resource Access',
                   6472:             url => '/adm/setblock',
1.568     raeburn  6473:             permission => ($vcb || $dcm),
1.520     raeburn  6474:             linktitle => 'Configure blocking of communication/collaboration and access to resources during an exam',
                   6475:             icon => 'comblock.png',
                   6476:             },
1.473     amueller 6477:           { linktext => 'Set Parameter Setting Default Actions',
                   6478:             url => '/adm/parmset?action=setdefaults',
1.568     raeburn  6479:             permission => $parm_permission->{'setdefaults'},
1.473     amueller 6480:             linktitle =>'Set default actions for parameters.'  ,
                   6481:             icon => 'folder-new.png'  ,
                   6482:             }]},
                   6483:       { categorytitle => 'New and Existing Parameter Settings for Resources',
                   6484:         items => [
                   6485:           { linktext => 'Edit Resource Parameters - Helper Mode',
                   6486:             url => '/adm/helper/parameter.helper',
1.568     raeburn  6487:             permission => $parm_permission->{'helper'},
1.473     amueller 6488:             linktitle =>'Set/Modify resource parameters in helper mode.'  ,
                   6489:             icon => 'dialog-information.png'  ,
                   6490:             #help => 'Parameter_Helper',
                   6491:             },
1.568     raeburn  6492:           { linktext => $linktext{'newoverview'},
1.473     amueller 6493:             url => '/adm/parmset?action=newoverview',
1.568     raeburn  6494:             permission => $parm_permission->{'newoverview'},
                   6495:             linktitle => $linktitle{'newoverview'},
                   6496:             icon => 'edit-find.png',
1.473     amueller 6497:             #help => 'Parameter_Overview',
                   6498:             },
1.568     raeburn  6499:           { linktext => $linktext{'settable'},
1.473     amueller 6500:             url => '/adm/parmset?action=settable',
1.568     raeburn  6501:             permission => $parm_permission->{'settable'},
                   6502:             linktitle => $linktitle{'settable'},
                   6503:             icon => 'edit-copy.png',
1.473     amueller 6504:             #help => 'Table_Mode',
                   6505:             }]},
1.417     droeschl 6506:            { categorytitle => 'Existing Parameter Settings for Resources',
1.473     amueller 6507:          items => [
1.570     raeburn  6508:           { linktext => $linktext{'setoverview'},
1.473     amueller 6509:             url => '/adm/parmset?action=setoverview',
1.568     raeburn  6510:             permission => $parm_permission->{'setoverview'},
                   6511:             linktitle => $linktitle{'setoverview'},
                   6512:             icon => 'preferences-desktop-wallpaper.png',
1.473     amueller 6513:             #help => 'Parameter_Overview',
                   6514:             },
                   6515:           { linktext => 'Change Log',
                   6516:             url => '/adm/parmset?action=parameterchangelog',
1.568     raeburn  6517:             permission => $parm_permission->{'parameterchangelog'},
1.477     raeburn  6518:             linktitle =>"View parameter and $lc_crstype blog posting/user notification change log."  ,
1.487     wenzelju 6519:             icon => 'document-properties.png',
1.473     amueller 6520:             }]}
1.193     albertel 6521:           );
1.414     droeschl 6522:     $r->print(&Apache::lonhtmlcommon::generate_menu(@menu));
1.539     raeburn  6523:     $r->print('</form>');
1.507     www      6524:     &endSettingsScreen($r);
1.539     raeburn  6525:     $r->print(&Apache::loncommon::end_page());
1.193     albertel 6526:     return;
                   6527: }
1.414     droeschl 6528: 
1.416     jms      6529: 
                   6530: 
1.560     damieng  6531: ##################################################
                   6532: # PORTFOLIO METADATA
                   6533: ##################################################
                   6534: 
1.563     damieng  6535: # Prints HTML to edit an item of portfolio metadata. The HTML contains several td elements (no tr).
                   6536: # It looks like field titles are not localized.
                   6537: #
                   6538: # @param {Apache2::RequestRec} $r - the Apache request
                   6539: # @param {string} $field_name - metadata field name
                   6540: # @param {string} $field_text - metadata field title, in English unless manually added
                   6541: # @param {boolean} $added_flag - true if the field was manually added
1.252     banghart 6542: sub output_row {
1.347     banghart 6543:     my ($r, $field_name, $field_text, $added_flag) = @_;
1.252     banghart 6544:     my $output;
1.263     banghart 6545:     my $options=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'};
                   6546:     my $values=$env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.values'};
1.337     banghart 6547:     if (!defined($options)) {
1.254     banghart 6548:         $options = 'active,stuadd';
1.261     banghart 6549:         $values = '';
1.252     banghart 6550:     }
1.337     banghart 6551:     if (!($options =~ /deleted/)) {
                   6552:         my @options= ( ['active', 'Show to student'],
1.418     schafran 6553:                     ['stuadd', 'Provide text area for students to type metadata'],
1.351     banghart 6554:                     ['choices','Provide choices for students to select from']);
1.473     amueller 6555: #           ['onlyone','Student may select only one choice']);
1.337     banghart 6556:         if ($added_flag) {
                   6557:             push @options,['deleted', 'Delete Metadata Field'];
                   6558:         }
1.351     banghart 6559:        $output = &Apache::loncommon::start_data_table_row();
1.451     bisitz   6560:         $output .= '<td><strong>'.$field_text.':</strong></td>';
1.351     banghart 6561:         $output .= &Apache::loncommon::end_data_table_row();
1.337     banghart 6562:         foreach my $opt (@options) {
1.560     damieng  6563:             my $checked = ($options =~ m/$opt->[0]/) ? ' checked="checked" ' : '' ;
                   6564:             $output .= &Apache::loncommon::continue_data_table_row();
                   6565:             $output .= '<td>'.('&nbsp;' x 5).'<label>
                   6566:                     <input type="checkbox" name="'.
                   6567:                     $field_name.'_'.$opt->[0].'" value="yes"'.$checked.' />'.
                   6568:                     &mt($opt->[1]).'</label></td>';
                   6569:             $output .= &Apache::loncommon::end_data_table_row();
                   6570:         }
1.351     banghart 6571:         $output .= &Apache::loncommon::continue_data_table_row();
1.451     bisitz   6572:         $output .= '<td>'.('&nbsp;' x 10).'<input name="'.$field_name.'_values" type="text" value="'.$values.'" size="80" /></td>';
1.351     banghart 6573:         $output .= &Apache::loncommon::end_data_table_row();
                   6574:         my $multiple_checked;
                   6575:         my $single_checked;
                   6576:         if ($options =~ m/onlyone/) {
1.422     bisitz   6577:             $multiple_checked = '';
1.423     bisitz   6578:             $single_checked = ' checked="checked"';
1.351     banghart 6579:         } else {
1.423     bisitz   6580:             $multiple_checked = ' checked="checked"';
1.422     bisitz   6581:             $single_checked = '';
1.351     banghart 6582:         }
1.560     damieng  6583:         $output .= &Apache::loncommon::continue_data_table_row();
                   6584:         $output .= '<td>'.('&nbsp;' x 10).'
                   6585:                     <input type="radio" name="'.$field_name.'_onlyone" value="multiple"'.$multiple_checked .' />
                   6586:                     '.&mt('Student may select multiple choices from list').'</td>';
                   6587:         $output .= &Apache::loncommon::end_data_table_row();
                   6588:         $output .= &Apache::loncommon::continue_data_table_row();
                   6589:         $output .= '<td>'.('&nbsp;' x 10).'
                   6590:                     <input type="radio" name="'.$field_name.'_onlyone"  value="single"'.$single_checked.' />
                   6591:                     '.&mt('Student may select only one choice from list').'</td>';
                   6592:         $output .= &Apache::loncommon::end_data_table_row();
1.252     banghart 6593:     }
                   6594:     return ($output);
                   6595: }
1.416     jms      6596: 
                   6597: 
1.560     damieng  6598: # UI to order portfolio metadata fields.
1.563     damieng  6599: # Currently useless because addmetafield does not work.
                   6600: #
                   6601: # @param {Apache2::RequestRec} $r - the Apache request
1.340     banghart 6602: sub order_meta_fields {
                   6603:     my ($r)=@_;
                   6604:     my $idx = 1;
                   6605:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6606:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6607:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};;
1.341     banghart 6608:     $r->print(&Apache::loncommon::start_page('Order Metadata Fields'));
1.560     damieng  6609:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6610:         {href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6611:         text=>"Add Metadata Field"});
1.560     damieng  6612:     &Apache::lonhtmlcommon::add_breadcrumb(
                   6613:         {href=>"/adm/parmset?action=setrestrictmeta",
                   6614:         text=>"Restrict Metadata"},
                   6615:         {text=>"Order Metadata"});
1.345     banghart 6616:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Order Metadata'));
1.531     raeburn  6617:     &startSettingsScreen($r,'parmset',$crstype);
1.340     banghart 6618:     if ($env{'form.storeorder'}) {
                   6619:         my $newpos = $env{'form.newpos'} - 1;
                   6620:         my $currentpos = $env{'form.currentpos'} - 1;
                   6621:         my @neworder = ();
1.548     raeburn  6622:         my @oldorder = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6623:         my $i;
1.341     banghart 6624:         if ($newpos > $currentpos) {
1.340     banghart 6625:         # moving stuff up
                   6626:             for ($i=0;$i<$currentpos;$i++) {
1.560     damieng  6627:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6628:             }
                   6629:             for ($i=$currentpos;$i<$newpos;$i++) {
1.560     damieng  6630:                 $neworder[$i]=$oldorder[$i+1];
1.340     banghart 6631:             }
                   6632:             $neworder[$newpos]=$oldorder[$currentpos];
                   6633:             for ($i=$newpos+1;$i<=$#oldorder;$i++) {
1.560     damieng  6634:                 $neworder[$i]=$oldorder[$i];
1.340     banghart 6635:             }
                   6636:         } else {
                   6637:         # moving stuff down
1.473     amueller 6638:             for ($i=0;$i<$newpos;$i++) {
                   6639:                 $neworder[$i]=$oldorder[$i];
                   6640:             }
                   6641:             $neworder[$newpos]=$oldorder[$currentpos];
                   6642:             for ($i=$newpos+1;$i<$currentpos+1;$i++) {
                   6643:                 $neworder[$i]=$oldorder[$i-1];
                   6644:             }
                   6645:             for ($i=$currentpos+1;$i<=$#oldorder;$i++) {
                   6646:                 $neworder[$i]=$oldorder[$i];
                   6647:             }
1.340     banghart 6648:         }
1.560     damieng  6649:         my $ordered_fields = join ",", @neworder;
1.343     banghart 6650:         my $put_result = &Apache::lonnet::put('environment',
1.560     damieng  6651:                         {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6652:         &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.metadata.addedorder' => $ordered_fields});
1.340     banghart 6653:     }
1.357     raeburn  6654:     my $fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.341     banghart 6655:     my $ordered_fields;
1.548     raeburn  6656:     my @fields_in_order = split(/,/,$env{'course.'.$env{'request.course.id'}.'.metadata.addedorder'});
1.340     banghart 6657:     if (!@fields_in_order) {
                   6658:         # no order found, pick sorted order then create metadata.addedorder key.
1.548     raeburn  6659:         foreach my $key (sort(keys(%$fields))) {
1.340     banghart 6660:             push @fields_in_order, $key;
1.341     banghart 6661:             $ordered_fields = join ",", @fields_in_order;
1.340     banghart 6662:         }
1.341     banghart 6663:         my $put_result = &Apache::lonnet::put('environment',
1.446     bisitz   6664:                             {'metadata.addedorder'=>$ordered_fields},$dom,$crs);
                   6665:     }
1.340     banghart 6666:     $r->print('<table>');
                   6667:     my $num_fields = scalar(@fields_in_order);
                   6668:     foreach my $key (@fields_in_order) {
                   6669:         $r->print('<tr><td>');
                   6670:         $r->print('<form method="post" action="">');
1.537     bisitz   6671:         $r->print('<select name="newpos" onchange="this.form.submit()">');
1.340     banghart 6672:         for (my $i = 1;$i le $num_fields;$i ++) {
                   6673:             if ($i eq $idx) {
                   6674:                 $r->print('<option value="'.$i.'"  SELECTED>('.$i.')</option>');
                   6675:             } else {
                   6676:                 $r->print('<option value="'.$i.'">'.$i.'</option>');
                   6677:             }
                   6678:         }
                   6679:         $r->print('</select></td><td>');
                   6680:         $r->print('<input type="hidden" name="currentpos" value="'.$idx.'" />');
                   6681:         $r->print('<input type="hidden" name="storeorder" value="true" />');
                   6682:         $r->print('</form>');
                   6683:         $r->print($$fields{$key}.'</td></tr>');
                   6684:         $idx ++;
                   6685:     }
                   6686:     $r->print('</table>');
1.507     www      6687:     &endSettingsScreen($r);
1.340     banghart 6688:     return 'ok';
                   6689: }
1.416     jms      6690: 
                   6691: 
1.563     damieng  6692: # Returns HTML with a Continue button redirecting to the initial portfolio metadata screen.
                   6693: # @returns {string}
1.359     banghart 6694: sub continue {
                   6695:     my $output;
                   6696:     $output .= '<form action="" method="post">';
                   6697:     $output .= '<input type="hidden" name="action" value="setrestrictmeta" />';
1.586     raeburn  6698:     $output .= '<input type="submit" value="'.&mt('Continue').'" />';
1.359     banghart 6699:     return ($output);
                   6700: }
1.416     jms      6701: 
                   6702: 
1.563     damieng  6703: # UI to add a metadata field.
                   6704: # Currenly does not work because of an HTML error (the field is not visible).
                   6705: #
                   6706: # @param {Apache2::RequestRec} $r - the Apache request
1.334     banghart 6707: sub addmetafield {
                   6708:     my ($r)=@_;
1.414     droeschl 6709:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=addmetadata',
1.473     amueller 6710:         text=>"Add Metadata Field"});
1.334     banghart 6711:     $r->print(&Apache::loncommon::start_page('Add Metadata Field'));
                   6712:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Add Metadata Field'));
1.335     banghart 6713:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6714:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6715:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6716:     &startSettingsScreen($r,'parmset',$crstype);
1.339     banghart 6717:     if (exists($env{'form.undelete'})) {
1.358     banghart 6718:         my @meta_fields = &Apache::loncommon::get_env_multiple('form.undeletefield');
1.339     banghart 6719:         foreach my $meta_field(@meta_fields) {
                   6720:             my $options = $env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.options'};
                   6721:             $options =~ s/deleted//;
                   6722:             $options =~ s/,,/,/;
                   6723:             my $put_result = &Apache::lonnet::put('environment',
                   6724:                                         {'metadata.'.$meta_field.'.options'=>$options},$dom,$crs);
1.446     bisitz   6725: 
1.586     raeburn  6726:             $r->print(&mt('Undeleted Metadata Field [_1] with result [_2]',
                   6727:                           '<strong>'.$env{'course.'.$env{'request.course.id'}.'.metadata.'.$meta_field.'.added'}.
                   6728:                           '</strong>',$put_result).
                   6729:                       '<br />');
1.339     banghart 6730:         }
1.359     banghart 6731:         $r->print(&continue());
1.339     banghart 6732:     } elsif (exists($env{'form.fieldname'})) {
1.335     banghart 6733:         my $meta_field = $env{'form.fieldname'};
                   6734:         my $display_field = $env{'form.fieldname'};
                   6735:         $meta_field =~ s/\W/_/g;
1.338     banghart 6736:         $meta_field =~ tr/A-Z/a-z/;
1.335     banghart 6737:         my $put_result = &Apache::lonnet::put('environment',
                   6738:                             {'metadata.'.$meta_field.'.values'=>"",
                   6739:                              'metadata.'.$meta_field.'.added'=>"$display_field",
                   6740:                              'metadata.'.$meta_field.'.options'=>""},$dom,$crs);
1.586     raeburn  6741:         $r->print(&mt('Added new Metadata Field [_1] with result [_2]',
                   6742:                       '<strong>'.$env{'form.fieldname'}.'</strong>',$put_result).
                   6743:                   '<br />');
1.359     banghart 6744:         $r->print(&continue());
1.335     banghart 6745:     } else {
1.357     raeburn  6746:         my $fields = &get_deleted_meta_fieldnames($env{'request.course.id'});
1.339     banghart 6747:         if ($fields) {
1.586     raeburn  6748:             $r->print(&mt('You may undelete previously deleted fields.').
                   6749:                       '<br />'.
                   6750:                       &mt('Check those you wish to undelete and click Undelete.').
                   6751:                       '<br />');
1.339     banghart 6752:             $r->print('<form method="post" action="">');
                   6753:             foreach my $key(keys(%$fields)) {
1.581     raeburn  6754:                 $r->print('<label><input type="checkbox" name="undeletefield" value="'.$key.'" />'.$$fields{$key}.'</label><br /');
1.339     banghart 6755:             }
1.586     raeburn  6756:             $r->print('<input type="submit" name="undelete" value="'.&mt('Undelete').'" />');
1.339     banghart 6757:             $r->print('</form>');
                   6758:         }
1.586     raeburn  6759:         $r->print('<hr />'.
                   6760:                   &mt('[_1]Or[_2] you may enter a new metadata field name.',
                   6761:                       '<strong>','</strong>').
1.581     raeburn  6762:                   '<form method="post" action="/adm/parmset?action=addmetadata">');
1.335     banghart 6763:         $r->print('<input type="text" name="fieldname" /><br />');
1.586     raeburn  6764:         $r->print('<input type="submit" value="'.&mt('Add Metadata Field').'" />');
1.581     raeburn  6765:         $r->print('</form>');
1.334     banghart 6766:     }
1.507     www      6767:     &endSettingsScreen($r);
1.334     banghart 6768: }
1.416     jms      6769: 
                   6770: 
                   6771: 
1.560     damieng  6772: # Display or save portfolio metadata.
1.563     damieng  6773: #
                   6774: # @param {Apache2::RequestRec} $r - the Apache request
1.259     banghart 6775: sub setrestrictmeta {
1.240     banghart 6776:     my ($r)=@_;
1.242     banghart 6777:     my $next_meta;
1.244     banghart 6778:     my $output;
1.245     banghart 6779:     my $item_num;
1.246     banghart 6780:     my $put_result;
1.414     droeschl 6781:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setrestrictmeta',
1.473     amueller 6782:         text=>"Restrict Metadata"});
1.280     albertel 6783:     $r->print(&Apache::loncommon::start_page('Restrict Metadata'));
1.298     albertel 6784:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Restrict Metadata'));
1.240     banghart 6785:     my $dom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6786:     my $crs = $env{'course.'.$env{'request.course.id'}.'.num'};
1.531     raeburn  6787:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
                   6788:     &startSettingsScreen($r,'parmset',$crstype);
1.259     banghart 6789:     my $key_base = $env{'course.'.$env{'request.course.id'}.'.'};
1.252     banghart 6790:     my $save_field = '';
1.586     raeburn  6791:     my %lt = &Apache::lonlocal::texthash(
                   6792:                                            addm => 'Add Metadata Field',
                   6793:                                            ordm => 'Order Metadata Fields',
                   6794:                                            save => 'Save',
                   6795:                                         );
1.259     banghart 6796:     if ($env{'form.restrictmeta'}) {
1.254     banghart 6797:         foreach my $field (sort(keys(%env))) {
1.252     banghart 6798:             if ($field=~m/^form.(.+)_(.+)$/) {
1.254     banghart 6799:                 my $options;
1.252     banghart 6800:                 my $meta_field = $1;
                   6801:                 my $meta_key = $2;
1.253     banghart 6802:                 if ($save_field ne $meta_field) {
1.252     banghart 6803:                     $save_field = $meta_field;
1.473     amueller 6804:                     if ($env{'form.'.$meta_field.'_stuadd'}) {
                   6805:                         $options.='stuadd,';
                   6806:                     }
                   6807:                     if ($env{'form.'.$meta_field.'_choices'}) {
                   6808:                         $options.='choices,';
                   6809:                     }
                   6810:                     if ($env{'form.'.$meta_field.'_onlyone'} eq 'single') {
                   6811:                         $options.='onlyone,';
                   6812:                     }
                   6813:                     if ($env{'form.'.$meta_field.'_active'}) {
                   6814:                         $options.='active,';
                   6815:                     }
                   6816:                     if ($env{'form.'.$meta_field.'_deleted'}) {
                   6817:                         $options.='deleted,';
                   6818:                     }
1.259     banghart 6819:                     my $name = $save_field;
1.560     damieng  6820:                     $put_result = &Apache::lonnet::put('environment',
                   6821:                         {'metadata.'.$meta_field.'.options'=>$options,
                   6822:                         'metadata.'.$meta_field.'.values'=>$env{'form.'.$meta_field.'_values'},
                   6823:                         },$dom,$crs);
1.252     banghart 6824:                 }
                   6825:             }
                   6826:         }
                   6827:     }
1.296     albertel 6828:     &Apache::lonnet::coursedescription($env{'request.course.id'},
1.473     amueller 6829:                        {'freshen_cache' => 1});
1.335     banghart 6830:     # Get the default metadata fields
1.258     albertel 6831:     my %metadata_fields = &Apache::lonmeta::fieldnames('portfolio');
1.335     banghart 6832:     # Now get possible added metadata fields
1.357     raeburn  6833:     my $added_metadata_fields = &get_added_meta_fieldnames($env{'request.course.id'});
1.347     banghart 6834:     $output .= &Apache::loncommon::start_data_table();
1.258     albertel 6835:     foreach my $field (sort(keys(%metadata_fields))) {
1.265     banghart 6836:         if ($field ne 'courserestricted') {
1.586     raeburn  6837:             $output.= &output_row($r,$field,$metadata_fields{$field});
1.560     damieng  6838:         }
1.255     banghart 6839:     }
1.351     banghart 6840:     my $buttons = (<<ENDButtons);
1.586     raeburn  6841:         <input type="submit" name="restrictmeta" value="$lt{'save'}" />
1.351     banghart 6842:         </form><br />
                   6843:         <form method="post" action="/adm/parmset?action=addmetadata" name="form1">
1.586     raeburn  6844:         <input type="submit" name="restrictmeta" value="$lt{'addm'}" />
1.351     banghart 6845:         </form>
                   6846:         <br />
                   6847:         <form method="post" action="/adm/parmset?action=ordermetadata" name="form2">
1.586     raeburn  6848:         <input type="submit" name="restrictmeta" value="$lt{'ordm'}" />
1.351     banghart 6849: ENDButtons
1.337     banghart 6850:     my $added_flag = 1;
1.335     banghart 6851:     foreach my $field (sort(keys(%$added_metadata_fields))) {
1.586     raeburn  6852:         $output.= &output_row($r,$field,$$added_metadata_fields{$field},$added_flag);
1.335     banghart 6853:     }
1.347     banghart 6854:     $output .= &Apache::loncommon::end_data_table();
1.446     bisitz   6855:     $r->print(<<ENDenv);
1.259     banghart 6856:         <form method="post" action="/adm/parmset?action=setrestrictmeta" name="form">
1.244     banghart 6857:         $output
1.351     banghart 6858:         $buttons
1.340     banghart 6859:         </form>
1.244     banghart 6860: ENDenv
1.507     www      6861:     &endSettingsScreen($r);
1.280     albertel 6862:     $r->print(&Apache::loncommon::end_page());
1.240     banghart 6863:     return 'ok';
                   6864: }
1.416     jms      6865: 
                   6866: 
1.563     damieng  6867: # Returns metadata fields that have been manually added.
                   6868: #
                   6869: # @param {string} $cid - course id
                   6870: # @returns {hash reference} - hash field name -> field title (not localized)
1.335     banghart 6871: sub get_added_meta_fieldnames {
1.357     raeburn  6872:     my ($cid) = @_;
1.335     banghart 6873:     my %fields;
                   6874:     foreach my $key(%env) {
1.357     raeburn  6875:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.335     banghart 6876:             my $field_name = $1;
                   6877:             my ($display_field_name) = $env{$key};
                   6878:             $fields{$field_name} = $display_field_name;
                   6879:         }
                   6880:     }
                   6881:     return \%fields;
                   6882: }
1.416     jms      6883: 
                   6884: 
1.563     damieng  6885: # Returns metadata fields that have been manually added and deleted.
                   6886: #
                   6887: # @param {string} $cid - course id
                   6888: # @returns {hash reference} - hash field name -> field title (not localized)
1.339     banghart 6889: sub get_deleted_meta_fieldnames {
1.357     raeburn  6890:     my ($cid) = @_;
1.339     banghart 6891:     my %fields;
                   6892:     foreach my $key(%env) {
1.357     raeburn  6893:         if ($key =~ m/\Q$cid\E\.metadata\.(.+)\.added$/) {
1.339     banghart 6894:             my $field_name = $1;
                   6895:             if ($env{'course.'.$env{'request.course.id'}.'.metadata.'.$field_name.'.options'} =~ m/deleted/) {
                   6896:                 my ($display_field_name) = $env{$key};
                   6897:                 $fields{$field_name} = $display_field_name;
                   6898:             }
                   6899:         }
                   6900:     }
                   6901:     return \%fields;
                   6902: }
1.560     damieng  6903: 
                   6904: 
                   6905: ##################################################
                   6906: # PARAMETER SETTINGS DEFAULT ACTIONS
                   6907: ##################################################
                   6908: 
                   6909: # UI to change parameter setting default actions
1.563     damieng  6910: #
                   6911: # @param {Apache2::RequestRec} $r - the Apache request
1.220     www      6912: sub defaultsetter {
1.280     albertel 6913:     my ($r) = @_;
                   6914: 
1.414     droeschl 6915:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=setdefaults',
1.473     amueller 6916:         text=>"Set Defaults"});
1.531     raeburn  6917:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   6918:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   6919:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.446     bisitz   6920:     my $start_page =
1.531     raeburn  6921:         &Apache::loncommon::start_page('Parameter Setting Default Actions');
1.298     albertel 6922:     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Defaults');
1.507     www      6923:     $r->print($start_page.$breadcrumbs);
1.531     raeburn  6924:     &startSettingsScreen($r,'parmset',$crstype);
1.507     www      6925:     $r->print('<form method="post" action="/adm/parmset?action=setdefaults" name="defaultform">');
1.280     albertel 6926: 
1.221     www      6927:     my @ids=();
                   6928:     my %typep=();
                   6929:     my %keyp=();
                   6930:     my %allparms=();
                   6931:     my %allparts=();
                   6932:     my %allmaps=();
                   6933:     my %mapp=();
                   6934:     my %symbp=();
                   6935:     my %maptitles=();
                   6936:     my %uris=();
                   6937:     my %keyorder=&standardkeyorder();
                   6938:     my %defkeytype=();
                   6939: 
1.446     bisitz   6940:     &extractResourceInformation(\@ids, \%typep,\%keyp, \%allparms, \%allparts, \%allmaps,
1.473     amueller 6941:                 \%mapp, \%symbp,\%maptitles,\%uris,
                   6942:                 \%keyorder,\%defkeytype);
1.224     www      6943:     if ($env{'form.storerules'}) {
1.560     damieng  6944:         my %newrules=();
                   6945:         my @delrules=();
                   6946:         my %triggers=();
                   6947:         foreach my $key (keys(%env)) {
1.225     albertel 6948:             if ($key=~/^form\.(\w+)\_action$/) {
1.560     damieng  6949:                 my $tempkey=$1;
                   6950:                 my $action=$env{$key};
1.226     www      6951:                 if ($action) {
1.560     damieng  6952:                     $newrules{$tempkey.'_action'}=$action;
                   6953:                     if ($action ne 'default') {
                   6954:                         my ($whichaction,$whichparm)=($action=~/^(.*\_)([^\_]+)$/);
                   6955:                         $triggers{$whichparm}.=$tempkey.':';
                   6956:                     }
                   6957:                     $newrules{$tempkey.'_type'}=$defkeytype{$tempkey};
                   6958:                     if (&isdateparm($defkeytype{$tempkey})) {
                   6959:                         $newrules{$tempkey.'_days'}=$env{'form.'.$tempkey.'_days'};
                   6960:                         $newrules{$tempkey.'_hours'}=$env{'form.'.$tempkey.'_hours'};
                   6961:                         $newrules{$tempkey.'_min'}=$env{'form.'.$tempkey.'_min'};
                   6962:                         $newrules{$tempkey.'_sec'}=$env{'form.'.$tempkey.'_sec'};
                   6963:                     } else {
                   6964:                         $newrules{$tempkey.'_value'}=$env{'form.'.$tempkey.'_value'};
                   6965:                         $newrules{$tempkey.'_triggervalue'}=$env{'form.'.$tempkey.'_triggervalue'};
                   6966:                     }
                   6967:                 } else {
                   6968:                     push(@delrules,$tempkey.'_action');
                   6969:                     push(@delrules,$tempkey.'_type');
                   6970:                     push(@delrules,$tempkey.'_hours');
                   6971:                     push(@delrules,$tempkey.'_min');
                   6972:                     push(@delrules,$tempkey.'_sec');
                   6973:                     push(@delrules,$tempkey.'_value');
                   6974:                 }
1.473     amueller 6975:             }
                   6976:         }
1.560     damieng  6977:         foreach my $key (keys(%allparms)) {
                   6978:             $newrules{$key.'_triggers'}=$triggers{$key};
1.473     amueller 6979:         }
1.560     damieng  6980:         &Apache::lonnet::put('parmdefactions',\%newrules,$cdom,$cnum);
                   6981:         &Apache::lonnet::del('parmdefactions',\@delrules,$cdom,$cnum);
                   6982:         &resetrulescache();
1.224     www      6983:     }
1.227     www      6984:     my %lt=&Apache::lonlocal::texthash('days' => 'Days',
1.473     amueller 6985:                        'hours' => 'Hours',
                   6986:                        'min' => 'Minutes',
                   6987:                        'sec' => 'Seconds',
                   6988:                        'yes' => 'Yes',
                   6989:                        'no' => 'No');
1.222     www      6990:     my @standardoptions=('','default');
                   6991:     my @standarddisplay=('',&mt('Default value when manually setting'));
                   6992:     my @dateoptions=('','default');
                   6993:     my @datedisplay=('',&mt('Default value when manually setting'));
                   6994:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  6995:         unless ($tempkey) { next; }
                   6996:         push @standardoptions,'when_setting_'.$tempkey;
                   6997:         push @standarddisplay,&mt('Automatically set when setting ').$tempkey;
                   6998:         if (&isdateparm($defkeytype{$tempkey})) {
                   6999:             push @dateoptions,'later_than_'.$tempkey;
                   7000:             push @datedisplay,&mt('Automatically set later than ').$tempkey;
                   7001:             push @dateoptions,'earlier_than_'.$tempkey;
                   7002:             push @datedisplay,&mt('Automatically set earlier than ').$tempkey;
                   7003:         }
1.222     www      7004:     }
1.563     damieng  7005:     $r->print(&mt('Manual setting rules apply to all interfaces.').'<br />'.
                   7006:         &mt('Automatic setting rules apply to table mode interfaces only.'));
1.318     albertel 7007:     $r->print("\n".&Apache::loncommon::start_data_table().
1.473     amueller 7008:           &Apache::loncommon::start_data_table_header_row().
                   7009:           "<th>".&mt('Rule for parameter').'</th><th>'.
                   7010:           &mt('Action').'</th><th>'.&mt('Value').'</th>'.
                   7011:           &Apache::loncommon::end_data_table_header_row());
1.221     www      7012:     foreach my $tempkey (&keysindisplayorder(\%allparms,\%keyorder)) {
1.560     damieng  7013:         unless ($tempkey) { next; }
                   7014:         $r->print("\n".&Apache::loncommon::start_data_table_row().
                   7015:             "<td>".$allparms{$tempkey}."\n<br />(".$tempkey.')</td><td>');
                   7016:         my $action=&rulescache($tempkey.'_action');
                   7017:         $r->print('<select name="'.$tempkey.'_action">');
                   7018:         if (&isdateparm($defkeytype{$tempkey})) {
                   7019:             for (my $i=0;$i<=$#dateoptions;$i++) {
                   7020:             if ($dateoptions[$i]=~/\_$tempkey$/) { next; }
                   7021:             $r->print("\n<option value='$dateoptions[$i]'".
                   7022:                 ($dateoptions[$i] eq $action?' selected="selected"':'').
                   7023:                 ">$datedisplay[$i]</option>");
                   7024:             }
                   7025:         } else {
                   7026:             for (my $i=0;$i<=$#standardoptions;$i++) {
                   7027:             if ($standardoptions[$i]=~/\_$tempkey$/) { next; }
                   7028:             $r->print("\n<option value='$standardoptions[$i]'".
                   7029:                 ($standardoptions[$i] eq $action?' selected="selected"':'').
                   7030:                 ">$standarddisplay[$i]</option>");
                   7031:             }
1.473     amueller 7032:         }
1.560     damieng  7033:         $r->print('</select>');
                   7034:         unless (&isdateparm($defkeytype{$tempkey})) {
                   7035:             $r->print("\n<br />".&mt('Triggering value(s) of other parameter (optional, comma-separated):').
                   7036:                 '<input type="text" size="20" name="'.$tempkey.'_triggervalue" value="'.&rulescache($tempkey.'_triggervalue').'" />');
1.473     amueller 7037:         }
1.560     damieng  7038:         $r->print("\n</td><td>\n");
1.222     www      7039: 
1.221     www      7040:         if (&isdateparm($defkeytype{$tempkey})) {
1.560     damieng  7041:             my $days=&rulescache($tempkey.'_days');
                   7042:             my $hours=&rulescache($tempkey.'_hours');
                   7043:             my $min=&rulescache($tempkey.'_min');
                   7044:             my $sec=&rulescache($tempkey.'_sec');
                   7045:             $r->print(<<ENDINPUTDATE);
                   7046:     <input name="$tempkey\_days" type="text" size="4" value="$days" />$lt{'days'}<br />
                   7047:     <input name="$tempkey\_hours" type="text" size="4" value="$hours" />$lt{'hours'}<br />
                   7048:     <input name="$tempkey\_min" type="text" size="4" value="$min" />$lt{'min'}<br />
                   7049:     <input name="$tempkey\_sec" type="text" size="4" value="$sec" />$lt{'sec'}
1.564     raeburn  7050: ENDINPUTDATE
1.560     damieng  7051:         } elsif ($defkeytype{$tempkey} eq 'string_yesno') {
                   7052:                 my $yeschecked='';
                   7053:                 my $nochecked='';
                   7054:                 if (&rulescache($tempkey.'_value') eq 'yes') { $yeschecked=' checked="checked"'; }
                   7055:                 if (&rulescache($tempkey.'_value') eq 'no') { $nochecked=' checked="checked"'; }
                   7056: 
                   7057:             $r->print(<<ENDYESNO);
                   7058:     <label><input type="radio" name="$tempkey\_value" value="yes"$yeschecked /> $lt{'yes'}</label><br />
                   7059:     <label><input type="radio" name="$tempkey\_value" value="no"$nochecked /> $lt{'no'}</label>
1.564     raeburn  7060: ENDYESNO
1.221     www      7061:         } else {
1.560     damieng  7062:             $r->print('<input type="text" size="20" name="'.$tempkey.'_value" value="'.&rulescache($tempkey.'_value').'" />');
                   7063:         }
1.318     albertel 7064:         $r->print('</td>'.&Apache::loncommon::end_data_table_row());
1.221     www      7065:     }
1.318     albertel 7066:     $r->print(&Apache::loncommon::end_data_table().
1.473     amueller 7067:           "\n".'<input type="submit" name="storerules" value="'.
1.507     www      7068:           &mt('Save').'" /></form>'."\n");
                   7069:     &endSettingsScreen($r);
                   7070:     $r->print(&Apache::loncommon::end_page());
1.220     www      7071:     return;
                   7072: }
1.193     albertel 7073: 
1.560     damieng  7074: ##################################################
                   7075: # PARAMETER CHANGES LOG
                   7076: ##################################################
                   7077: 
1.563     damieng  7078: # Returns some info for a parameter log entry.
                   7079: # Returned entries:
                   7080: # $realm - HTML title for the parameter level and resource
                   7081: # $section - parameter section
                   7082: # $name - parameter name
                   7083: # $part - parameter part
                   7084: # $what - $part.'.'.$name
                   7085: # $middle - resource symb ?
                   7086: # $uname - user name (same as given)
                   7087: # $udom - user domain (same as given)
                   7088: # $issection - section or group name
                   7089: # $realmdescription - title for the parameter level and resource (without using HTML)
                   7090: #
                   7091: # @param {string} $key - parameter log key
                   7092: # @param {string} $uname - user name
                   7093: # @param {string} $udom - user domain
                   7094: # @param {boolean} $typeflag - .type log entry
                   7095: # @returns {Array}
1.290     www      7096: sub components {
1.581     raeburn  7097:     my ($key,$uname,$udom,$typeflag)=@_;
1.330     albertel 7098: 
                   7099:     if ($typeflag) {
1.560     damieng  7100:         $key=~s/\.type$//;
1.290     www      7101:     }
1.330     albertel 7102: 
                   7103:     my ($middle,$part,$name)=
1.572     damieng  7104:         ($key=~/^$env{'request.course.id'}\.(?:(.+)\.)*([\w\s\-]+)\.(\w+)$/);
1.291     www      7105:     my $issection;
1.330     albertel 7106: 
1.290     www      7107:     my $section=&mt('All Students');
                   7108:     if ($middle=~/^\[(.*)\]/) {
1.560     damieng  7109:         $issection=$1;
                   7110:         $section=&mt('Group/Section').': '.$issection;
                   7111:         $middle=~s/^\[(.*)\]//;
1.290     www      7112:     }
                   7113:     $middle=~s/\.+$//;
                   7114:     $middle=~s/^\.+//;
1.291     www      7115:     if ($uname) {
1.560     damieng  7116:         $section=&mt('User').": ".&Apache::loncommon::plainname($uname,$udom);
                   7117:         $issection='';
1.291     www      7118:     }
1.316     albertel 7119:     my $realm='<span class="LC_parm_scope_all">'.&mt('All Resources').'</span>';
1.446     bisitz   7120:     my $realmdescription=&mt('all resources');
1.556     raeburn  7121:     if ($middle=~/^(.+)\_\_\_\((all|rec)\)$/) {
                   7122:         my $mapurl = $1;
                   7123:         my $maplevel = $2;
                   7124:         my $leveltitle = &mt('Folder/Map');
                   7125:         if ($maplevel eq 'rec') {
                   7126:             $leveltitle = &mt('Recursive');
                   7127:         }
1.560     damieng  7128:         $realm='<span class="LC_parm_scope_folder">'.$leveltitle.
                   7129:             ': '.&Apache::lonnet::gettitle($mapurl).' <span class="LC_parm_folder"><br />('.
                   7130:             $mapurl.')</span></span>';
                   7131:         $realmdescription=&mt('folder').' '.&Apache::lonnet::gettitle($mapurl);
                   7132:     } elsif ($middle) {
                   7133:         my ($map,$id,$url)=&Apache::lonnet::decode_symb($middle);
                   7134:         $realm='<span class="LC_parm_scope_resource">'.&mt('Resource').
                   7135:             ': '.&Apache::lonnet::gettitle($middle).' <br /><span class="LC_parm_symb">('.$url.
                   7136:             ' in '.$map.' id: '.$id.')</span></span>';
                   7137:         $realmdescription=&mt('resource').' '.&Apache::lonnet::gettitle($middle);
1.290     www      7138:     }
1.291     www      7139:     my $what=$part.'.'.$name;
1.330     albertel 7140:     return ($realm,$section,$name,$part,
1.473     amueller 7141:         $what,$middle,$uname,$udom,$issection,$realmdescription);
1.290     www      7142: }
1.293     www      7143: 
1.563     damieng  7144: my %standard_parms; # hash parameter name -> parameter title (not localized)
                   7145: my %standard_parms_types; # hash parameter name -> parameter type
1.416     jms      7146: 
1.563     damieng  7147: # Reads parameter info from packages.tab into %standard_parms.
1.328     albertel 7148: sub load_parameter_names {
1.583     raeburn  7149:     open(my $config,"<","$Apache::lonnet::perlvar{'lonTabDir'}/packages.tab");
1.328     albertel 7150:     while (my $configline=<$config>) {
1.560     damieng  7151:         if ($configline !~ /\S/ || $configline=~/^\#/) { next; }
                   7152:         chomp($configline);
                   7153:         my ($short,$plain)=split(/:/,$configline);
                   7154:         my (undef,$name,$type)=split(/\&/,$short,3);
                   7155:         if ($type eq 'display') {
                   7156:             $standard_parms{$name} = $plain;
1.469     raeburn  7157:         } elsif ($type eq 'type') {
1.560     damieng  7158:                 $standard_parms_types{$name} = $plain;
1.469     raeburn  7159:         }
1.328     albertel 7160:     }
                   7161:     close($config);
                   7162:     $standard_parms{'int_pos'}      = 'Positive Integer';
                   7163:     $standard_parms{'int_zero_pos'} = 'Positive Integer or Zero';
1.575     raeburn  7164:     $standard_parms{'scoreformat'}  = 'Format for display of score';
1.328     albertel 7165: }
                   7166: 
1.563     damieng  7167: # Returns a parameter title for standard parameters, the name for others.
                   7168: #
                   7169: # @param {string} $name - parameter name
                   7170: # @returns {string}
1.292     www      7171: sub standard_parameter_names {
                   7172:     my ($name)=@_;
1.328     albertel 7173:     if (!%standard_parms) {
1.560     damieng  7174:         &load_parameter_names();
1.328     albertel 7175:     }
1.292     www      7176:     if ($standard_parms{$name}) {
1.560     damieng  7177:         return $standard_parms{$name};
1.446     bisitz   7178:     } else {
1.560     damieng  7179:         return $name;
1.292     www      7180:     }
                   7181: }
1.290     www      7182: 
1.563     damieng  7183: # Returns a parameter type for standard parameters, undef for others.
                   7184: #
                   7185: # @param {string} $name - parameter name
                   7186: # @returns {string}
1.469     raeburn  7187: sub standard_parameter_types {
                   7188:     my ($name)=@_;
                   7189:     if (!%standard_parms_types) {
                   7190:         &load_parameter_names();
                   7191:     }
                   7192:     if ($standard_parms_types{$name}) {
                   7193:         return $standard_parms_types{$name};
                   7194:     }
                   7195:     return;
                   7196: }
1.309     www      7197: 
1.563     damieng  7198: # Returns a parameter level title (not localized) from the parameter level name.
                   7199: #
                   7200: # @param {string} $name - parameter level name (recognized: resourcelevel|maplevel|maplevelrecurse|courselevel)
                   7201: # @returns {string}
1.557     raeburn  7202: sub standard_parameter_levels {
                   7203:     my ($name)=@_;
                   7204:     my %levels = (
                   7205:                     'resourcelevel'   => 'a single resource',
                   7206:                     'maplevel'        => 'the enclosing map/folder', 
                   7207:                     'maplevelrecurse' => 'the enclosing map/folder (recursive into sub-folders)',
                   7208:                     'courselevel'     => 'the general (course) level',
                   7209:                  );
                   7210:     if ($levels{$name}) {
                   7211:         return $levels{$name};
                   7212:     }
                   7213:     return;
                   7214: }
                   7215: 
1.560     damieng  7216: # Display log for parameter changes, blog postings, user notification changes.
1.563     damieng  7217: #
                   7218: # @param {Apache2::RequestRec} $r - the Apache request
1.285     albertel 7219: sub parm_change_log {
1.568     raeburn  7220:     my ($r,$parm_permission)=@_;
1.531     raeburn  7221:     my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7222:     my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.569     raeburn  7223:     my $crstype = $env{'course.'.$env{'request.course.id'}.'.type'};
1.414     droeschl 7224:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/parmset?action=settable',
1.473     amueller 7225:     text=>"Parameter Change Log"});
1.522     raeburn  7226:     my $js = '<script type="text/javascript">'."\n".
                   7227:              '// <![CDATA['."\n".
                   7228:              &Apache::loncommon::display_filter_js('parmslog')."\n".
                   7229:              '// ]]>'."\n".
                   7230:              '</script>'."\n";
                   7231:     $r->print(&Apache::loncommon::start_page('Parameter Change Log',$js));
1.327     albertel 7232:     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Parameter Change Log'));
1.531     raeburn  7233:     &startSettingsScreen($r,'parmset',$crstype);
                   7234:     my %parmlog=&Apache::lonnet::dump('nohist_parameterlog',$cdom,$cnum);
1.311     albertel 7235: 
1.301     www      7236:     if ((keys(%parmlog))[0]=~/^error\:/) { undef(%parmlog); }
1.311     albertel 7237: 
1.522     raeburn  7238:     $r->print('<div class="LC_left_float">'.
                   7239:               '<fieldset><legend>'.&mt('Display of Changes').'</legend>'.
                   7240:               '<form action="/adm/parmset?action=parameterchangelog"
1.327     albertel 7241:                      method="post" name="parameterlog">');
1.446     bisitz   7242: 
1.311     albertel 7243:     my %saveable_parameters = ('show' => 'scalar',);
                   7244:     &Apache::loncommon::store_course_settings('parameter_log',
                   7245:                                               \%saveable_parameters);
                   7246:     &Apache::loncommon::restore_course_settings('parameter_log',
                   7247:                                                 \%saveable_parameters);
1.522     raeburn  7248:     $r->print(&Apache::loncommon::display_filter('parmslog').'&nbsp;'."\n".
                   7249:               '<input type="submit" value="'.&mt('Display').'" />'.
                   7250:               '</form></fieldset></div><br clear="all" />');
1.301     www      7251: 
1.568     raeburn  7252:     my $readonly = 1;
                   7253:     if ($parm_permission->{'edit'}) {
                   7254:         undef($readonly);
                   7255:     }
1.531     raeburn  7256:     my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
1.301     www      7257:     $r->print(&Apache::loncommon::start_data_table().&Apache::loncommon::start_data_table_header_row().
1.473     amueller 7258:           '<th>'.&mt('Time').'</th><th>'.&mt('User').'</th><th>'.&mt('Extent').'</th><th>'.&mt('Users').'</th><th>'.
1.568     raeburn  7259:           &mt('Parameter').'</th><th>'.&mt('Part').'</th><th>'.&mt('New Value').'</th>');
                   7260:     unless ($readonly) {
                   7261:         $r->print('<th>'.&mt('Announce').'</th>');
                   7262:     }
                   7263:     $r->print(&Apache::loncommon::end_data_table_header_row());
1.309     www      7264:     my $shown=0;
1.349     www      7265:     my $folder='';
                   7266:     if ($env{'form.displayfilter'} eq 'currentfolder') {
1.560     damieng  7267:         my $last='';
                   7268:         if (tie(my %hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                   7269:                 &GDBM_READER(),0640)) {
                   7270:             $last=$hash{'last_known'};
                   7271:             untie(%hash);
                   7272:         }
                   7273:         if ($last) { ($folder) = &Apache::lonnet::decode_symb($last); }
                   7274:     }
1.595     raeburn  7275:     my $numgroups = 0;
                   7276:     my @groups;
                   7277:     if ($env{'request.course.groups'} ne '') {
                   7278:         @groups = split(/:/,$env{'request.course.groups'});
                   7279:         $numgroups = scalar(@groups);
                   7280:     }
1.560     damieng  7281:     foreach my $id (sort {
                   7282:                 if ($parmlog{$b}{'exe_time'} ne $parmlog{$a}{'exe_time'}) {
                   7283:                     return $parmlog{$b}{'exe_time'} <=>$parmlog{$a}{'exe_time'}
                   7284:                 }
                   7285:                 my $aid = (split('00000',$a))[-1];
                   7286:                 my $bid = (split('00000',$b))[-1];
                   7287:                 return $bid<=>$aid;
1.473     amueller 7288:             } (keys(%parmlog))) {
1.294     www      7289:         my @changes=keys(%{$parmlog{$id}{'logentry'}});
1.560     damieng  7290:         my $count = 0;
                   7291:         my $time =
                   7292:             &Apache::lonlocal::locallocaltime($parmlog{$id}{'exe_time'});
                   7293:         my $plainname =
                   7294:             &Apache::loncommon::plainname($parmlog{$id}{'exe_uname'},
                   7295:                         $parmlog{$id}{'exe_udom'});
                   7296:         my $about_me_link =
                   7297:             &Apache::loncommon::aboutmewrapper($plainname,
                   7298:                             $parmlog{$id}{'exe_uname'},
                   7299:                             $parmlog{$id}{'exe_udom'});
                   7300:         my $send_msg_link='';
1.568     raeburn  7301:         if ((!$readonly) && 
                   7302:             (($parmlog{$id}{'exe_uname'} ne $env{'user.name'})
1.560     damieng  7303:             || ($parmlog{$id}{'exe_udom'} ne $env{'user.domain'}))) {
                   7304:             $send_msg_link ='<br />'.
                   7305:             &Apache::loncommon::messagewrapper(&mt('Send message'),
                   7306:                             $parmlog{$id}{'exe_uname'},
                   7307:                             $parmlog{$id}{'exe_udom'});
                   7308:         }
                   7309:         my $row_start=&Apache::loncommon::start_data_table_row();
                   7310:         my $makenewrow=0;
                   7311:         my %istype=();
                   7312:         my $output;
                   7313:         foreach my $changed (reverse(sort(@changes))) {
                   7314:                 my $value=$parmlog{$id}{'logentry'}{$changed};
                   7315:             my $typeflag = ($changed =~/\.type$/ &&
                   7316:                     !exists($parmlog{$id}{'logentry'}{$changed.'.type'}));
1.330     albertel 7317:             my ($realm,$section,$parmname,$part,$what,$middle,$uname,$udom,$issection,$realmdescription)=
1.581     raeburn  7318:                 &components($changed,$parmlog{$id}{'uname'},$parmlog{$id}{'udom'},$typeflag);
1.560     damieng  7319:             if ($env{'request.course.sec'} ne '') {
1.595     raeburn  7320:                 next if (($issection ne '') && (!(($issection eq $env{'request.course.sec'}) ||
                   7321:                                                   ($numgroups && (grep(/^\Q$issection\E$/,@groups))))));
1.560     damieng  7322:                 if ($uname ne '') {
                   7323:                     my $stusection = &Apache::lonnet::getsection($uname,$udom,$env{'request.course.id'});
                   7324:                     next if (($stusection ne '-1') && ($stusection ne $env{'request.course.sec'})); 
                   7325:                 }
                   7326:             }
                   7327:             if ($env{'form.displayfilter'} eq 'currentfolder') {
                   7328:                 if ($folder) {
                   7329:                     if ($middle!~/^\Q$folder\E/) { next; }
                   7330:                 }
                   7331:             }
                   7332:             if ($typeflag) {
                   7333:                 $istype{$parmname}=$value;
                   7334:                 if (!$env{'form.includetypes'}) { next; }
                   7335:             }
                   7336:             $count++;
                   7337:             if ($makenewrow) {
                   7338:                 $output .= $row_start;
                   7339:             } else {
                   7340:                 $makenewrow=1;
                   7341:             }
1.470     raeburn  7342:             my $parmitem = &standard_parameter_names($parmname);
1.560     damieng  7343:             $output .='<td>'.$realm.'</td><td>'.$section.'</td><td>'.
                   7344:                 &mt($parmitem).'</td><td>'.
                   7345:                 ($part?&mt('Part: [_1]',$part):&mt('All Parts')).'</td><td>';
                   7346:             my $stillactive=0;
                   7347:             if ($parmlog{$id}{'delflag'}) {
                   7348:                 $output .= &mt('Deleted');
                   7349:             } else {
                   7350:                 if ($typeflag) {
1.470     raeburn  7351:                     my $parmitem = &standard_parameter_names($value); 
                   7352:                     $parmitem = &mt($parmitem);
1.560     damieng  7353:                     $output .= &mt('Type: [_1]',$parmitem);
                   7354:                 } else {
1.584     raeburn  7355:                     my $toolsymb;
                   7356:                     if ($middle =~ /ext\.tool$/) {
                   7357:                         $toolsymb = $middle;
                   7358:                     }
1.560     damieng  7359:                     my ($level,@all)=&parmval_by_symb($what,$middle,
1.584     raeburn  7360:                         &Apache::lonnet::metadata($middle,$what,$toolsymb),
1.560     damieng  7361:                         $uname,$udom,$issection,$issection,$courseopt);
1.469     raeburn  7362:                     my $showvalue = $value;
                   7363:                     if ($istype{$parmname} eq '') {
                   7364:                         my $type = &standard_parameter_types($parmname);
                   7365:                         if ($type ne '') {
                   7366:                             if (&isdateparm($type)) {
                   7367:                                 $showvalue =
                   7368:                                     &Apache::lonlocal::locallocaltime($value);
                   7369:                             }
                   7370:                         }
                   7371:                     } else {
1.560     damieng  7372:                         if (&isdateparm($istype{$parmname})) {
                   7373:                             $showvalue = &Apache::lonlocal::locallocaltime($value);
                   7374:                         }
1.469     raeburn  7375:                     }
                   7376:                     $output .= $showvalue;
1.560     damieng  7377:                     if ($value ne $all[$level]) {
                   7378:                         $output .= '<br /><span class="LC_warning">'.&mt('Not active anymore').'</span>';
                   7379:                     } else {
                   7380:                         $stillactive=1;
                   7381:                     }
                   7382:                 }
1.473     amueller 7383:             }
1.568     raeburn  7384:             $output .= '</td>';
                   7385: 
                   7386:             unless ($readonly) { 
                   7387:                 $output .= '<td>';
                   7388:                 if ($stillactive) {
                   7389:                     my $parmitem = &standard_parameter_names($parmname);
                   7390:                     $parmitem = &mt($parmitem);
                   7391:                     my $title=&mt('Changed [_1]',$parmitem);
                   7392:                     my $description=&mt('Changed [_1] for [_2] to [_3]',
                   7393:                         $parmitem,$realmdescription,
                   7394:                         (&isdateparm($istype{$parmname})?&Apache::lonlocal::locallocaltime($value):$value));
                   7395:                     if (($uname) && ($udom)) {
                   7396:                         $output .=
                   7397:                         &Apache::loncommon::messagewrapper('Notify User',
                   7398:                                                            $uname,$udom,$title,
                   7399:                                                            $description);
                   7400:                     } else {
                   7401:                         $output .=
                   7402:                             &Apache::lonrss::course_blog_link($id,$title,
                   7403:                                                               $description);
                   7404:                     }
1.560     damieng  7405:                 }
1.568     raeburn  7406:                 $output .= '</td>';
1.560     damieng  7407:             }
1.568     raeburn  7408:             $output .= &Apache::loncommon::end_data_table_row();
1.473     amueller 7409:         }
1.560     damieng  7410:         if ($env{'form.displayfilter'} eq 'containing') {
                   7411:             my $wholeentry=$about_me_link.':'.
                   7412:             $parmlog{$id}{'exe_uname'}.':'.$parmlog{$id}{'exe_udom'}.':'.
                   7413:             $output;
                   7414:             if ($wholeentry!~/\Q$env{'form.containingphrase'}\E/i) { next; }
1.473     amueller 7415:         }
1.349     www      7416:         if ($count) {
1.560     damieng  7417:             $r->print($row_start.'<td rowspan="'.$count.'">'.$time.'</td>
                   7418:                         <td rowspan="'.$count.'">'.$about_me_link.
                   7419:             '<br /><tt>'.$parmlog{$id}{'exe_uname'}.
                   7420:                         ':'.$parmlog{$id}{'exe_udom'}.'</tt>'.
                   7421:             $send_msg_link.'</td>'.$output);
                   7422:             $shown++;
                   7423:         }
                   7424:         if (!($env{'form.show'} eq &mt('all')
                   7425:             || $shown<=$env{'form.show'})) { last; }
1.286     www      7426:     }
1.301     www      7427:     $r->print(&Apache::loncommon::end_data_table());
1.507     www      7428:     &endSettingsScreen($r);
1.284     www      7429:     $r->print(&Apache::loncommon::end_page());
                   7430: }
                   7431: 
1.560     damieng  7432: ##################################################
                   7433: # MISC !
                   7434: ##################################################
                   7435: 
1.563     damieng  7436: # Stores slot information.
1.560     damieng  7437: # Used by table UI
1.563     damieng  7438: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7439: #
                   7440: # @param {string} $slot_name - slot name
                   7441: # @param {string} $cdom - course domain
                   7442: # @param {string} $cnum - course number
                   7443: # @param {string} $symb - resource symb
                   7444: # @param {string} $uname - user name
                   7445: # @param {string} $udom - user domain
                   7446: # @returns {string} - 'ok' or error name
1.437     raeburn  7447: sub update_slots {
                   7448:     my ($slot_name,$cdom,$cnum,$symb,$uname,$udom) = @_;
                   7449:     my %slot=&Apache::lonnet::get_slot($slot_name);
                   7450:     if (!keys(%slot)) {
                   7451:         return 'error: slot does not exist';
                   7452:     }
                   7453:     my $max=$slot{'maxspace'};
                   7454:     if (!defined($max)) { $max=99999; }
                   7455: 
                   7456:     my %consumed=&Apache::lonnet::dump('slot_reservations',$cdom,$cnum,
                   7457:                                        "^$slot_name\0");
                   7458:     my ($tmp)=%consumed;
                   7459:     if ($tmp=~/^error: 2 / ) {
                   7460:         return 'error: unable to determine current slot status';
                   7461:     }
                   7462:     my $last=0;
                   7463:     foreach my $key (keys(%consumed)) {
                   7464:         my $num=(split('\0',$key))[1];
                   7465:         if ($num > $last) { $last=$num; }
                   7466:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7467:             return 'ok';
                   7468:         }
                   7469:     }
                   7470: 
                   7471:     if (scalar(keys(%consumed)) >= $max) {
                   7472:         return 'error: no space left in slot';
                   7473:     }
                   7474:     my $wanted=$last+1;
                   7475: 
                   7476:     my %reservation=('name'      => $uname.':'.$udom,
                   7477:                      'timestamp' => time,
                   7478:                      'symb'      => $symb);
                   7479: 
                   7480:     my $success=&Apache::lonnet::newput('slot_reservations',
                   7481:                                         {"$slot_name\0$wanted" =>
                   7482:                                              \%reservation},
                   7483:                                         $cdom, $cnum);
1.438     raeburn  7484:     if ($success eq 'ok') {
                   7485:         my %storehash = (
                   7486:                           symb    => $symb,
                   7487:                           slot    => $slot_name,
                   7488:                           action  => 'reserve',
                   7489:                           context => 'parameter',
                   7490:                         );
1.526     raeburn  7491:         &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7492:                                    '',$uname,$udom,$cnum,$cdom);
1.438     raeburn  7493: 
1.526     raeburn  7494:         &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7495:                                    '',$uname,$udom,$uname,$udom);
1.438     raeburn  7496:     }
1.437     raeburn  7497:     return $success;
                   7498: }
                   7499: 
1.563     damieng  7500: # Deletes a slot reservation.
1.560     damieng  7501: # Used by table UI
1.563     damieng  7502: # FIXME: I don't understand how this can work when the symb is not defined (if only a map was selected)
                   7503: #
                   7504: # @param {string} $slot_name - slot name
                   7505: # @param {string} $cdom - course domain
                   7506: # @param {string} $cnum - course number
                   7507: # @param {string} $uname - user name
                   7508: # @param {string} $udom - user domain
                   7509: # @param {string} $symb - resource symb
                   7510: # @returns {string} - 'ok' or error name
1.437     raeburn  7511: sub delete_slots {
                   7512:     my ($slot_name,$cdom,$cnum,$uname,$udom,$symb) = @_;
                   7513:     my $delresult;
                   7514:     my %consumed = &Apache::lonnet::dump('slot_reservations',$cdom,
                   7515:                                          $cnum, "^$slot_name\0");
                   7516:     if (&Apache::lonnet::error(%consumed)) {
                   7517:         return 'error: unable to determine current slot status';
                   7518:     }
                   7519:     my ($tmp)=%consumed;
                   7520:     if ($tmp=~/^error: 2 /) {
                   7521:         return 'error: unable to determine current slot status';
                   7522:     }
                   7523:     foreach my $key (keys(%consumed)) {
                   7524:         if ($consumed{$key}->{'name'} eq $uname.':'.$udom) {
                   7525:             my $num=(split('\0',$key))[1];
                   7526:             my $entry = $slot_name.'\0'.$num;
                   7527:             $delresult = &Apache::lonnet::del('slot_reservations',[$entry],
                   7528:                                               $cdom,$cnum);
                   7529:             if ($delresult eq 'ok') {
                   7530:                 my %storehash = (
                   7531:                                   symb    => $symb,
                   7532:                                   slot    => $slot_name,
                   7533:                                   action  => 'release',
                   7534:                                   context => 'parameter',
                   7535:                                 );
1.526     raeburn  7536:                 &Apache::lonnet::write_log('course','slotreservationslog',\%storehash,
1.524     raeburn  7537:                                            1,$uname,$udom,$cnum,$cdom);
1.526     raeburn  7538:                 &Apache::lonnet::write_log('course',$cdom.'_'.$cnum.'_slotlog',\%storehash,
1.524     raeburn  7539:                                            1,$uname,$udom,$uname,$udom);
1.437     raeburn  7540:             }
                   7541:         }
                   7542:     }
                   7543:     return $delresult;
                   7544: }
                   7545: 
1.563     damieng  7546: # Returns true if there is a current course.
1.560     damieng  7547: # Used by handler
1.563     damieng  7548: #
                   7549: # @returns {boolean}
1.355     albertel 7550: sub check_for_course_info {
                   7551:     my $navmap = Apache::lonnavmaps::navmap->new();
                   7552:     return 1 if ($navmap);
                   7553:     return 0;
                   7554: }
                   7555: 
1.563     damieng  7556: # Returns the current course host and host LON-CAPA version.
                   7557: #
                   7558: # @returns {Array} - (course hostname, major version number, minor version number)
1.514     raeburn  7559: sub parameter_release_vars { 
1.504     raeburn  7560:    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   7561:    my $chome = $env{'course.'.$env{'request.course.id'}.'.home'};
                   7562:    my $chostname = &Apache::lonnet::hostname($chome);
                   7563:    my ($cmajor,$cminor) = 
                   7564:        split(/\./,&Apache::lonnet::get_server_loncaparev($cdom,$chome));
                   7565:    return ($chostname,$cmajor,$cminor);
                   7566: }
                   7567: 
1.563     damieng  7568: # Checks if the course host version can handle a parameter required version,
                   7569: # and if it does, stores the release needed for the course.
                   7570: #
                   7571: # @param {string} $name - parameter name
                   7572: # @param {string} $value - parameter value
                   7573: # @param {string} $valmatch - name of the test used for checking the value
                   7574: # @param {string} $namematch - name of the test used for checking the name
                   7575: # @param {string} $needsrelease - version needed by the parameter, major.minor
                   7576: # @param {integer} $cmajor - course major version number
                   7577: # @param {integer} $cminor - course minor version number
                   7578: # @returns {boolean} - true if a newer version is needed
1.514     raeburn  7579: sub parameter_releasecheck {
1.557     raeburn  7580:     my ($name,$value,$valmatch,$namematch,$needsrelease,$cmajor,$cminor) = @_;
1.504     raeburn  7581:     my $needsnewer;
                   7582:     my ($needsmajor,$needsminor) = split(/\./,$needsrelease);
                   7583:     if (($cmajor < $needsmajor) || 
                   7584:         ($cmajor == $needsmajor && $cminor < $needsminor)) {
                   7585:         $needsnewer = 1;
1.557     raeburn  7586:     } elsif ($name) {
                   7587:         if ($valmatch) {
                   7588:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.'::'.$valmatch.':'});
                   7589:         } elsif ($value) { 
                   7590:             &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter:'.$name.':'.$value.'::'});
                   7591:         }
                   7592:     } elsif ($namematch) {
                   7593:         &Apache::lonnet::update_released_required($Apache::lonnet::needsrelease{'parameter::::'.$namematch});
1.504     raeburn  7594:     }
                   7595:     return $needsnewer;
                   7596: }
                   7597: 
1.568     raeburn  7598: sub get_permission {
                   7599:     my %permission;
                   7600:     my $allowed = 0;
                   7601:     return (\%permission,$allowed) unless ($env{'request.course.id'});
                   7602:     if ((&Apache::lonnet::allowed('opa',$env{'request.course.id'})) ||
                   7603:         (&Apache::lonnet::allowed('opa',$env{'request.course.id'}.'/'.
                   7604:                   $env{'request.course.sec'}))) {
                   7605:         %permission= (
                   7606:                        'edit'               => 1,
                   7607:                        'set'                => 1,
                   7608:                        'setoverview'        => 1,
                   7609:                        'addmetadata'        => 1,
                   7610:                        'ordermetadata'      => 1,
                   7611:                        'setrestrictmeta'    => 1,
                   7612:                        'newoverview'        => 1,
                   7613:                        'setdefaults'        => 1,
                   7614:                        'settable'           => 1,
                   7615:                        'parameterchangelog' => 1,
                   7616:                        'cleanparameters'    => 1,
                   7617:                        'dateshift1'         => 1,
                   7618:                        'dateshift2'         => 1,
                   7619:                        'helper'             => 1,
                   7620:          );
                   7621:     } elsif ((&Apache::lonnet::allowed('vpa',$env{'request.course.id'})) ||
                   7622:              (&Apache::lonnet::allowed('vpa',$env{'request.course.id'}.'/'.
                   7623:                   $env{'request.course.sec'}))) {
                   7624:         %permission = (
                   7625:                        'set'                => 1,
                   7626:                        'settable'           => 1,
                   7627:                        'newoverview'        => 1,
                   7628:                        'setoverview'        => 1,
                   7629:                        'parameterchangelog' => 1,
                   7630:                       );
                   7631:     }
                   7632:     foreach my $perm (values(%permission)) {
                   7633:         if ($perm) { $allowed=1; last; }
                   7634:     }
                   7635:     return (\%permission,$allowed);
                   7636: }
                   7637: 
1.560     damieng  7638: ##################################################
                   7639: # HANDLER
                   7640: ##################################################
                   7641: 
                   7642: # Main handler for lonparmset.
                   7643: # Sub called based on request parameters action and command:
                   7644: # no command or action: print_main_menu
                   7645: # command 'set': assessparms (direct access to table mode for a resource)
                   7646: #                (this can also be accessed simply with the symb parameter)
                   7647: # action 'setoverview': overview (display all existing parameter settings)
                   7648: # action 'addmetadata': addmetafield (called to add a portfolio metadata field)
                   7649: # action 'ordermetadata': order_meta_fields (called to order portfolio metadata fields)
                   7650: # action 'setrestrictmeta': setrestrictmeta (display or save portfolio metadata)
                   7651: # action 'newoverview': newoverview (overview mode)
                   7652: # action 'setdefaults': defaultsetter (UI to change parameter setting default actions)
                   7653: # action 'settable': assessparms (table mode)
                   7654: # action 'parameterchangelog': parm_change_log (display log for parameter changes,
                   7655: #                              blog postings, user notification changes)
                   7656: # action 'cleanparameters': clean_parameters (unused)
                   7657: # action 'dateshift1': date_shift_one (overview mode, shift all dates)
                   7658: # action 'dateshift2': date_shift_two (overview mode, shift all dates)
1.30      www      7659: sub handler {
1.43      albertel 7660:     my $r=shift;
1.30      www      7661: 
1.376     albertel 7662:     &reset_caches();
                   7663: 
1.414     droeschl 7664:     &Apache::loncommon::content_type($r,'text/html');
                   7665:     $r->send_http_header;
                   7666:     return OK if $r->header_only;
                   7667: 
1.193     albertel 7668:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.473     amueller 7669:                         ['action','state',
1.205     www      7670:                                              'pres_marker',
                   7671:                                              'pres_value',
1.206     www      7672:                                              'pres_type',
1.506     www      7673:                                              'filter','part',
1.390     www      7674:                                              'udom','uname','symb','serial','timebase']);
1.131     www      7675: 
1.83      bowersj2 7676: 
1.193     albertel 7677:     &Apache::lonhtmlcommon::clear_breadcrumbs();
1.194     albertel 7678:     &Apache::lonhtmlcommon::add_breadcrumb({href=>"/adm/parmset",
1.507     www      7679:                         text=>"Content and Problem Settings",
1.473     amueller 7680:                         faq=>10,
                   7681:                         bug=>'Instructor Interface',
1.442     droeschl 7682:                                             help =>
                   7683:                                             'Parameter_Manager,Course_Environment,Parameter_Helper,Parameter_Overview,Table_Mode'});
1.203     www      7684: 
1.30      www      7685: # ----------------------------------------------------- Needs to be in a course
1.568     raeburn  7686:     my ($parm_permission,$allowed) = &get_permission();
1.355     albertel 7687:     my $exists = &check_for_course_info();
                   7688: 
1.568     raeburn  7689:     if ($env{'request.course.id'} && $allowed && $exists) {
1.193     albertel 7690:         #
                   7691:         # Main switch on form.action and form.state, as appropriate
                   7692:         #
                   7693:         # Check first if coming from someone else headed directly for
                   7694:         #  the table mode
1.568     raeburn  7695:         if (($parm_permission->{'set'}) && 
                   7696:             ((($env{'form.command'} eq 'set') && ($env{'form.url'})
                   7697:                 && (!$env{'form.dis'})) || ($env{'form.symb'}))) {
                   7698:             &assessparms($r,$parm_permission);
1.193     albertel 7699:         } elsif (! exists($env{'form.action'})) {
                   7700:             &print_main_menu($r,$parm_permission);
1.568     raeburn  7701:         } elsif (!$parm_permission->{$env{'form.action'}}) {
                   7702:             &print_main_menu($r,$parm_permission);
1.414     droeschl 7703:         } elsif ($env{'form.action'} eq 'setoverview') {
1.568     raeburn  7704:             &overview($r,$parm_permission);
1.560     damieng  7705:         } elsif ($env{'form.action'} eq 'addmetadata') {
                   7706:             &addmetafield($r);
                   7707:         } elsif ($env{'form.action'} eq 'ordermetadata') {
                   7708:             &order_meta_fields($r);
1.414     droeschl 7709:         } elsif ($env{'form.action'} eq 'setrestrictmeta') {
1.560     damieng  7710:             &setrestrictmeta($r);
1.414     droeschl 7711:         } elsif ($env{'form.action'} eq 'newoverview') {
1.568     raeburn  7712:             &newoverview($r,$parm_permission);
1.414     droeschl 7713:         } elsif ($env{'form.action'} eq 'setdefaults') {
1.560     damieng  7714:             &defaultsetter($r);
                   7715:         } elsif ($env{'form.action'} eq 'settable') {
1.568     raeburn  7716:             &assessparms($r,$parm_permission);
1.414     droeschl 7717:         } elsif ($env{'form.action'} eq 'parameterchangelog') {
1.568     raeburn  7718:             &parm_change_log($r,$parm_permission);
1.414     droeschl 7719:         } elsif ($env{'form.action'} eq 'cleanparameters') {
1.560     damieng  7720:             &clean_parameters($r);
1.414     droeschl 7721:         } elsif ($env{'form.action'} eq 'dateshift1') {
1.390     www      7722:             &date_shift_one($r);
1.414     droeschl 7723:         } elsif ($env{'form.action'} eq 'dateshift2') {
1.390     www      7724:             &date_shift_two($r);
1.446     bisitz   7725:         }
1.43      albertel 7726:     } else {
1.1       www      7727: # ----------------------------- Not in a course, or not allowed to modify parms
1.560     damieng  7728:         if ($exists) {
                   7729:             $env{'user.error.msg'}=
                   7730:             "/adm/parmset:opa:0:0:Cannot modify assessment parameters";
                   7731:         } else {
                   7732:             $env{'user.error.msg'}=
                   7733:             "/adm/parmset::0:1:Course environment gone, reinitialize the course";
                   7734:         }
                   7735:         return HTTP_NOT_ACCEPTABLE;
1.43      albertel 7736:     }
1.376     albertel 7737:     &reset_caches();
                   7738: 
1.43      albertel 7739:     return OK;
1.1       www      7740: }
                   7741: 
                   7742: 1;
                   7743: __END__
                   7744: 
                   7745: 

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