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

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

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