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

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

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